灰度发布
灰度发布在新版本上线的时候,只对线上一小部分用户开放新版本权限,大部分用户访问旧的版本,等新版本持续测试稳定后,将全部用户引入新版本。
灰度网关
创建项目
1 | ~]# mkdir gray |
2 | ~]# cd gray |
3 | ~]# mkdir conf logs lua |
创建nginx.conf
1 | ~]# vim conf/nginx.conf |
2 | worker_processes auto; |
3 | events { |
4 | worker_connections 10240; |
5 | use epoll; |
6 | } |
7 |
|
8 | http { |
9 | upstream pre { |
10 | server 127.0.0.1:80; |
11 | balancer_by_lua_file lua/balancer_pre.lua; |
12 | } |
13 |
|
14 | upstream prod { |
15 | server 127.0.0.1:80; |
16 | balancer_by_lua_file lua/balancer_prod.lua; |
17 | } |
18 |
|
19 | server { |
20 | listen 80; |
21 | server_name _; |
22 | location / { |
23 | access_by_lua_file lua/access.lua; |
24 | content_by_lua_file lua/gray.lua; |
25 | } |
26 |
|
27 | location @pre { |
28 | proxy_pass http://pre; |
29 | } |
30 |
|
31 | location @prod { |
32 | proxy_pass http://prod; |
33 | } |
34 | } |
35 | } |
安装redis模块
1 | # 搜索redis模块 |
2 | opm search redis |
3 |
|
4 | # 安装redis模块 |
5 | opm install openresty/lua-resty-redis |
6 |
|
7 | # 安装redis服务 |
8 | yum install redis |
1 | local redis_ip = "127.0.0.1" |
2 | local redis_port = 6379 |
3 | local redis = require "resty.redis" |
4 | local cjson = require "cjson" |
5 | local rds = redis:new() |
6 | rds:set_timeout(1000) |
7 | local ip = ngx.var.remote_addr |
8 |
|
9 | local ok, err = rds:connect(redis_ip, redis_port) |
10 | if not ok then |
11 | ngx.say("fail to connect: ", err) |
12 | return |
13 | end |
14 |
|
15 | local res, err = rds:lrange('gray', 0, -1) |
16 | if string.find(cjson.encode(res), ip) == nil then |
17 | ngx.exec('@prod') |
18 | else |
19 | ngx.exec("@pre") |
20 | end |
21 |
|
22 | local ok, err = rds:close() |
写入redis的gray的列表数据ip允许访问新的上线版本
1 | ~]# redis-cli |
2 | 127.0.0.1:6379> LPUSH gray "192.168.1.1" |
3 | (integer) 1 |
4 | 127.0.0.1:6379> LPUSH gray "192.168.1.3" |
5 | (integer) 2 |
6 | 127.0.0.1:6379> LRANGE gray 0 -1 |
7 | 1) "192.168.1.3" |
8 | 2) "192.168.1.1" |
1 | local redis_ip = "127.0.0.1" |
2 | local redis_port = 6379 |
3 | local redis = require "resty.redis" |
4 | local rds = redis:new() |
5 | rds:set_timeout(1000) |
6 |
|
7 | local ok, err = rds:connect(redis_ip, redis_port) |
8 | if not ok then |
9 | ngx.say("fail to connect: ", err) |
10 | return |
11 | end |
12 |
|
13 | local res, err = rds:lrange('pre', 0, -1) |
14 | ngx.ctx.pre = res |
15 |
|
16 | local res, err = rds:lrange('prod', 0, -1) |
17 | ngx.ctx.prod = res |
写入redis的pre的列表数据ip是新版本的后端服务
1 | ~]# redis-cli |
2 | 127.0.0.1:6379> LPUSH pre "192.168.2.1" |
3 | (integer) 1 |
4 | 127.0.0.1:6379> LPUSH pre "192.168.2.3" |
5 | (integer) 2 |
6 | 127.0.0.1:6379> LRANGE pre 0 -1 |
7 | 1) "192.168.2.3" |
8 | 2) "192.168.2.1" |
写入redis的pre的列表数据ip是旧版本的后端服务
1 | ~]# redis-cli |
2 | 127.0.0.1:6379> LPUSH prod "192.168.3.1" |
3 | (integer) 1 |
4 | 127.0.0.1:6379> LPUSH prod "192.168.3.3" |
5 | (integer) 2 |
6 | 127.0.0.1:6379> LRANGE prod 0 -1 |
7 | 1) "192.168.3.3" |
8 | 2) "192.168.3.1" |
1 | local balancer = require "ngx.balancer" |
2 | balancer.set_timeouts(1, 1, 1) |
3 | balancer.set_more_tries(2) |
4 |
|
5 | local n = math.random(#ngx.ctx.pre) |
6 |
|
7 | local ok, err = balancer.set_current_peer( |
8 | ngx.ctx.pre[n], 80 |
9 | ) |
10 | if not ok then |
11 | ngx.log(ngx.ERR, "pre failed to set peer: ", err) |
12 | return ngx.exit(500) |
13 | end |
1 | local balancer = require "ngx.balancer" |
2 | balancer.set_timeouts(1, 1, 1) |
3 | balancer.set_more_tries(2) |
4 |
|
5 | local n = math.random(#ngx.ctx.prod) |
6 |
|
7 | local ok, err = balancer.set_current_peer( |
8 | ngx.ctx.prod[n], 80 |
9 | ) |
10 | if not ok then |
11 | ngx.log(ngx.ERR, "prod failed to set peer: ", err) |
12 | return ngx.exit(500) |
13 | end |