新聞中心
1概述
在當(dāng)今快節(jié)奏的軟件開(kāi)發(fā)環(huán)境中,隨著用戶(hù)需求的不斷變化和競(jìng)爭(zhēng)日益激烈,軟件更新和發(fā)布的頻率已成為常態(tài)。然而,與此同時(shí),保證用戶(hù)體驗(yàn)的穩(wěn)定性和可靠性也是至關(guān)重要的。傳統(tǒng)的大規(guī)模軟件發(fā)布往往會(huì)面臨著線上故障風(fēng)險(xiǎn),可能導(dǎo)致用戶(hù)體驗(yàn)下降,甚至影響業(yè)務(wù)正常運(yùn)行。

創(chuàng)新互聯(lián)專(zhuān)注于企業(yè)成都全網(wǎng)營(yíng)銷(xiāo)、網(wǎng)站重做改版、利州網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5響應(yīng)式網(wǎng)站、商城開(kāi)發(fā)、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站制作、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性?xún)r(jià)比高,為利州等各大城市提供網(wǎng)站開(kāi)發(fā)制作服務(wù)。
為了解決這一矛盾,在軟件開(kāi)發(fā)領(lǐng)域催生出了灰度發(fā)布的概念?;叶劝l(fā)布是一種漸進(jìn)式的軟件發(fā)布方式,它允許將新功能或更新逐步推送給一部分用戶(hù),而不是一次性全部發(fā)布。這樣的方式能夠有效降低線上故障的風(fēng)險(xiǎn),保障用戶(hù)體驗(yàn),同時(shí)也為開(kāi)發(fā)團(tuán)隊(duì)提供了更多時(shí)間和機(jī)會(huì)在全面發(fā)布前進(jìn)行驗(yàn)證和修復(fù)。
然而,隨著軟件架構(gòu)的演進(jìn),尤其是微服務(wù)架構(gòu)的普及,軟件系統(tǒng)往往由多個(gè)微服務(wù)組成,不同服務(wù)的版本升級(jí)需要協(xié)調(diào)和同步。在這種背景下,單一服務(wù)的灰度發(fā)布已經(jīng)不能完全適應(yīng)需求,全鏈路灰度發(fā)布應(yīng)運(yùn)而生。
全鏈路灰度發(fā)布考慮到整個(gè)軟件系統(tǒng)的多個(gè)微服務(wù),允許多個(gè)微服務(wù)同時(shí)進(jìn)行版本控制和升級(jí),以確保整個(gè)系統(tǒng)的平穩(wěn)過(guò)渡和穩(wěn)定性,是一種更為全面和細(xì)致的灰度發(fā)布方式。通過(guò)全鏈路灰度發(fā)布,開(kāi)發(fā)團(tuán)隊(duì)能夠更加精確地控制不同服務(wù)版本的發(fā)布比例,降低系統(tǒng)風(fēng)險(xiǎn),保障線上穩(wěn)定性,最大程度地滿(mǎn)足用戶(hù)需求。
圖片
以圖 1 為例,軟件系統(tǒng)包含網(wǎng)關(guān)和 4 個(gè)微服務(wù),通過(guò)全鏈路灰度發(fā)布,可以使ServiceB 和 ServiceD 進(jìn)行灰度發(fā)布,通過(guò)灰線所示的流量進(jìn)行灰度功能驗(yàn)證,同時(shí)不影響藍(lán)線所示的正常訪問(wèn)流量。
2全鏈路灰度發(fā)布核心問(wèn)題
我們通過(guò)圖1 可以清晰地看到,在實(shí)施全鏈路灰度發(fā)布時(shí),需要部署相關(guān)服務(wù)的灰度版本,并確保在整個(gè)請(qǐng)求的調(diào)用鏈上,網(wǎng)關(guān)和微服務(wù)組件能夠準(zhǔn)確識(shí)別正式流量和特定版本灰度流量,并根據(jù)流量類(lèi)型動(dòng)態(tài)地將請(qǐng)求路由到正確版本的上游微服務(wù)上。所以,我們需要解決以下幾個(gè)問(wèn)題:
- 微服務(wù)實(shí)例具有版本信息,針對(duì)不同流量對(duì)應(yīng)版本實(shí)例提供服務(wù);
- 請(qǐng)求流量具有流量特征,可以區(qū)分出是請(qǐng)求不同版本微服務(wù)的流量;
- 調(diào)用鏈上各組件可以根據(jù)流量特征將請(qǐng)求動(dòng)態(tài)路由到正確版本的微服務(wù)上。當(dāng)前的微服務(wù)架構(gòu)主要分為兩類(lèi)模式:一類(lèi)是建立在傳統(tǒng)微服務(wù)框架(例如Spring Cloud等)之上的微服務(wù)體系,另一類(lèi)是云原生時(shí)代采用Kubernetes和服務(wù)網(wǎng)格(如Istio)構(gòu)建的微服務(wù)架構(gòu),為了方便起見(jiàn),我們姑且簡(jiǎn)稱(chēng)為傳統(tǒng)模式和云原生模式。下面我們將介紹在兩類(lèi)模式下,如何解決以上問(wèn)題,進(jìn)行全鏈路灰度發(fā)布。
微服務(wù)標(biāo)識(shí)
我們通過(guò)給微服務(wù)實(shí)例添加標(biāo)識(shí)的方式,使微服務(wù)實(shí)例具有版本信息,針對(duì)不同流量對(duì)應(yīng)版本實(shí)例提供服務(wù)。
傳統(tǒng)模式
在傳統(tǒng)模式下,一般需要產(chǎn)品根據(jù)使用的微服務(wù)框架決定添加標(biāo)識(shí)的方式。我們以基于 Spring Cloud 框架 + Nacos注冊(cè)中心 的微服務(wù)為例,一般通過(guò)在微服務(wù)元數(shù)據(jù)配置(spring.cloud.nacos.discovery.metadata)中添加標(biāo)識(shí),配置示例如下:
spring:
cloud:
nacos:
discovery:
metadata:
version: ${APP-VERSION:v1}微服務(wù)在 Nacos 注冊(cè)中心中服務(wù)信息如下:
圖片
云原生模式
在云原生模式下,為微服務(wù)實(shí)例添加標(biāo)識(shí)更加方便,不需要修改微服務(wù)代碼配置,一般在微服務(wù) Deployment 的 Pod 模版中添加Labal標(biāo)識(shí)即可,實(shí)例如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo
spec:
selector:
matchLabels:
app: demo
version: v1
template:
metadata:
labels:
app: demo
version: v1
流量標(biāo)識(shí)
和微服務(wù)標(biāo)識(shí)相同,我們也是通過(guò)為流量添加不同標(biāo)識(shí)的方式區(qū)分流量,流量標(biāo)識(shí)在業(yè)界還有一個(gè)更專(zhuān)業(yè)更形象的叫法叫流量染色。
流量染色分兩步:第一步在流量源頭染色,第二步在調(diào)用鏈內(nèi)染色。
第一步比較簡(jiǎn)單,通過(guò)前端或者網(wǎng)關(guān)根據(jù)流量特點(diǎn)(比如瀏覽器類(lèi)型,用戶(hù)標(biāo)識(shí),地域標(biāo)識(shí)等)為流量添加標(biāo)識(shí)(比如在HTTP Header中添加version標(biāo)簽)。
第二步是全鏈路灰度中最核心也是最復(fù)雜的部分,需要流量標(biāo)識(shí)在調(diào)用鏈中透?jìng)飨氯?,保證調(diào)用鏈上的每個(gè)微服務(wù)組件都能根據(jù)標(biāo)識(shí)識(shí)別流量并動(dòng)態(tài)路由。
傳統(tǒng)的微服務(wù)框架注重基礎(chǔ)功能的實(shí)現(xiàn),例如服務(wù)注冊(cè)與發(fā)現(xiàn)、負(fù)載均衡等,而未將流量標(biāo)識(shí)透?jìng)髯鳛楹诵奶匦灾?,?dǎo)致在實(shí)際應(yīng)用中難以實(shí)現(xiàn)流量標(biāo)識(shí)的無(wú)縫傳遞。
云原生時(shí)代的 Kubernetes + Istio 同樣無(wú)法幫助微服務(wù)實(shí)現(xiàn)流量標(biāo)識(shí)透?jìng)?。不少人存在誤解,認(rèn)為 Istio 能對(duì)微服務(wù)實(shí)例的出入流量進(jìn)行攔截,應(yīng)該原生支持流量標(biāo)識(shí)透?jìng)?,但?shí)際上 Istio 本身沒(méi)有流量標(biāo)識(shí)透?jìng)鞯哪芰Α?/p>
圖片
Istio Sidecar 對(duì)微服務(wù)入口和出口流量攔截如上圖所示,Sidecar 雖然能將入口流量1 攔截后轉(zhuǎn)給微服務(wù)容器(入口流量2),也能將微服務(wù)容器出口流量 3 攔截并轉(zhuǎn)發(fā)到 Pod 外(出口流量4),但 Sidecar 不知道出口流量 3 和入口流量 2 的對(duì)應(yīng)關(guān)系,在實(shí)際情況中,Sidecar 會(huì)攔截很多的出口流量,也會(huì)攔截很多的入口流量,但 Sidecar 并不知道某一個(gè)出口流量對(duì)應(yīng)哪個(gè)入口流量。只有微服務(wù)應(yīng)用知道對(duì)應(yīng)關(guān)系,因?yàn)槲⒎?wù)應(yīng)用親自做了流量處理(微服務(wù)應(yīng)用收到入口流量請(qǐng)求2后,進(jìn)行業(yè)務(wù)邏輯處理,然后再發(fā)出出口流量3,請(qǐng)求下一級(jí)微服務(wù)),所以 Istio 雖然能對(duì)微服務(wù)出入流量攔截,但不知道出入流量的對(duì)應(yīng)關(guān)系,無(wú)法將入口流量的標(biāo)識(shí)自動(dòng)添加到出口流量上,無(wú)法做流量標(biāo)識(shí)透?jìng)鳌?/p>
流量標(biāo)識(shí)透?jìng)鞣绞?/h4>
那么如何進(jìn)行流量標(biāo)識(shí)透?jìng)髂兀ǔS幸韵?種方式:
微服務(wù)修改源碼方式
微服務(wù)側(cè)進(jìn)行業(yè)務(wù)代碼改造,從入口流量請(qǐng)求中獲取流量標(biāo)識(shí),并在出口流量中添加流量標(biāo)識(shí),代碼示例如下:
// 從請(qǐng)求中獲取流量標(biāo)識(shí) version
String versionValue = request.getHeader("version");
// 構(gòu)造新請(qǐng)求需要的 Header,獲取到的流量標(biāo)識(shí)添加到新請(qǐng)求的 Header 中
HttpHeaders headers = new HttpHeaders();
headers.set("version", versionValue);
// 發(fā)起出口流量請(qǐng)求
使用基礎(chǔ)SDK方式
將從入口流量請(qǐng)求中獲取流量標(biāo)識(shí),并在出口流量中添加流量標(biāo)識(shí)這種共性邏輯封裝到基礎(chǔ) SDK 中,其原理通常涉及 SDK 對(duì)請(qǐng)求和響應(yīng)的攔截處理。這種方法的核心在于SDK能夠攔截到微服務(wù)內(nèi)部的請(qǐng)求,從請(qǐng)求中獲取流量標(biāo)識(shí),并在微服務(wù)發(fā)起外部請(qǐng)求時(shí),將這個(gè)標(biāo)識(shí)加入請(qǐng)求中,實(shí)現(xiàn)流量標(biāo)識(shí)的透?jìng)??;A(chǔ) SDK 的工作機(jī)制一般包括以下幾個(gè)關(guān)鍵步驟:
- 攔截請(qǐng)求和響應(yīng): SDK會(huì)通過(guò)某種方式(例如AOP、攔截器等)攔截微服務(wù)的請(qǐng)求和響應(yīng),這使得SDK能夠在請(qǐng)求進(jìn)入微服務(wù)之前或響應(yīng)返回之后對(duì)其進(jìn)行處理。
- 獲取流量標(biāo)識(shí): 在請(qǐng)求被微服務(wù)處理之前,SDK會(huì)從請(qǐng)求中獲取流量標(biāo)識(shí)。這可能包括從HTTP頭部、Cookie、請(qǐng)求參數(shù)等位置獲取特定的標(biāo)識(shí)符。
- 向外發(fā)送請(qǐng)求: 當(dāng)微服務(wù)需要向外部服務(wù)發(fā)起請(qǐng)求時(shí),SDK會(huì)在請(qǐng)求中添加之前獲取到的流量標(biāo)識(shí)。這意味著,SDK會(huì)將其添加到新的請(qǐng)求頭、請(qǐng)求體或其他適當(dāng)?shù)奈恢?,以確保這個(gè)標(biāo)識(shí)被透?jìng)鞯酵獠糠?wù)。
通過(guò)以上步驟,基礎(chǔ) SDK 能夠在微服務(wù)內(nèi)部對(duì)流量進(jìn)行攔截、獲取流量標(biāo)識(shí),并在微服務(wù)發(fā)起外部請(qǐng)求時(shí),將這個(gè)標(biāo)識(shí)透?jìng)鞯酵獠糠?wù)中去。
在一些大型企業(yè)內(nèi)部,基礎(chǔ)設(shè)施團(tuán)隊(duì)會(huì)提供基礎(chǔ) SDK 供產(chǎn)品團(tuán)隊(duì)使用,也有一些相關(guān)的開(kāi)源方案可以參考,例如阿里開(kāi)源的KtEnv,提供了一個(gè)Java語(yǔ)言的SDK示例,采用Spring框架的切面機(jī)制來(lái)自動(dòng)化"環(huán)境標(biāo)簽"的傳遞,其中環(huán)境標(biāo)簽即為一種流量標(biāo)識(shí)。
使用基礎(chǔ)Agent方式
使用 Agent 技術(shù)實(shí)現(xiàn)流量標(biāo)識(shí)透?jìng)魇且环N相對(duì)隱式且高度可配置的方式。Agent 是一種可以介入到 JVM 運(yùn)行時(shí)的程序,它可以對(duì) Java 應(yīng)用程序進(jìn)行動(dòng)態(tài)的字節(jié)碼操作和增強(qiáng)。
在實(shí)現(xiàn)流量標(biāo)識(shí)透?jìng)鲿r(shí),Agent 可以通過(guò)動(dòng)態(tài)字節(jié)碼增強(qiáng)技術(shù),通過(guò)字節(jié)碼操作工具(如ASM、ByteBuddy等)對(duì)特定類(lèi)或方法進(jìn)行字節(jié)碼增強(qiáng),動(dòng)態(tài)地修改微服務(wù)應(yīng)用的字節(jié)碼,使得在請(qǐng)求處理鏈路中自動(dòng)獲取到流量標(biāo)識(shí),并在請(qǐng)求發(fā)起時(shí)將這些標(biāo)識(shí)添加到外部請(qǐng)求中。這些標(biāo)識(shí)可能包括從HTTP頭部、上下文信息、或者其他標(biāo)識(shí)性的數(shù)據(jù)。
有一些基礎(chǔ)Agent開(kāi)源方案可以選擇參考,如:Homer,這是專(zhuān)門(mén)為javaweb應(yīng)用提供了無(wú)感知的header透?jìng)鞯拈_(kāi)源方案,華為的Sermant,Sermant 是利用JavaAgent技術(shù)為Java應(yīng)用程序提供服務(wù)網(wǎng)格功能的開(kāi)源方案,提供了流量透?jìng)鞑寮ag-transmission,可以幫助微服務(wù)實(shí)現(xiàn)流量透?jìng)鞴δ堋?/p>
三種方式總結(jié)
這三種實(shí)現(xiàn)流量標(biāo)識(shí)透?jìng)鞯姆绞礁髯跃哂歇?dú)特的優(yōu)勢(shì)和適用場(chǎng)景??偨Y(jié)如下:
- 業(yè)務(wù)代碼修改: 這種方式簡(jiǎn)單直接,但會(huì)增加業(yè)務(wù)代碼的復(fù)雜性和維護(hù)成本,尤其在大型微服務(wù)體系中,需要在多個(gè)服務(wù)間添加相似的邏輯,不夠靈活和智能,實(shí)際應(yīng)用較少。
- 基礎(chǔ) SDK: 使用基礎(chǔ) SDK 相對(duì)于業(yè)務(wù)代碼修改更為智能化和自動(dòng)化,減少了對(duì)業(yè)務(wù)代碼的侵入,同時(shí)也能夠提供一定程度的可配置性和擴(kuò)展性,但對(duì)業(yè)務(wù)代碼仍然有侵入,并且和語(yǔ)言相關(guān),在大型多語(yǔ)言微服務(wù)體系中需要提供多語(yǔ)言SDK,另外 SDK 版本升級(jí)困難。
- Agent 方式: 基于 Agent 技術(shù),可以在不修改業(yè)務(wù)代碼的情況下,實(shí)現(xiàn)流量標(biāo)識(shí)的攔截和傳遞。這種方式尤其適用于不想或不能直接修改業(yè)務(wù)代碼的場(chǎng)景,其靈活性和智能化程度較高,但也存在和語(yǔ)言綁定,版本升級(jí)相對(duì)困難的問(wèn)題。
總體而言,三種方式各有利弊,在實(shí)際場(chǎng)景中,需要根據(jù)具體需求和現(xiàn)有架構(gòu),選擇適合的方式。
流量路由
流量路由和微服務(wù)標(biāo)識(shí)類(lèi)似,由于傳統(tǒng)模式和云原生模式都支持,較流量標(biāo)識(shí)簡(jiǎn)單很多。
在傳統(tǒng)微服務(wù)框架(如 Spring Cloud)中,實(shí)現(xiàn)動(dòng)態(tài)路由通常通過(guò) API 網(wǎng)關(guān)(如Spring Cloud Gateway)或負(fù)載均衡器(如Netflix Ribbon)等組件,根據(jù)特定的策略或規(guī)則,對(duì)流量進(jìn)行分發(fā)和路由。例如,可以基于請(qǐng)求頭中的流量標(biāo)識(shí)信息,利用負(fù)載均衡策略,將請(qǐng)求分發(fā)到不同版本的微服務(wù)實(shí)例上,實(shí)現(xiàn)動(dòng)態(tài)路由。
而在云原生架構(gòu)下(例如 Kubernetes + Istio),動(dòng)態(tài)路由更加簡(jiǎn)單。通過(guò) Istio 中的流量管理功能,定義Gateway、VirtualService、DestinationRule等規(guī)則和配置來(lái)實(shí)現(xiàn)流量的精細(xì)化控制和路由。
3全鏈路灰度發(fā)布實(shí)踐
我們?cè)谠圃J较?,?duì)概述部分圖1 所示的微服務(wù)進(jìn)行全鏈路灰度發(fā)布實(shí)踐。微服務(wù)版本情況及調(diào)用鏈路和圖 1 一致,微服務(wù)實(shí)例列表如下:
圖片
網(wǎng)關(guān)采用 Istio Ingress Gateway,流量標(biāo)識(shí)透?jìng)鞑捎没A(chǔ) Agent 方式,可以在微服務(wù)調(diào)用鏈路中透?jìng)?key 為 et-mark 的 HTTP Request Header ,流量路由通過(guò) Istio 流量管理功能實(shí)現(xiàn),關(guān)鍵Gateway、VirtualService、DestinationRule 規(guī)則部分如下:
---
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: ingress-gateway
namespace: e2e-canary-release
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- 'www.e2e-canary-release.com'
port:
name: http
number: 80
protocol: HTTP
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: service-a
namespace: e2e-canary-release
spec:
gateways:
- e2e-canary-release/ingress-gateway
hosts:
- 'www.e2e-canary-release.com'
http:
- route:
- destination:
host: service-a
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: service-b
namespace: e2e-canary-release
spec:
hosts:
- service-b
http:
- match:
- headers:
et-mark:
exact: v2
route:
- destination:
host: service-b
subset: v2
- route:
- destination:
host: service-b
subset: v1
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: service-b
namespace: e2e-canary-release
spec:
host: service-b
subsets:
- labels:
version: v1
name: v1
- labels:
version: v2
name: v2實(shí)際效果如下,可以看到默認(rèn)情況下請(qǐng)求流量流經(jīng)的微服務(wù)版本均為正式版本v1,當(dāng)請(qǐng)求header中包含流量標(biāo)識(shí)時(shí),即流量為灰度流量時(shí),會(huì)按照?qǐng)D1 中的灰色路徑流轉(zhuǎn),實(shí)現(xiàn)了全鏈路灰度發(fā)布。
圖片
圖片
4總結(jié)
本文首先介紹了全鏈路灰度發(fā)布的概念、作用以及實(shí)現(xiàn)全鏈路灰度發(fā)布時(shí)需要解決的關(guān)鍵問(wèn)題,針對(duì)每個(gè)問(wèn)題分別從傳統(tǒng)模式和云原生模式介紹了對(duì)應(yīng)的解決方案,其中對(duì)流量標(biāo)識(shí)透?jìng)髯隽嗽敿?xì)的介紹,然后在云原生模式下,對(duì)微服務(wù) Demo 進(jìn)行了全鏈路灰度發(fā)布實(shí)踐,展示了實(shí)踐效果。由于能力和時(shí)間有限,一些內(nèi)容僅進(jìn)行了粗淺介紹,希望后續(xù)可以繼續(xù)深入研究分享,文中存在錯(cuò)誤的地方,也望大家指正。
5參考文章及相關(guān)鏈接
- 深入剖析全鏈路灰度技術(shù)內(nèi)幕
https://developer.aliyun.com/article/834510#slide-1 - 基于 Istio 的全鏈路灰度方案探索和實(shí)踐https://xie.infoq.cn/article/f6a1db8756e8bfa831947ee05
- 聊聊 Spring Cloud 全鏈路灰度發(fā)布方案~ https://z.itpub.net/article/detail/5D9F94265D666C4607B92CBC32667692
- Spring Cloud Alibaba-全鏈路灰度設(shè)計(jì)https://www.nowcoder.com/discuss/517248839594541056
- 標(biāo)記透?jìng)鳎何⒎?wù)系統(tǒng)如何做標(biāo)記透?jìng)鞣桨高x型?https://leeshengis.com/archives/444794
- 流量治理的基石——基于字節(jié)碼增強(qiáng)的全鏈路流量標(biāo)簽透?jìng)鱤ttps://juejin.cn/post/7282957826510667816
- KtEnv
https://alibaba.github.io/virtual-environment/#/zh-cn/doc/use-sdk?id=%E4%BD%BF%E7%94%A8sdk - Homer
https://github.com/kaikeba/homer - Sermant
https://sermant.io/zh/
作者:張海文,中國(guó)移動(dòng)云能力中心高級(jí)軟件研發(fā)工程師,移動(dòng)云服務(wù)網(wǎng)格負(fù)責(zé)人,QCon、KubeCon等大會(huì)分享者,專(zhuān)注于云原生、微服務(wù)、算力網(wǎng)絡(luò)等。
新聞標(biāo)題:漫談全鏈路灰度發(fā)布
文章轉(zhuǎn)載:http://www.5511xx.com/article/djdcpco.html


咨詢(xún)
建站咨詢(xún)
