本文作者:曹磊,碧桂園服務(wù)技術(shù)經(jīng)理,一個(gè)喜歡研究新技術(shù)方向的代碼玩家

引言
在日常發(fā)布中,如何保證系統(tǒng)的高可用及穩(wěn)定性,是我們始終以來(lái)的重要任務(wù)。我們深知一個(gè)可靠、高效的系統(tǒng)對(duì)用戶體驗(yàn)和業(yè)務(wù)運(yùn)行的關(guān)鍵性作用。
在軟件發(fā)布與功能驗(yàn)證的環(huán)節(jié),我們?nèi)匀粫?huì)面臨許許多多的挑戰(zhàn),全鏈路灰度發(fā)布方案專為微服務(wù)架構(gòu)設(shè)計(jì),旨在應(yīng)對(duì)微服務(wù)架構(gòu)下的灰度發(fā)布挑戰(zhàn)。
1?前版本發(fā)布策略的現(xiàn)狀及存在的問(wèn)題
目前,大部分系統(tǒng)都是應(yīng)用了基于k8s容器的滾動(dòng)發(fā)布方案,或者在滾動(dòng)發(fā)布的邏輯上,實(shí)現(xiàn)了優(yōu)雅停機(jī)的邏輯。

1.1 現(xiàn)狀
優(yōu)雅停服1個(gè)節(jié)點(diǎn),保留其他節(jié)點(diǎn)依然提供生產(chǎn)服務(wù);
通過(guò)日志,觀察一段時(shí)間,看新的節(jié)點(diǎn)是否運(yùn)行正常。如果不正常,就回滾版本;
如果運(yùn)行正常,繼續(xù)1、2的步驟,一直到所有節(jié)點(diǎn)部署完成;
測(cè)試人員上生產(chǎn)做基本驗(yàn)證。
1.2 存在問(wèn)題
不能有效的控制灰度流量,導(dǎo)致測(cè)試人員要全部節(jié)點(diǎn)部署完,才可以做生產(chǎn)驗(yàn)證;
目前的滾動(dòng)發(fā)布邏輯,無(wú)法做到增量更新,一旦新版本出了問(wèn)題,肯定會(huì)影響到生產(chǎn)的運(yùn)行;
難以實(shí)現(xiàn)全天候平滑穩(wěn)定的發(fā)版;
如果版本發(fā)布涉及不同服務(wù)之間的依賴關(guān)系,或者前后端都需要調(diào)整,當(dāng)前策略無(wú)法一步到位滿足全鏈路灰度測(cè)試場(chǎng)景。
2?業(yè)界常用的軟件發(fā)布策略對(duì)比

3 什么是灰度發(fā)布?為什么需要采用灰度發(fā)布?
3.1 什么是灰度發(fā)布?
灰度發(fā)布,簡(jiǎn)單來(lái)說(shuō)就是先小范圍進(jìn)行版本發(fā)布,充分驗(yàn)證功能符合預(yù)期后,再逐步擴(kuò)大發(fā)布范圍。如果出現(xiàn)負(fù)面反饋或功能異常時(shí),則需要停止放量,回滾到原先的穩(wěn)定版本。
從技術(shù)上來(lái)說(shuō),灰度發(fā)布是一種流量控制方案,對(duì)服務(wù)的請(qǐng)求流量按用戶或者其它特性打標(biāo)簽,保證特定標(biāo)簽的流量只經(jīng)過(guò)特定標(biāo)簽的服務(wù)路徑。
3.2 為什么采用灰度發(fā)布?

1、降低發(fā)布風(fēng)險(xiǎn)
在新版本發(fā)布之前,通過(guò)灰度發(fā)布把新版本先部署到一小部分用戶,以便能更快地發(fā)現(xiàn)并解決潛在的問(wèn)題。
2、提高發(fā)布質(zhì)量
因?yàn)樵诨叶劝l(fā)布期間可以及時(shí)發(fā)現(xiàn)和解決問(wèn)題,所以能夠在全量發(fā)布之前不斷完善代碼質(zhì)量,提高系統(tǒng)穩(wěn)定性和可靠性。
3、優(yōu)化用戶體驗(yàn)
在灰度發(fā)布期間,我們可以根據(jù)用戶反饋來(lái)針對(duì)性地優(yōu)化產(chǎn)品功能和界面,確保用戶使用的體驗(yàn)最佳。
4、降低對(duì)系統(tǒng)性能的影響
由于灰度發(fā)布只向部分用戶發(fā)布新版本,所以能夠限制新版本對(duì)整個(gè)系統(tǒng)的影響。
4?全鏈路灰度發(fā)布的實(shí)現(xiàn)思路
全鏈路流量路由目前有兩種主流實(shí)現(xiàn):
1、基于 Istio
采用 Istio 這個(gè)開(kāi)源 Service Mesh 組件,通過(guò)在每個(gè)服務(wù)的容器中部署 Envoy 透明代理,攔截服務(wù)之間的網(wǎng)絡(luò)通信并按指定規(guī)則轉(zhuǎn)發(fā),從而實(shí)現(xiàn)了全鏈路流量路由,無(wú)需對(duì)現(xiàn)有代碼進(jìn)行修改。
2、基于服務(wù)發(fā)現(xiàn)組件
通過(guò)支持為服務(wù)設(shè)置元數(shù)據(jù)的服務(wù)注冊(cè)中心,如 Nacos,可以標(biāo)記服務(wù)實(shí)例的特征,例如灰度版本。每個(gè)服務(wù)可以通過(guò)注冊(cè)中心獲取其他服務(wù)實(shí)例的版本信息,并通過(guò)修改代碼邏輯或 Java Agent 實(shí)現(xiàn)流量路由
接下來(lái),我們?cè)敿?xì)來(lái)講基于服務(wù)發(fā)現(xiàn)組件來(lái)實(shí)現(xiàn)灰度發(fā)布邏輯的方案。
5?灰度發(fā)布邏輯工程實(shí)踐
5.1 灰度鏈路流程圖

5.2?后端代碼改造
代碼改造原理是通過(guò)Spring Cloud的默認(rèn)負(fù)載均衡器LoadBalancer,結(jié)合nacos提供的注冊(cè)中心和配置中心,實(shí)現(xiàn)基于微服務(wù)網(wǎng)關(guān)調(diào)用和服務(wù)間OpenFeign調(diào)用的生產(chǎn)和灰度隔離。
以下代碼是以Loadbalancer為例,擴(kuò)展的灰度邏輯,如果目前系統(tǒng)基于Ribbon,可以考慮使用Loadbalancer替換掉Ribbon,也可以直接基于Ribbon定義自己的灰度負(fù)載均衡邏輯,實(shí)現(xiàn)方法在本文中不做詳細(xì)描述。
步驟1:指定灰度啟動(dòng)節(jié)點(diǎn)
指定灰度節(jié)點(diǎn)與生產(chǎn)節(jié)點(diǎn),用于負(fù)載均衡器按規(guī)則選擇不同的鏈路,用于區(qū)別流量,建設(shè)jenkins部署腳本時(shí),設(shè)置在啟動(dòng)項(xiàng)里面。

步驟2:灰度負(fù)載均衡邏輯的實(shí)現(xiàn)
Spring Cloud的負(fù)載均衡邏輯,無(wú)論負(fù)載均衡器是LoadBalancer或者是Ribbon,默認(rèn)邏輯都是輪循邏輯,可以保證每一個(gè)上線節(jié)點(diǎn)瀏量的平均分配,但是無(wú)法保證灰度策略的實(shí)現(xiàn),因此,必須得重新定義新的負(fù)載均衡邏輯。?



步驟3:開(kāi)啟灰度負(fù)載均衡策略

步驟4:Feign服務(wù)調(diào)用
注意,feign調(diào)用需要定義一個(gè)默認(rèn)攔截器,將請(qǐng)求中的灰度標(biāo)識(shí)繼續(xù)往下傳,另外,除此之外,調(diào)用的服務(wù)模塊啟動(dòng)的時(shí)候,仍然需要在啟動(dòng)項(xiàng)上,添加開(kāi)啟灰度負(fù)載均衡代碼,如上圖。
5.3?前臺(tái)灰度發(fā)布邏輯改造
前臺(tái)灰度發(fā)布無(wú)需涉及到前臺(tái)代碼的改造,基于ingress/nginx,通過(guò)對(duì)于Cookies的指定參數(shù)進(jìn)行判斷,判斷是否訪問(wèn)灰度節(jié)點(diǎn)或者生產(chǎn)節(jié)點(diǎn),所以,仍然只需要在登錄的時(shí)候,判斷一下當(dāng)前登錄用戶的穩(wěn)定標(biāo)識(shí),進(jìn)行是否需要進(jìn)行灰度驗(yàn)證。

5.4?網(wǎng)關(guān)節(jié)點(diǎn)如何灰度發(fā)布?

以上后端服務(wù)各個(gè)節(jié)點(diǎn)的灰度方案,基本上都是基于負(fù)載均衡規(guī)則改寫(xiě)得以實(shí)現(xiàn),對(duì)于網(wǎng)關(guān)節(jié)點(diǎn)的負(fù)載改造,其實(shí)也是類似于前臺(tái)灰度發(fā)布邏輯,通過(guò)ingress/nginx得以實(shí)現(xiàn),我們只需要在請(qǐng)求頭中帶上灰度節(jié)點(diǎn)標(biāo)識(shí),就可以請(qǐng)求到灰度網(wǎng)關(guān)節(jié)點(diǎn),完成功能性驗(yàn)證。
6 成果展示
全鏈路灰度發(fā)布方案自創(chuàng)新部門應(yīng)用并實(shí)施以來(lái),首批試點(diǎn)項(xiàng)目(API能力共享平臺(tái),數(shù)據(jù)交換總線)已經(jīng)完成改造,對(duì)業(yè)務(wù)產(chǎn)生了積極的促進(jìn)作用,為A/B測(cè)試打下堅(jiān)實(shí)的技術(shù)底座:
①可全天候?qū)崿F(xiàn)系統(tǒng)用戶零感知平滑升級(jí)。

②可以實(shí)現(xiàn)前后端一起發(fā)布驗(yàn)證,可以動(dòng)態(tài)擴(kuò)大灰度范圍。
③可以極大的減少線上事故率,保證系統(tǒng)的穩(wěn)定性與高可用,提升用戶體驗(yàn)。
7 總結(jié)

灰度發(fā)布是一種有效的軟件發(fā)布策略,能夠在保證系統(tǒng)穩(wěn)定性的同時(shí),提高軟件的質(zhì)量和可靠性。通過(guò)逐步擴(kuò)大新版本服務(wù)的流量,實(shí)現(xiàn)平滑升級(jí)和容錯(cuò)處理,微服務(wù)灰度發(fā)布設(shè)計(jì)為現(xiàn)代軟件開(kāi)發(fā)帶來(lái)了諸多優(yōu)勢(shì)。然而,也需要注意其可能帶來(lái)的性能下降、復(fù)雜性和開(kāi)發(fā)成本增加等挑戰(zhàn)。
在進(jìn)行微服務(wù)灰度發(fā)布設(shè)計(jì)時(shí),需要充分考慮實(shí)際業(yè)務(wù)需求和應(yīng)用場(chǎng)景,制定合適的發(fā)布策略,并對(duì)潛在的風(fēng)險(xiǎn)進(jìn)行有效控制。