ABTesingGateway 是一個(gè)可以動(dòng)態(tài)設(shè)置分流策略的灰度發(fā)布系統(tǒng),工作在7層,基于tengine,采用ngx-lua開發(fā),使用 redis 作為分流策略數(shù)據(jù)庫(kù),可以實(shí)現(xiàn)動(dòng)態(tài)調(diào)度功能。
nginx是目前使用較多的7層服務(wù)器,可以實(shí)現(xiàn)高性能的轉(zhuǎn)發(fā)和響應(yīng);ABTestingGateway 是在 nginx 轉(zhuǎn)發(fā)的框架內(nèi),在轉(zhuǎn)向 upstream 前,根據(jù) 用戶請(qǐng)求特征 和 系統(tǒng)的分流策略 ,查找出目標(biāo)upstream,進(jìn)而實(shí)現(xiàn)分流。
在以往的基于 nginx 實(shí)現(xiàn)的灰度系統(tǒng)中,分流邏輯往往通過(guò) rewrite 階段的 if 和 rewrite 指令等實(shí)現(xiàn),優(yōu)點(diǎn)是性能較高,缺點(diǎn)是功能受限、容易出錯(cuò),以及轉(zhuǎn)發(fā)規(guī)則固定,只能靜態(tài)分流。針對(duì)這些缺點(diǎn),我們?cè)O(shè)計(jì)實(shí)現(xiàn)了ABTesingGateway,采用 ngx-lua 實(shí)現(xiàn)系統(tǒng)功能,通過(guò)啟用lua-shared-dict和lua-resty-lock作為系統(tǒng)緩存和緩存鎖,系統(tǒng)獲得了較為接近原生nginx轉(zhuǎn)發(fā)的性能。

ABTesingGateway 的架構(gòu)簡(jiǎn)圖
Features:
支持多種分流方式,目前包括iprange、uidrange、uid尾數(shù)和指定uid分流
動(dòng)態(tài)設(shè)置分流策略,即時(shí)生效,無(wú)需重啟
可擴(kuò)展性,提供了開發(fā)框架,開發(fā)者可以靈活添加新的分流方式,實(shí)現(xiàn)二次開發(fā)
高性能,壓測(cè)數(shù)據(jù)接近原生nginx轉(zhuǎn)發(fā)
灰度系統(tǒng)配置寫在nginx配置文件中,方便管理員配置
適用于多種場(chǎng)景:灰度發(fā)布、AB測(cè)試和負(fù)載均衡等
系統(tǒng)實(shí)現(xiàn)
分流功能:
轉(zhuǎn)發(fā)分流是灰度系統(tǒng)的主要功能,目前 ABTesingGateway 支持ip段分流(iprange)、uid用戶段分流(uidrange)、uid尾數(shù)分流(uidsuffix)和指定特殊uid分流(uidappoint)四種方式。
ABTesingGateway 依據(jù)系統(tǒng)中配置的運(yùn)行時(shí)信息runtimeInfo進(jìn)行分流工作;通過(guò)將 runtimeInfo 設(shè)置為不同的分流策略,實(shí)現(xiàn)運(yùn)行時(shí)分流策略的動(dòng)態(tài)更新,達(dá)到動(dòng)態(tài)調(diào)度的目的。
系統(tǒng)運(yùn)行時(shí)信息設(shè)置

如圖所示
系統(tǒng)管理員通過(guò)系統(tǒng)管理接口將分流策略policy設(shè)置為運(yùn)行時(shí)策略,并指定該策略對(duì)應(yīng)的分流模塊名divModulename和用戶信息提取模塊名userInfoModulename后,系統(tǒng)可以進(jìn)行分流工作。
系統(tǒng)對(duì)用戶請(qǐng)求進(jìn)行分流時(shí),首先獲得系統(tǒng)運(yùn)行時(shí)信息runtimeInfo中的信息,然后提取用戶特征userInfo,最后分流模塊divModule根據(jù)分流策略dviDataKey和用戶特征userInfo查找出應(yīng)該轉(zhuǎn)發(fā)到的upstream。如果沒有對(duì)應(yīng)的upstream,則將該請(qǐng)求轉(zhuǎn)向默認(rèn)upstream。
以iprange分流為例
1
2
3
4
5
6
7
8
9
以某個(gè)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中的每個(gè) range:upstream 對(duì)中,range 為 ip 段,upstream 為 ip 段對(duì)應(yīng)的后端;range 中的 start 和 end 分別為 ip 段的起始和終止, ip以整型表示。 當(dāng)灰度系統(tǒng)啟用iprange分流方式時(shí),會(huì)根據(jù)用戶請(qǐng)求的ip進(jìn)行分流轉(zhuǎn)發(fā)。 假如用戶請(qǐng)求中的ip信息轉(zhuǎn)為整型后是4000,將被轉(zhuǎn)發(fā)至beta2 upstream。
分流過(guò)程流程圖

分流過(guò)程流程圖
管理功能:

管理功能架構(gòu)圖
1.?管理員登入后,得到系統(tǒng)信息視圖,運(yùn)行時(shí)信息視圖,可以進(jìn)行策略管理和運(yùn)行時(shí)信息管理
2.?業(yè)務(wù)接口層向管理員提供??增/刪/查/改??接口
3.?適配層將承擔(dān)業(yè)務(wù)接口與分流模塊的溝通工作
4.?適配層提出統(tǒng)一接口,開發(fā)人員可以通過(guò)實(shí)現(xiàn)接口來(lái)添加新的分流方式
管理接口:
[策略管理接口]????
????#分流策略檢查,參數(shù)為一個(gè)分流策略數(shù)據(jù)的json串
????1.?/admin/policy/check
????#分流策略添加,參數(shù)與check接口一致
????2.?/admin/policy/set
????#分流策略讀取,參數(shù)為要讀取策略的policyid
????3.?/admin/policy/get
????#分流策略刪除,參數(shù)為要?jiǎng)h除策略的policyid
????4.?/admin/policy/del
[運(yùn)行時(shí)信息管理接口]
????#設(shè)置分流策略為運(yùn)行時(shí)策略,參數(shù)為policyid
????1.?/admin/runtime/set
????#獲取系統(tǒng)當(dāng)前運(yùn)行時(shí)信息,無(wú)參數(shù)
????2.?/admin/runtime/get
????#刪除系統(tǒng)運(yùn)行時(shí)信息,關(guān)閉分流接口,無(wú)參數(shù)
????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
系統(tǒng)部署
repo中的utils/conf文件夾中有灰度系統(tǒng)部署所需的最小示例
1.?git?clone?https://github.com/SinaMSRE/ABTestingGateway
2.?cd?/path/to/ABTestingGateway/utils
#啟動(dòng)redis數(shù)據(jù)庫(kù)
3.?redis-server?conf/redis.conf?
#啟動(dòng)upstream?server,其中stable為默認(rèn)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
#啟動(dòng)灰度系統(tǒng),proxy?server,灰度系統(tǒng)的配置也寫在conf/nginx.conf中
9.?/usr/local/nginx/sbin/nginx?-p?`pwd`?-c?conf/nginx.conf
灰度系統(tǒng)使用demo
管理功能
1.?部署并啟動(dòng)系統(tǒng)
2.?查詢系統(tǒng)運(yùn)行時(shí)信息,得到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.?向系統(tǒng)添加策略,返回成功,并返回新添加策略的policyid
???????以u(píng)idsuffix尾數(shù)分流方式為例,示例分流策略為:
????????????{
????????????????"divtype":"uidsuffix",
????????????????"divdata":[
????????????????????????????{"suffix":"1",?"upstream":"beta1"},
????????????????????????????{"suffix":"3",?"upstream":"beta2"},
????????????????????????????{"suffix":"5",?"upstream":"beta1"},
????????????????????????????{"suffix":"0",?"upstream":"beta3"}
??????????????????????????]
????????????}
添加分流策略接口?/admin/policy/set?接受json化的policy數(shù)據(jù)
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.?查看添加結(jié)果
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.?設(shè)置系統(tǒng)運(yùn)行時(shí)策略為?0號(hào)策略
0>?curl?127.0.0.1:8030/admin/runtime/set?policyid=0
{"errcode":200,"errinfo":"success?"}
7.?查看系統(tǒng)運(yùn)行時(shí)信息,得到結(jié)果
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.?當(dāng)訪問(wèn)接口不正確返回時(shí),將返回相應(yīng)的?錯(cuò)誤碼?和?錯(cuò)誤描述信息
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"}
分流功能
在驗(yàn)證管理功能通過(guò),并設(shè)置系統(tǒng)運(yùn)行時(shí)策略后,開始驗(yàn)證分流功能
1.?分流,不帶用戶uid,轉(zhuǎn)發(fā)至默認(rèn)upstream
0>?curl?127.0.0.1:8030/
this?is?stable?server
2.?分流,帶uid為30,根據(jù)策略,轉(zhuǎn)發(fā)至beta3
0>?curl?127.0.0.1:8030/??-H?'X-Uid:30'
this?is?beta3?server
3.?分流,帶uid為33,根據(jù)策略,轉(zhuǎn)發(fā)至beta2
0>?curl?127.0.0.1:8030/??-H?'X-Uid:33'
this?is?beta2?server
壓測(cè)結(jié)果:

壓測(cè)環(huán)境下灰度系統(tǒng)與原生nginx轉(zhuǎn)發(fā)的對(duì)比圖

壓測(cè)環(huán)境下灰度系統(tǒng)與原生nginx轉(zhuǎn)發(fā)的數(shù)據(jù)對(duì)比
如圖所示,用戶請(qǐng)求完全命中cache是理想中的情況,灰度系統(tǒng)在理想情況下可以達(dá)到十分接近原生nginx轉(zhuǎn)發(fā)的性能。
產(chǎn)生圖中壓測(cè)結(jié)果的場(chǎng)景是:用戶請(qǐng)求經(jīng)過(guò)proxy server轉(zhuǎn)向upstream server,訪問(wèn)1KB大小的靜態(tài)文件。
proxy server的硬件配置:
CPU:E5620 2.4GHz 16核
Mem:24GB
Nic:千兆網(wǎng)卡,多隊(duì)列
線上部署簡(jiǎn)圖:
