Jusene's Blog

OpenResty 灰度之路探索

字数统计: 766阅读时长: 4 min
2019/09/03 Share

灰度发布

灰度发布在新版本上线的时候,只对线上一小部分用户开放新版本权限,大部分用户访问旧的版本,等新版本持续测试稳定后,将全部用户引入新版本。

灰度网关

  • 创建项目

    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
  • lua/gray.lua
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"
  • lua/access.lua
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"
  • lua/balancer_pre.lua
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
  • lua/balancer_prod.lua
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
CATALOG
  1. 1. 灰度发布
  2. 2. 灰度网关