新浪的动态策略灰度发布系统:ABTestingGateway

ABTesingGateway 是一个可以动态设置分流策略的灰度发布系统,工作在7层,基于tengine,采用ngx-lua开发,使用 redis 作为分流策略数据库,可以实现动态调度功能。

nginx是目前使用较多的7层服务器,可以实现高性能的转发和响应;ABTestingGateway 是在 nginx 转发的框架内,在转向 upstream 前,根据 用户请求特征 和 系统的分流策略 ,查找出目标upstream,进而实现分流。

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




ABTesingGateway 的架构简图

Features:

支持多种分流方式,目前包括iprange、uidrange、uid尾数和指定uid分流

动态设置分流策略,即时生效,无需重启

可扩展性,提供了开发框架,开发者可以灵活添加新的分流方式,实现二次开发

高性能,压测数据接近原生nginx转发

灰度系统配置写在nginx配置文件中,方便管理员配置

适用于多种场景:灰度发布、AB测试和负载均衡等

系统实现

分流功能:

转发分流是灰度系统的主要功能,目前 ABTesingGateway 支持ip段分流(iprange)、uid用户段分流(uidrange)、uid尾数分流(uidsuffix)和指定特殊uid分流(uidappoint)四种方式。

ABTesingGateway 依据系统中配置的运行时信息runtimeInfo进行分流工作;通过将 runtimeInfo 设置为不同的分流策略,实现运行时分流策略的动态更新,达到动态调度的目的。

系统运行时信息设置

如图所示

系统管理员通过系统管理接口将分流策略policy设置为运行时策略,并指定该策略对应的分流模块名divModulename和用户信息提取模块名userInfoModulename后,系统可以进行分流工作。

系统对用户请求进行分流时,首先获得系统运行时信息runtimeInfo中的信息,然后提取用户特征userInfo,最后分流模块divModule根据分流策略dviDataKey和用户特征userInfo查找出应该转发到的upstream。如果没有对应的upstream,则将该请求转向默认upstream。

以iprange分流为例

1

2

3

4

5

6

7

8

9

以某个iprange分流策略为例:

    {

        "divtype":"iprange",

        "divdata":[

                    {"range":{"start":1111, "end":2222}, "upstream":"beta1"},

                    {"range":{"start":3333, "end":4444}, "upstream":"beta2"},

                    {"range":{"start":7777, "end":8888}, "upstream":"beta3"}

                  ]

    }

其中divdata中的每个 range:upstream 对中,range 为 ip 段,upstream 为 ip 段对应的后端;range 中的 start 和 end 分别为 ip 段的起始和终止, ip以整型表示。 当灰度系统启用iprange分流方式时,会根据用户请求的ip进行分流转发。 假如用户请求中的ip信息转为整型后是4000,将被转发至beta2 upstream。

分流过程流程图

分流过程流程图

管理功能:

管理功能架构图

1. 管理员登入后,得到系统信息视图,运行时信息视图,可以进行策略管理和运行时信息管理

2. 业务接口层向管理员提供  增/删/查/改  接口

3. 适配层将承担业务接口与分流模块的沟通工作

4. 适配层提出统一接口,开发人员可以通过实现接口来添加新的分流方式

管理接口:

[策略管理接口]    

    #分流策略检查,参数为一个分流策略数据的json串

    1. /admin/policy/check

    #分流策略添加,参数与check接口一致

    2. /admin/policy/set

    #分流策略读取,参数为要读取策略的policyid

    3. /admin/policy/get

    #分流策略删除,参数为要删除策略的policyid

    4. /admin/policy/del

[运行时信息管理接口]

    #设置分流策略为运行时策略,参数为policyid

    1. /admin/runtime/set

    #获取系统当前运行时信息,无参数

    2. /admin/runtime/get

    #删除系统运行时信息,关闭分流接口,无参数

    3. /admin/runtime/del

快速部署

软件依赖

tengine-2.1.0

LuaJIT-2.1-20141128

ngx_lua-0.9.13

lua-cjson-2.1.0.2

redis-2.8.19

系统部署

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

1. git clone https://github.com/SinaMSRE/ABTestingGateway

2. cd /path/to/ABTestingGateway/utils

#启动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

灰度系统使用demo

管理功能

1. 部署并启动系统

2. 查询系统运行时信息,得到null

0> curl 127.0.0.1:8030/admin/runtime/get

{"errcode":200,"errinfo":"success ","data":{"divModulename":null,"divDataKey":null,"userInfoModulename":null}}

3. 查询id为9的策略,得到null

0> curl 127.0.0.1:8030/admin/policy/get?policyid=9

{"errcode":200,"errinfo":"success ","data":{"divdata":null,"divtype":null}}

4. 向系统添加策略,返回成功,并返回新添加策略的policyid

       以uidsuffix尾数分流方式为例,示例分流策略为:

            {

                "divtype":"uidsuffix",

                "divdata":[

                            {"suffix":"1", "upstream":"beta1"},

                            {"suffix":"3", "upstream":"beta2"},

                            {"suffix":"5", "upstream":"beta1"},

                            {"suffix":"0", "upstream":"beta3"}

                          ]

            }

添加分流策略接口 /admin/policy/set 接受json化的policy数据

0> curl 127.0.0.1:8030/admin/policy/set -d '{"divtype":"uidsuffix","divdata":[{"suffix":"1","upstream":"beta1"},{"suffix":"3","upstream":"beta2"},{"suffix":"5","upstream":"beta1"},{"suffix":"0","upstream":"beta3"}]}'

{"errcode":200,"errinfo":"success  the id of new policy is 0"}

5. 查看添加结果

0> curl 127.0.0.1:8030/admin/policy/get?policyid=0

{"errcode":200,"errinfo":"success ","data":{"divdata":["1","beta1","3","beta2","5","beta1","0","beta3"],"divtype":"uidsuffix"}}

6. 设置系统运行时策略为 0号策略

0> curl 127.0.0.1:8030/admin/runtime/set?policyid=0

{"errcode":200,"errinfo":"success "}

7. 查看系统运行时信息,得到结果

0> curl 127.0.0.1:8030/admin/runtime/get

{"errcode":200,"errinfo":"success ","data":{"divModulename":"abtesting.diversion.uidsuffix","divDataKey":"ab:test:policies:0:divdata","userInfoModulename":"abtesting.userinfo.uidParser"}}

8. 当访问接口不正确返回时,将返回相应的 错误码 和 错误描述信息

0> curl 127.0.0.1:8030/admin/policy/get?policyid=abc

{"errcode":50104,"errinfo":"parameter type error for policyID should be a positive Integer"}

分流功能

在验证管理功能通过,并设置系统运行时策略后,开始验证分流功能

1. 分流,不带用户uid,转发至默认upstream

0> curl 127.0.0.1:8030/

this is stable server

2. 分流,带uid为30,根据策略,转发至beta3

0> curl 127.0.0.1:8030/  -H 'X-Uid:30'

this is beta3 server

3. 分流,带uid为33,根据策略,转发至beta2

0> curl 127.0.0.1:8030/  -H 'X-Uid:33'

this is beta2 server

压测结果:

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

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

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

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

proxy server的硬件配置:

CPU:E5620 2.4GHz 16核

Mem:24GB

Nic:千兆网卡,多队列

线上部署简图:

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容