在微服務情境中,應用間的調用是隨機的。當您部署的Spring Cloud應用或Dubbo應用存在升級版本時,可能會導致無法將具有一定特徵的流量路由到應用的目標版本。通過MSE提供的全鏈路灰階能力,您無需修改業務代碼,就可以實現端到端的全鏈路流量控制。泳道可以將應用的相關版本隔離成一個獨立的運行環境。通過設定泳道規則,可以將滿足規則的請求流量路由到目標版本的應用。本文介紹如何通過配置MSE雲原生網關實現端到端的全鏈路灰階。
使用限制
由於全鏈路灰階功能整合了標籤路由功能(此處指的是MSE微服務治理的標籤路由,與MSE雲原生網關的標籤路由無關),因此不推薦已經加入全鏈路流量控制的應用配置金絲雀發布和標籤路由規則。
全鏈路灰階能力,對於Java應用的限制詳見微服務治理支援的Java架構。
最新版本的全鏈路灰階能力,MSE雲原生網關版本需要大於等於2.0.6版本,升級網關版本詳見升級MSE雲原生網關。
情境樣本
本文以電商架構中的下單情境為例,介紹從MSE雲原生網關到微服務的全鏈路流控功能。假設應用的架構由MSE雲原生網關以及後端的微服務架構(Spring Cloud)組成,後端調用鏈路有3個:交易中心(A)、商品中心(B)、庫存中心(C),可以通過用戶端或者HTML來訪問後端服務,這些服務之間通過MSE Nacos註冊中心實現服務發現。
客戶下單後流量從MSE雲原生網關進來,調用交易中心(A),交易中心(A)再調用商品中心(B),商品中心(B)調用下遊的庫存中心(C)。總之,調用鏈路為:客戶>MSE雲原生網關>A>B>C。
隨著業務不斷迭代,新功能需要上線,涉及到應用A和應用C同時發布新版本。在新版本正式上線之前,需要同時對應用A和應用C進行灰階驗證,確認無誤後方可正式上線。
通過MSE雲原生網關和MSE微服務治理提供的全鏈路灰階能力,您可以端到端構建從網關到多個後端服務的全鏈路灰階,控制具有一定特徵的灰階流量始終路由到應用對應的灰階環境,滿足您同時灰階驗證多個服務的訴求。此外,在應用無目標灰階版本時,自動容災到正式環境中。

名詞解釋
MSE雲原生網關:MSE雲原生網關是相容K8s Ingress標準的下一代網關產品,支援ACK容器和Nacos等多種服務發現方式,支援多種認證登入方式快速構建安全防線。
泳道:為相同版本應用定義的一套隔離環境。只有滿足了流控路由規則的請求流量才會路由到對應泳道裡的打標應用。一個應用可以屬於多個泳道,一個泳道可以包含多個應用,應用和泳道是多對多的關係。
泳道組:泳道的集合。泳道組的作用主要是為了區分不同團隊或不同情境。
基準環境:未打標的應用屬於基準環境,是其他環境的兜底環境。
準備工作
開啟MSE微服務治理
重要 請確保MSE Java 探針的版本3.2.3及以上,否則會影響業務運行。
步驟一:搭建業務應用的基準環境
步驟1:部署後端業務應用的基準版本
登入Container Service控制台。
在左側導覽列,單擊叢集列表,然後單擊目的地組群名稱。
在左側導覽列,選擇。
在頁面上方,選擇叢集的命名空間,然後單擊右上方的使用YAML建立資源。
部署基準應用。
服務來源為MSE Nacos
複製如下YAML檔案內容,部署A、B、C三個應用的基準版本。
說明 代碼中的{nacos server address}需要替換成您建立的MSE Nacos的內網網域名稱,同時需要去掉大括弧{}。
展開查看YAML檔案
# 應用A的基準版本
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-a
namespace: default
spec:
selector:
matchLabels:
app: spring-cloud-a
template:
metadata:
labels:
app: spring-cloud-a
msePilotCreateAppName: spring-cloud-a
msePilotAutoEnable: 'on'
spec:
containers:
- name: spring-cloud-a
image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-a:3.0.1
imagePullPolicy: Always
ports:
- containerPort: 20001
livenessProbe:
tcpSocket:
port: 20001
initialDelaySeconds: 30
periodSeconds: 60
env:
- name: spring.cloud.nacos.discovery.server-addr
value: {nacos server address}
- name: dubbo.registry.address
value: 'nacos://{nacos server address}:8848'
---
# 應用B的基準版本
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-b
namespace: default
spec:
selector:
matchLabels:
app: spring-cloud-b
template:
metadata:
labels:
app: spring-cloud-b
msePilotCreateAppName: spring-cloud-b
msePilotAutoEnable: 'on'
spec:
containers:
- name: spring-cloud-b
image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-b:3.0.1
imagePullPolicy: Always
ports:
- containerPort: 20002
livenessProbe:
tcpSocket:
port: 20002
initialDelaySeconds: 30
periodSeconds: 60
env:
- name: spring.cloud.nacos.discovery.server-addr
value: {nacos server address}
- name: dubbo.registry.address
value: 'nacos://{nacos server address}:8848'
---
# 應用C的基準版本
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-c
namespace: default
spec:
selector:
matchLabels:
app: spring-cloud-c
template:
metadata:
labels:
app: spring-cloud-c
msePilotCreateAppName: spring-cloud-c
msePilotAutoEnable: 'on'
spec:
containers:
- name: spring-cloud-c
image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-c:3.0.1
imagePullPolicy: Always
ports:
- containerPort: 20003
livenessProbe:
tcpSocket:
port: 20003
initialDelaySeconds: 30
periodSeconds: 60
env:
- name: spring.cloud.nacos.discovery.server-addr
value: {nacos server address}
- name: dubbo.registry.address
value: 'nacos://{nacos server address}:8848'
服務來源為Container Service
複製如下YAML檔案,部署Nacos,類比自建服務註冊中心的情境。
展開查看YAML檔案
apiVersion: apps/v1
kind: Deployment
metadata:
name: nacos-server
spec:
replicas: 1
selector:
matchLabels:
app: nacos-server
template:
metadata:
labels:
msePilotAutoEnable: "off"
app: nacos-server
spec:
containers:
- name: nacos-server
image: 'registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/nacos-server:v2.1.2'
env:
- name: MODE
value: standalone
- name: JVM_XMS
value: 512M
- name: JVM_XMX
value: 512M
- name: JVM_XMN
value: 256M
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
initialDelaySeconds: 15
periodSeconds: 10
successThreshold: 1
tcpSocket:
port: 8848
timeoutSeconds: 3
readinessProbe:
failureThreshold: 5
initialDelaySeconds: 15
periodSeconds: 15
successThreshold: 1
tcpSocket:
port: 8848
timeoutSeconds: 3
resources:
requests:
cpu: '1'
memory: 2Gi
dnsPolicy: ClusterFirst
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: nacos-server
spec:
type: ClusterIP
ports:
- name: nacos-server-8848-8848
port: 8848
protocol: TCP
targetPort: 8848
- name: nacos-server-9848-9848
port: 9848
protocol: TCP
targetPort: 9848
selector:
app: nacos-server
複製如下YAML檔案,部署A、B、C三個應用的基準版本。
展開查看YAML檔案
# 應用A的基準版本
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-a
namespace: default
spec:
selector:
matchLabels:
app: spring-cloud-a
template:
metadata:
labels:
app: spring-cloud-a
msePilotCreateAppName: spring-cloud-a
msePilotAutoEnable: 'on'
spec:
containers:
- name: spring-cloud-a
image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-a:3.0.1
imagePullPolicy: Always
ports:
- containerPort: 20001
livenessProbe:
tcpSocket:
port: 20001
initialDelaySeconds: 30
periodSeconds: 60
# 通過Nacos的Service訪問自建Nacos
env:
- name: spring.cloud.nacos.discovery.server-addr
value: nacos-server
- name: dubbo.registry.address
value: 'nacos://nacos-server:8848'
---
# 應用B的基準版本
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-b
namespace: default
spec:
selector:
matchLabels:
app: spring-cloud-b
template:
metadata:
labels:
app: spring-cloud-b
msePilotCreateAppName: spring-cloud-b
msePilotAutoEnable: 'on'
spec:
containers:
- name: spring-cloud-b
image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-b:3.0.1
imagePullPolicy: Always
ports:
- containerPort: 20002
livenessProbe:
tcpSocket:
port: 20002
initialDelaySeconds: 30
periodSeconds: 60
# 通過Nacos的Service訪問自建Nacos
env:
- name: spring.cloud.nacos.discovery.server-addr
value: nacos-server
- name: dubbo.registry.address
value: 'nacos://nacos-server:8848'
---
# 應用C的基準版本
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-c
namespace: default
spec:
selector:
matchLabels:
app: spring-cloud-c
template:
metadata:
labels:
app: spring-cloud-c
msePilotCreateAppName: spring-cloud-c
msePilotAutoEnable: 'on'
spec:
containers:
- name: spring-cloud-c
image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-c:3.0.1
imagePullPolicy: Always
ports:
- containerPort: 20003
livenessProbe:
tcpSocket:
port: 20003
initialDelaySeconds: 30
periodSeconds: 60
# 通過Nacos的Service訪問自建Nacos
env:
- name: spring.cloud.nacos.discovery.server-addr
value: nacos-server
- name: dubbo.registry.address
value: 'nacos://nacos-server:8848'
複製如下YAML檔案,為入口應用A建立Service。
展開查看YAML檔案
# 暴露應用A
apiVersion: v1
kind: Service
metadata:
name: sc-a
namespace: default
spec:
ports:
- port: 20001
protocol: TCP
targetPort: 20001
selector:
app: spring-cloud-a
type: ClusterIP
步驟2:通過MSE雲原生網關暴露應用A
情況一:新服務
如果您未在雲原生網關上添加過應用A,可以通過如下操作暴露應用A。
登入MSE管理主控台。選擇雲原生網關 > 網關列表,單擊已建立的雲原生網關執行個體。在左側導覽列的路由管理頁面,選擇服務頁簽,單擊创建服务。具體操作,請參見建立服務。
來源為Container Service
來源為MSE Nacos
服務來源:選擇MSE Nacos。
命名空間:選擇public。
服務列表:選擇sc-A。
在路由管理頁面,選擇路由頁簽。單擊建立路由,為服務sc-a/sc-A建立路由完成對外暴露。具體操作,請參見建立路由。
配置項 | 描述 |
路徑(Path) | 選擇匹配條件為首碼是,路徑為/a。 |
路由指向 | 選擇單服務。 |
後端服務 | 選擇 sc-A |
情況二:線上已有服務
如果您的實際情境是針對已匯入的服務,可通過如下操作暴露應用A。
登入MSE管理主控台。選擇雲原生網關 > 網關列表,選擇已建立的雲原生網關執行個體。在左側導覽列路由管理頁面,選擇路由頁簽。編輯已有的路由,以便暴露服務。
配置項 | 描述 |
路徑(Path) | 選擇匹配條件為首碼是,路徑為/a。 |
路由指向 | 選擇單服務。 |
後端服務 | 選擇 sc-A |
步驟3:測試基準版本流量
登入MSE網關管理主控台,並在頂部功能表列選擇地區。
在左側導覽列,選擇云原生网关 > 网关列表,單擊目標網關名稱。
在左側導覽列,單擊基本概览。
在接入点頁簽的网关入口處,查看SLB的入口地址。
使用curl命令,測試基準版本流量,發現流量經過了A、B和C的基準版本。如下所示:
# 測試命令
curl x.x.1.1/a
# 測試結果
A[10.0.3.178][config=base] -> B[10.0.3.195] -> C[10.0.3.201]
如測試結果所示,B和C輸出結果的應用程式名稱後面沒有版本,則代表訪問對應應用的基準版本。
步驟二:搭建業務應用的灰階環境
如果業務應用要發布新功能,新功能要求應用A和應用C同時發版,這時就需要藉助全鏈路灰階來同時驗證不同應用的灰階版本。
步驟1:部署後端業務應用的灰階版本
登入Container Service控制台。
在左側導覽列,單擊叢集列表,然後單擊目的地組群名稱。
在左側導覽列,選擇。
在頁面上方,選擇叢集的命名空間,然後單擊右上方的使用YAML建立資源。
複製以下YAML檔案內容,部署A、C兩個應用的灰階版本。
服務來源為MSE Nacos
說明 代碼中的{nacos server address}需要替換成您建立的MSE Nacos的內網網域名稱,同時需要去掉大括弧{}。
展開查看YAML檔案
# 應用A的灰階版本
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-a-gray
namespace: default
spec:
selector:
matchLabels:
app: spring-cloud-a-gray
template:
metadata:
labels:
alicloud.service.tag: gray
app: spring-cloud-a-gray
msePilotCreateAppName: spring-cloud-a
msePilotAutoEnable: 'on'
spec:
containers:
- name: spring-cloud-a
image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-a:3.0.1
imagePullPolicy: Always
ports:
- containerPort: 20001
livenessProbe:
tcpSocket:
port: 20001
initialDelaySeconds: 30
periodSeconds: 60
env:
- name: spring.cloud.nacos.discovery.server-addr
value: {nacos server address}
- name: dubbo.registry.address
value: 'nacos://{nacos server address}:8848'
---
# 應用C的灰階版本
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-c-gray
namespace: default
spec:
selector:
matchLabels:
app: spring-cloud-c-gray
template:
metadata:
labels:
alicloud.service.tag: gray
app: spring-cloud-c-gray
msePilotCreateAppName: spring-cloud-c
msePilotAutoEnable: 'on'
spec:
containers:
- name: spring-cloud-c
image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-c:3.0.1
imagePullPolicy: Always
ports:
- containerPort: 20003
livenessProbe:
tcpSocket:
port: 20003
initialDelaySeconds: 30
periodSeconds: 60
env:
- name: spring.cloud.nacos.discovery.server-addr
value: {nacos server address}
- name: dubbo.registry.address
value: 'nacos://{nacos server address}:8848'
服務來源為Container Service
展開查看YAML檔案
# 應用A的灰階版本
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-a-gray
namespace: default
spec:
selector:
matchLabels:
app: spring-cloud-a
template:
metadata:
labels:
alicloud.service.tag: gray
app: spring-cloud-a
msePilotCreateAppName: spring-cloud-a
msePilotAutoEnable: 'on'
spec:
containers:
- name: spring-cloud-a
image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-a:3.0.1
imagePullPolicy: Always
ports:
- containerPort: 20001
livenessProbe:
tcpSocket:
port: 20001
initialDelaySeconds: 30
periodSeconds: 60
# 通過Nacos的Service訪問自建Nacos
env:
- name: spring.cloud.nacos.discovery.server-addr
value: nacos-server
- name: dubbo.registry.address
value: 'nacos://nacos-server:8848'
---
# 應用C的灰階版本
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-c-gray
namespace: default
spec:
selector:
matchLabels:
app: spring-cloud-c
template:
metadata:
labels:
alicloud.service.tag: gray
app: spring-cloud-c
msePilotCreateAppName: spring-cloud-c
msePilotAutoEnable: 'on'
spec:
containers:
- name: spring-cloud-c
image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-c:3.0.1
imagePullPolicy: Always
ports:
- containerPort: 20003
livenessProbe:
tcpSocket:
port: 20003
initialDelaySeconds: 30
periodSeconds: 60
# 通過Nacos的Service訪問自建Nacos
env:
- name: spring.cloud.nacos.discovery.server-addr
value: nacos-server
- name: dubbo.registry.address
value: 'nacos://nacos-server:8848'
步驟2:建立灰階環境泳道組
登入MSE治理中心控制台,並在頂部功能表列選擇地區。
在左側導覽列,選擇。
如果您選擇的微服務命名空間內沒有建立過泳道組,則單擊创建泳道组及泳道。如果您選擇的微服務命名空間內已經建立過泳道組,則單擊+创建泳道组。
在创建泳道组面板,設定如下相關配置,然後單擊确定。
配置項 | 說明 |
泳道组名称 | 自訂泳道組的名稱。 |
入口类型 | 選擇MSE 云原生网关。 |
入口网关 | 選擇目標雲原生網關。 |
泳道组涉及应用 | 選擇spring-cloud-a、spring-cloud-b和spring-cloud-c。 |

泳道組建立完成後,在全链路灰度頁面的泳道组地區,可以查看您建立的泳道組。如需變更泳道組資訊,單擊
表徵圖,可在頁面自行修改相關資訊。
步驟3:建立灰階環境泳道
說明 使用全鏈路灰階功能時,需要您給灰階應用添加一個特殊的 tag 標記,以便將這些節點和其他節點區分開來。容器環境下需要您在spec.template.metadata.labels下增加alicloud.service.tag: ${tag}資訊;在ECS環境下需要添加Java啟動參數-Dalicloud.service.tag=${tag}。
以雲原生網關作為全鏈路灰階入口時,MSE支援兩種泳道灰階模式。
泳道路由模式在一個泳道組中需要保持一致。您只有在建立泳道組中第一條泳道時可以調整泳道路由的灰階模式。
在全链路灰度頁面底部,如果您選擇的微服務命名空間內沒有建立過泳道,則單擊点击创建第一个分流泳道。如果您選擇的微服務命名空間內已經建立過泳道,則單擊+创建泳道。
在创建泳道面板,設定流控泳道相關配置,然後單擊确定。
建立按請求內容路由的泳道
配置項 | 說明 |
配置節點標籤 | 需要您給灰階應用節點打上標籤,以便與正常節點做區分。 |
填寫泳道資訊 | 泳道名稱:輸入便於理解和識別的泳道名稱。 泳道標籤:該泳道內的匹配的流量去往的目標標籤。 確認匹配關係:檢查您配置了該標籤的應用節點數是否符合預期。 泳道狀態:選擇開啟。 |
配置灰階規則 | 設定流量進入該泳道的規則。 灰階模式:選擇按內容灰階。 灰階條件:選擇以下條件同時滿足。 本樣本灰階條件配置如下: 参数类型:Header。 参数:canary。 条件:==。 值:gray。
|
泳道路由模式說明
灰階條件 | 效果 |
以下條件同時滿足 | 需要所有條件內容滿足的流量才會去往對應的泳道。 |
以下條件任意滿足 | 滿足如下任意一個條件內容的流量就會去往對應的泳道。 |
條件內容說明
條件 | 描述 | 全鏈路灰階配置樣本 | 雲原生網關請求樣本 |
== | 精確匹配,流量值與條件值需要完全相等。 | 
| 
|
!= | 不等匹配,流量值與條件值不相等時滿足條件。 | 
| 
|
in | 包含匹配,流量值需要在指定的列表中時滿足條件。 | 
| 
|
百分比 | 百分比匹配,原理:滿足`hash(get(key)) % 100 < value` 成立時滿足條件。 | 
| 
|
正則匹配 | Regex匹配,按照Regex規則匹配時滿足條件。 | 
| 
|
建立按比例路由的泳道
說明 建立按比例路由的泳道,需要ack-onepilot版本為3.0.18及以上,且探針版本為3.2.3及以上。
配置項 | 說明 |
配置節點標籤 | 需要您手工給您的灰階應用節點打上標籤,以便與正常節點做區分。 |
填寫泳道資訊 | 泳道名稱:輸入便於理解和識別的泳道名稱。 泳道標籤:該泳道內的匹配的流量去往的目標標籤。 確認匹配關係:檢查您配置了該標籤的應用節點數是否符合預期。 泳道狀態:選擇開啟。 |
配置路由和灰階規則 | 設定流量進入該泳道的規則。 |
說明 您還可以為每條網關基準路由分別設定不同的流量比例,開啟該功能時,您需要注意該網關基準路由當前在所有泳道組中配置的流量比例總和不應超過100%。
完成泳道建立後,在全链路灰度的流量分配地區,可以查看泳道詳情,還可以進行如下操作。
步驟4:測試灰階版本流量
測試按請求內容路由的泳道
使用curl命令測試灰階流量,如測試結果所示,流量經過了A、C的灰階環境,由於B沒有gray環境,所以流量自動容災到基準版本。
# 測試命令
curl -H "canary: gray" x.x.x.x/a
# 測試結果
Agray[10.0.3.177][config=base] -> B[10.0.3.195] -> Cgray[10.0.3.180]
測試按比例路由的泳道
可以通過如下Python指令碼測試按比例路由的分流情況(需要安裝requests包),並將“x.x.x.x”替換為雲原生網關的入口SLB地址。
展開查看Python指令碼
# pip3 install requests
# python3 traffic.py
import requests
TOTAL_REQUEST = 100
ENTRY_URL = 'http://x.x.x.x/a'
def parse_tag(text:str):
'''
A[10.0.23.64][config=base] -> B[10.0.23.65] -> C[10.0.23.61]
Agray[10.0.23.64][config=base] -> B[10.0.23.65] -> Cgray[10.0.23.61]
Ablue[10.0.23.64][config=base] -> B[10.0.23.65] -> Cblue[10.0.23.61]
'''
print(text)
app_parts = text.split(' -> ')
# tag_app: C[10.0.23.61] / Cgray[10.0.23.61]
tag_app = app_parts[-1]
splits = tag_app.split('[')
# tag_part: C / Cgray
tag_part = splits[0]
tag = tag_part[1:]
return tag if len(tag) > 0 else 'base'
def get_tag(url:str):
resp = requests.get(url)
resp.encoding = resp.apparent_encoding
return parse_tag(resp.text)
def cal_tag_count(url:str, total_request:int):
count_map = {}
for i in range(total_request):
tag = get_tag(url)
if tag not in count_map:
count_map[tag] = 1
else:
count_map[tag] += 1
print()
print('Total Request:', total_request)
print('Traffic Distribution:', count_map)
if __name__ == '__main__':
cal_tag_count(ENTRY_URL, TOTAL_REQUEST)
從結果可以看到,約有30%比例的流量去往了灰階環境。

(可選)步驟三:可觀測
若應用出現異常,您可以通過MSE提供的可觀測能力查看異常資料,協助您快速定位問題。
雲原生網關可觀測
在MSE雲原生網關的路由管理頁面,選擇服務頁簽。單擊目標服務,在监控地區查看服務的流量情況。

微服務治理可觀測
在MSE微服務治理的全链路灰度頁面,單擊目標應用,在應用 QPS 監控地區,可查看對應泳道基準版本(未打標)和灰階版本的流量情況。

總QPS:該應用總的QPS。
異常QPS:該應用出錯的請求數。
GrayQPS:該應用gray版本的QPS。
Arms 可觀測
如果您的應用同時接入了 Arms,您可以在 Arms 全鏈路灰階情境化頁面觀察灰階環境業務情況,觀察灰階大盤業務情況,決定復原還是繼續發布。
