CNSRE / ABTestingGateway

MIT License
2.36k stars 768 forks source link

基于动态策略的灰度发布系统

在以往的基于 nginx 实现的灰度系统中,分流逻辑往往通过 rewrite 阶段的 if 和 rewrite 指令等实现,优点是性能较高,缺点是功能受限容易出错,以及转发规则固定,只能静态分流。针对这些缺点,我们设计实现了ABTestingGateway,采用 ngx-lua 实现系统功能,通过启用lua-shared-dictlua-resty-lock作为系统缓存和缓存锁,系统获得了较为接近原生nginx转发的性能。

ABTestingGateway 的架构简图

如果在使用过程中有任何问题,欢迎大家来吐槽,一起完善、一起提高、一起使用!

email: bg2bkk@gmail.com open.hfc@gmail.com

压测数据:压测报告

项目演讲:演讲文档

Features:

灰度发布系统功能简介

对于ab管理功能而言,步骤是以下三步:

  1. 向系统添加策略,将策略写入策略数据库中
  2. 为具体的server设置运行时信息,将某个分流策略设置为运行时策略
  3. 之后可以进行分流操作

详细解释参见: ab分流功能须知

对于ab分流功能而言,分流流程图如图所示

分流过程流程图

系统部署

软件依赖

注意:建议选用openresty最新版,但是从openresty-1.9.15.1开始,lua-resty-core有些api变更,因此建议先使用openresty-1.9.7.5,原因是:必读

注意:tengine用户仍然可以使用本项目,只需要从openresty软件包中获取最新的ngx_lua、LuaJIT以及lua-cjson等,并注意:必读

how to start

repo中的utils/conf文件夹中有灰度系统部署所需的最小示例

目前repo的master分支是支持多级分流的版本,如果只想体验单级分流,可以fork single_diversion_release分支,具体文档都在相关分支的readme中。

1. git clone https://github.com/SinaMSRE/ABTestingGateway
2. cd /path/to/ABTestingGateway/utils && mkdir logs

# 启动redis数据库
3. redis-server conf/redis.conf 

# 启动upstream server,其中stable为默认upstream
4. /usr/local/nginx/sbin/nginx -p `pwd` -c conf/stable.conf
5. /usr/local/nginx/sbin/nginx -p `pwd` -c conf/beta1.conf
6. /usr/local/nginx/sbin/nginx -p `pwd` -c conf/beta2.conf
7. /usr/local/nginx/sbin/nginx -p `pwd` -c conf/beta3.conf
8. /usr/local/nginx/sbin/nginx -p `pwd` -c conf/beta4.conf

# 启动灰度系统,proxy server,灰度系统的配置也写在conf/nginx.conf中
9. /usr/local/nginx/sbin/nginx -p `pwd` -c conf/nginx.conf

# 简单验证:添加分流策略组
$ curl 127.0.0.1:8080/ab_admin?action=policygroup_set -d '{"1":{"divtype":"uidsuffix","divdata":[{"suffix":"1","upstream":"beta1"},{"suffix":"3","upstream":"beta2"},{"suffix":"5","upstream":"beta1"},{"suffix":"0","upstream":"beta3"}]},"2":{"divtype":"arg_city","divdata":[{"city":"BJ","upstream":"beta1"},{"city":"SH","upstream":"beta2"},{"city":"XA","upstream":"beta1"},{"city":"HZ","upstream":"beta3"}]},"3":{"divtype":"iprange","divdata":[{"range":{"start":1111,"end":2222},"upstream":"beta1"},{"range":{"start":3333,"end":4444},"upstream":"beta2"},{"range":{"start":7777,"end":2130706433},"upstream":"beta2"}]}}'

{"desc":"success ","code":200,"data":{"groupid":0,"group":[0,1,2]}}

# 简单验证:设置运行时策略

$ curl "127.0.0.1:8080/ab_admin?action=runtime_set&hostname=api.weibo.cn&policygroupid=0"

# 分流
$ curl 127.0.0.1:8030 -H 'X-Uid:39' -H 'X-Real-IP:192.168.1.1'
this is stable server

$ curl 127.0.0.1:8030 -H 'X-Uid:30' -H 'X-Real-IP:192.168.1.1'
this is beta3 server

$ curl 127.0.0.1:8030/?city=BJ -H 'X-Uid:39' -H 'X-Real-IP:192.168.1.1'
this is beta1 server

配置过程

nginx.conf配置过程

redis.conf配置过程

系统使用

ab分流策略

ab分流策略格式和样例

ab功能接口

    * 策略管理:增删改查
    /ab_admin?action=policy_check
    /ab_admin?action=policy_set
    /ab_admin?action=policy_get
    /ab_admin?action=policy_del

    * 策略组管理(用于多级分流)
    /ab_admin?action=policygroup_check
    /ab_admin?action=policygroup_set
    /ab_admin?action=policygroup_get
    /ab_admin?action=policygroup_del

    * 运行时信息管理
        * 其中runtime_set接受policyid和policygroupid参数,分别用于单级分流和多级分流

    /ab_admin?action=runtime_get
    /ab_admin?action=runtime_set
    /ab_admin?action=runtime_del

压测结果:

压测环境下灰度系统与原生nginx转发的对比图

压测环境下灰度系统与原生nginx转发的数据对比

如图所示,用户请求完全命中cache是理想中的情况,灰度系统在理想情况下可以达到十分接近原生nginx转发的性能。

产生图中压测结果的场景是:用户请求经过proxy server转向upstream server,访问1KB大小的静态文件。

proxy server的硬件配置:

线上部署简图:

FAQ

TODO LIST


local dict = ngx.shared.ngxdb
-----------------------------------

local db_tab = "db_tab"
local k_tab = {["a"]=1, ["b"]=2}
local v_tab = {1, 2, 3}

dict:set(db_tab, k_tab, v_tab)

local v_tab = dict:get(db_tab, k_tab)
-----------------------------------

local db_kv = "db_kv"
local k = "foo"
local v = "bar"

dict:set(db_kv, k, v)

local getv = dict:get(db_kv, v)
-----------------------------------