當(dāng)服務(wù)有新版本要發(fā)布上線時,通過引流一小部分流量到新版本,可以及時發(fā)現(xiàn)程序問題,有效阻止大面積故障的發(fā)生。業(yè)界上已經(jīng)有比較成熟的服務(wù)發(fā)布策略,比如藍(lán)綠發(fā)布、A/B 測試以及金絲雀發(fā)布,這些發(fā)布策略主要專注于如何對單個服務(wù)進(jìn)行發(fā)布。在微服務(wù)體系架構(gòu)中,服務(wù)之間的依賴關(guān)系錯綜復(fù)雜,有時某個功能發(fā)版依賴多個服務(wù)同時升級上線。我們希望可以對這些服務(wù)的新版本同時進(jìn)行小流量灰度驗證,這就是微服務(wù)架構(gòu)中特有的全鏈路灰度場景,通過構(gòu)建從網(wǎng)關(guān)到整個后端服務(wù)的環(huán)境隔離來對多個不同版本的服務(wù)進(jìn)行灰度驗證。
本文將會揭開全鏈路灰度的神秘面紗,深入剖析全鏈路灰度技術(shù)內(nèi)幕,引出兩種不同的實現(xiàn)方案,并對實現(xiàn)方案的技術(shù)細(xì)節(jié)進(jìn)行深入探討,最后通過實踐環(huán)節(jié)來展示全鏈路灰度在實際業(yè)務(wù)中的使用場景。
01
微服務(wù)架構(gòu)帶來的挑戰(zhàn)
Cloud Native
其中,流量網(wǎng)關(guān)是四層代理,主要功能有負(fù)載均衡、TLS 卸載以及一些安全防護(hù)功能;微服務(wù)網(wǎng)關(guān)是七層代理,主要用來暴露后端服務(wù)、流量治理、訪問控制和流量監(jiān)控。以"高內(nèi)聚、低耦合"作為設(shè)計理念的微服務(wù)架構(gòu)為開發(fā)者帶來了前所未有的開發(fā)體驗,每個業(yè)務(wù)團(tuán)隊專注于自身業(yè)務(wù)的代碼邏輯,并通過 API 形式對外發(fā)布。服務(wù)依賴方只需引入服務(wù)提供方的 API 定義,即可完成服務(wù)之間通信,無需關(guān)心服務(wù)提供方的部署形態(tài)和內(nèi)部實現(xiàn)。
但任何架構(gòu)都不是銀彈,在解決舊問題同時勢必會引入一些新的問題。微服務(wù)體系中最令人頭疼的問題,是如何對眾多微服務(wù)進(jìn)行高效、便捷的治理,主要表現(xiàn)在可見性、連接性和安全性這三個方面。進(jìn)一步細(xì)化,微服務(wù)架構(gòu)帶來了以下的挑戰(zhàn):
本文的重點(diǎn)主要關(guān)注服務(wù)發(fā)布這一子領(lǐng)域,如何保證微服務(wù)體系中服務(wù)新版本升級過程中平滑無損,以及如何低成本的為多個微服務(wù)構(gòu)建流量隔離環(huán)境,方便開發(fā)者同時對多個服務(wù)新版本進(jìn)行充分的灰度驗證,避免故障的發(fā)生。
02
什么是全鏈路灰度
Cloud Native
1
單體架構(gòu)下的服務(wù)發(fā)布
首先,我們先看一下在單體架構(gòu)中,如何對應(yīng)用中某個服務(wù)模塊進(jìn)行新版本發(fā)布。如下圖,應(yīng)用中的 Cart 服務(wù)模塊有新版本迭代:
由于 Cart 服務(wù)是應(yīng)用的一部分,所以新版本上線時需要對整個應(yīng)用進(jìn)行編譯、打包以及部署。服務(wù)級別發(fā)布問題變成了應(yīng)用級別的發(fā)布問題,我們需要對應(yīng)用的新版本而不是服務(wù)來實施有效的發(fā)布策略。
目前,業(yè)界已經(jīng)有非常成熟的服務(wù)發(fā)布方案,例如藍(lán)綠發(fā)布和灰度發(fā)布。藍(lán)綠發(fā)布需要對服務(wù)的新版本進(jìn)行冗余部署,一般新版本的機(jī)器規(guī)格和數(shù)量與舊版本保持一致,相當(dāng)于該服務(wù)有兩套完全相同的部署環(huán)境,只不過此時只有舊版本在對外提供服務(wù),新版本作為熱備。當(dāng)服務(wù)進(jìn)行版本升級時,我們只需將流量全部切換到新版本即可,舊版本作為熱備。我們的例子使用藍(lán)綠發(fā)布的示意圖如下,流量切換基于四層代理的流量網(wǎng)關(guān)即可完成。
在藍(lán)綠發(fā)布中,由于存在流量整體切換,所以需要按照原服務(wù)占用的機(jī)器規(guī)模為新版本克隆一套環(huán)境,相當(dāng)于要求原來1倍的機(jī)器資源?;叶劝l(fā)布的核心思想是根據(jù)請求內(nèi)容或者請求流量的比例將線上流量的一小部分轉(zhuǎn)發(fā)至新版本,待灰度驗證通過后,逐步調(diào)大新版本的請求流量,是一種循序漸進(jìn)的發(fā)布方式。我們的例子使用灰度發(fā)布的示意圖如下,基于內(nèi)容或比例的流量控制需要借助于一個七層代理的微服務(wù)網(wǎng)關(guān)來完成。
其中,Traffic Routing 是基于內(nèi)容的灰度方式,比如請求中含有頭部 stag=gray 的流量路由到應(yīng)用 v2 版本;Traffic Shifting 是基于比例的灰度方式,以無差別的方式對線上流量按比重進(jìn)行分流。相比藍(lán)綠發(fā)布,灰度發(fā)布在機(jī)器資源成本以及流量控制能力上更勝一籌,但缺點(diǎn)就是發(fā)布周期過長,對運(yùn)維基礎(chǔ)設(shè)施要求較高。
2
微服務(wù)架構(gòu)下的服務(wù)發(fā)布
在分布式微服務(wù)架構(gòu)中,應(yīng)用中被拆分出來的子服務(wù)都是獨(dú)立部署、運(yùn)行和迭代的。單個服務(wù)新版本上線時,我們再也不需要對應(yīng)用整體進(jìn)行發(fā)版,只需關(guān)注每個微服務(wù)自身的發(fā)布流程即可,如下:
為了驗證服務(wù) Cart 的新版本,流量在整個調(diào)用鏈路上能夠通過某種方式有選擇的路由到 Cart 的灰度版本,這屬于微服務(wù)治理領(lǐng)域中流量治理問題。常見的治理策略包括基于 Provider 和基于 Consumer 的方式。
-
基于 Provider 的治理策略。配置 Cart 的流量流入規(guī)則,User 路由到 Cart 時使用 Cart 的流量流入規(guī)則。
-
基于 Consumer 的治理策略。配置 User 的流量流出規(guī)則, User 路由到 Cart 時使用 User 的流量流出規(guī)則。
此外,使用這些治理策略時可以結(jié)合上面介紹的藍(lán)綠發(fā)布和灰度發(fā)布方案來實施真正的服務(wù)級別的版本發(fā)布。
3
全鏈路灰度
繼續(xù)考慮上面微服務(wù)體系中對服務(wù) Cart 進(jìn)行發(fā)布的場景,如果此時服務(wù) Order 也需要發(fā)布新版本,由于本次新功能涉及到服務(wù) Cart 和 Order 的共同變動,所以要求在灰度驗證時能夠使得灰度流量同時經(jīng)過服務(wù) Cart 和 Order 的灰度版本。如下圖:
按照上一小節(jié)提出的兩種治理策略,我們需要額外配置服務(wù) Order 的治理規(guī)則,確保來自灰度環(huán)境的服務(wù) Cart 的流量轉(zhuǎn)發(fā)至服務(wù) Order 的灰度版本。這樣的做法看似符合正常的操作邏輯,但在真實業(yè)務(wù)場景中,業(yè)務(wù)的微服務(wù)規(guī)模和數(shù)量遠(yuǎn)超我們的例子,其中一條請求鏈路可能經(jīng)過數(shù)十個微服務(wù),新功能發(fā)布時也可能會涉及到多個微服務(wù)同時變更,并且業(yè)務(wù)的服務(wù)之間依賴錯綜復(fù)雜,頻繁的服務(wù)發(fā)布、以及服務(wù)多版本并行開發(fā)導(dǎo)致流量治理規(guī)則日益膨脹,給整個系統(tǒng)的維護(hù)性和穩(wěn)定性帶來了不利因素。
對于以上的問題,開發(fā)者結(jié)合實際業(yè)務(wù)場景和生產(chǎn)實踐經(jīng)驗,提出了一種端到端的灰度發(fā)布方案,即全鏈路灰度。全鏈路灰度治理策略主要專注于整個調(diào)用鏈,它不關(guān)心鏈路上經(jīng)過具體哪些微服務(wù),流量控制視角從服務(wù)轉(zhuǎn)移至請求鏈路上,僅需要少量的治理規(guī)則即可構(gòu)建出從網(wǎng)關(guān)到整個后端服務(wù)的多個流量隔離環(huán)境,有效保證了多個親密關(guān)系的服務(wù)順利安全發(fā)布以及服務(wù)多版本并行開發(fā),進(jìn)一步促進(jìn)業(yè)務(wù)的快速發(fā)展。