Nginx实战灰度发布
灰度发布,就是根据各种条件,让一部分用户使用旧版本,另一部分用户使用新版本,而并不是直接将所有流量切过来,测试人员对新版本做运行状态观察,收集各种运行时数据,也就是所谓的A/B测试,如果没有问题,那么可以将少量的用户流量导入到新版本上,将负面影响控制在最小范围内。
# 灰度发布类型
依据实现终端不同,我认为灰度发布可以分为两类:
- 客户端灰度:客户端依据特殊条件,例如用户ID/IP等条件实现分流
- 服务端灰度:依托Web服务器反向代理或者编码,对不同IP/用户ID等条件实现分流
# 实践
这里我们主要讨论服务段灰度发布,我们依托Openresty(Nginx+Lua)+Redis来实现灰度发布,原理如下图:
执行过程:
- 当用户请求到达前端web(代理)服务器Openresty,内嵌的lua模块解析Nginx配置文件中的lua脚本代码;
- Lua获取客户端IP地址,去查询Redis中是否有该键值,如果有返回值执行@clien2,否则执行@client1;
- Location @client2把请求转发给预发布服务器,location @client1把请求转发给生产服务器,服务器返回结果,整个过程完成;
Openresty配置如下:
upstream client1 {
server 127.0.0.1:8080; #模拟生产服务器
}
upstream client2 {
server 127.0.0.1:8090; #模拟预发布服务器
}
server {
listen 80;
server_name localhost;
location ^~ /test {
content_by_lua_file ab.lua
}
location @client1{
proxy_pass http://client1;
}
location @client2{
proxy_pass http://client2;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ab.lua代码实现如下:
local redis = require "resty.redis"
local cache = redis.new()
cache:set_timeout(60000)
local ok, err = cache.connect(cache, '127.0.0.1', 6379)
if not ok then
ngx.say("failed to connect:", err)
return
end
local local_ip = ngx.req.get_headers()["X-Real-IP"]
if local_ip == nil then
local_ip = ngx.req.get_headers()["x_forwarded_for"]
end
if local_ip == nil then
local_ip = ngx.var.remote_addr
end
--ngx.say("local_ip is : ", local_ip)
local intercept = cache:get(local_ip)
if intercept == local_ip then
ngx.exec("@client2")
return
end
ngx.exec("@client1")
local ok, err = cache:close()
if not ok then
ngx.say("failed to close:", err)
return
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
到此最基本的灰度发布已经实现,如果要做更细粒度灰度发布可参考新浪开源的一个动态路由系统考ABTestingGateway
项目。ABTestingGateway是一个可以动态设置分流策略的灰度发布系统,工作在7层,基于nginx和ngx-lua开发,使用redis作为分流策略数据库,可以实现动态调度功能。
ABTestingGateway:https://github.com/CNSRE/ABTestingGateway
上次更新: 2022/12/01, 11:09:34