互聯(lián)網(wǎng)技術(shù)發(fā)展到今天,無(wú)論從開(kāi)發(fā)角度還是從運(yùn)維角度,都需要依靠灰度發(fā)布來(lái)控制版本質(zhì)量、控制影響范圍、搜集用戶反饋等等,在接入層實(shí)現(xiàn)灰度策略是較為常見(jiàn)的一種方法。閑話少說(shuō),下面以haproxy為例說(shuō)明如何在接入層實(shí)現(xiàn)灰度發(fā)布。
一、灰度原則
1.任何脫離應(yīng)用場(chǎng)景的灰度都是耍流氓,所以每個(gè)應(yīng)用的灰度策略需要針對(duì)具體應(yīng)用場(chǎng)景和邏輯進(jìn)行設(shè)計(jì)
2.實(shí)現(xiàn)灰度策略應(yīng)盡可能少的代碼入侵
3.在設(shè)計(jì)編碼階段,提前想好灰度入口,即一個(gè)請(qǐng)求過(guò)來(lái),依據(jù)什么來(lái)判斷是否走原始版本,還是走灰度版本
4.要做到走灰度版本的一直走灰度版本,做到對(duì)用戶透明
二、搭建工作
1.使用idea快速搭建兩個(gè)springboot應(yīng)用,一個(gè)模擬原始版本,一個(gè)模擬灰度版本。兩個(gè)應(yīng)用都較為簡(jiǎn)單,訪問(wèn)/hello后原始版本輸出hello world,灰度版本輸出hello gray
原始版本訪問(wèn)地址:http://127.0.0.1:8081/hello
灰度版本訪問(wèn)地址:http://127.0.0.1:8080/hello
核心代碼截圖如下:


使用postman模擬訪問(wèn)兩個(gè)地址,ok,基礎(chǔ)服務(wù)已經(jīng)搭建完畢


2.啟動(dòng)haproxy,建立frontend和backend灰度策略入口。


3.目前訪問(wèn)haproxy,默認(rèn)會(huì)一直訪問(wèn)原始版本,那么如何根據(jù)制定的策略訪問(wèn)灰度版本呢?我們不妨在header中增加userid參數(shù),設(shè)定當(dāng)userid小于100時(shí),這部分用戶去訪問(wèn)灰度版本,其他的用戶則繼續(xù)訪問(wèn)原始版本,修改haproxy配置如下
在本例中,我們將應(yīng)用的業(yè)務(wù)參數(shù)userid置于請(qǐng)求的header中,haproxy以此進(jìn)行灰度控制。放在header中可以在接入層實(shí)現(xiàn)灰度,而無(wú)需在應(yīng)用層進(jìn)行控制,減少了代碼入侵。同理也可以將灰度策略的入口條件置于請(qǐng)求的cookie中

通過(guò)配置acl規(guī)則,我們從header中提取userid的參數(shù),正則校驗(yàn)符合小于100,則訪問(wèn)hellogray的灰度版本后端,否則就訪問(wèn)helloworld的原始版本后端,重啟haproxy,測(cè)試如下:


3.通過(guò)以上配置,我們已經(jīng)實(shí)現(xiàn)了通過(guò)haproxy灰度的目標(biāo),我們通過(guò)篩選合適的請(qǐng)求,將其分發(fā)至不同的后端上面,但是如何實(shí)現(xiàn)“一灰永灰”呢?即訪問(wèn)灰度版本的客戶一直訪問(wèn)灰度版本,不可以再跳回原始版本。我們先看看目前的訪問(wèn)


我們不難想到,在每個(gè)請(qǐng)求的header中都帶有userid參數(shù),也是一種解決方法,但是這樣對(duì)代碼的入侵過(guò)大,需要在每個(gè)請(qǐng)求中都置userid這個(gè)參數(shù),我們能否做到只在應(yīng)用入口的請(qǐng)求header中增加參數(shù),做到一灰永灰?看看如下配置



三、總結(jié)
通過(guò)以上示例,我們利用haproxy的策略實(shí)現(xiàn)了灰度發(fā)布的目標(biāo),且做到了一灰永灰??偨Y(jié)起來(lái),實(shí)現(xiàn)邏輯為: