當服務調用執行未成功時,回退機制提供替代的另外執行路徑。當某個微服務發生故障或無法使用時,回退機制會調用一個備用的服務來處理請求,以確保整個系統的穩定性和可用性。例如,當一個服務端點不可用時,可以使用回退機制將請求轉發到一個備用的服務版本,確??蛻舳苏埱竽軌蚶^續正常運行,而不會出現錯誤或中斷。ASM支持在VirtualService中定義fallback參數以支持請求服務失敗時的回退機制。本文介紹如何使用ASM回退機制。
前提條件
已創建ASM企業版或旗艦版實例,且版本為1.17.2.22及以上。具體操作,請參見創建ASM實例。
已添加ACK集群到ASM實例。具體操作,請參見添加集群到ASM實例。
已部署Bookinfo示例。具體操作,請參見在ASM實例關聯的集群中部署應用。
數據面Sidecar版本需為1.17及以上。
配置說明
本文以Bookinfo示例中的reviews服務為例。當productpage服務訪問reivews服務的三個版本v1、v2、v3時,如果v3版本不可用,將執行回退機制降級訪問v2版本,并且不返回503失敗信息。
您可以單擊配置文件,直接下載本文使用的相關YAML文件。
步驟一:訪問Bookinfo示例
使用以下內容,創建reviews.yaml文件,聲明reviews服務的v1、v2、v3三個版本。
apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: reviews spec: host: reviews subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2 - name: v3 labels: version: v3
在ASM實例對應的KubeConfig環境下,執行以下命令,部署DestinationRule。
kubectl apply -f reviews.yaml
任選以下方式,獲取網關的IP。
方式一:通過以下命令獲取。
kubectl get svc -n istio-system istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
方式二:通過ASM控制臺的入口網關頁面獲取網關IP。具體操作,請參見獲取ASM網關地址。
在瀏覽器中訪問
http://${YourGatewayIp}/productpage
。${YourGatewayIp}
為上一步獲取的網關IP。您可以通過Reviews served by的值或星星來判斷版本。v1版本沒有星星,v2版本為黑色星星,v3版本為紅色星星。例如,下圖reviews-v2表示v2版本,星星為黑色。
不斷刷新頁面,您可以看到請求reviews時,負載均衡到reviews的v1、v2、v3三個版本。
步驟二:定義訪問reviews的路由和回退規則
使用以下內容,創建reviews-route-fallback-sample1.yaml文件。
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: reviews-route namespace: default spec: hosts: - reviews http: - route: - destination: host: reviews subset: v3 fallback: target: host: reviews subset: v2
在ASM實例對應的KubeConfig環境下,執行以下命令,部署訪問reviews的路由和回退規則。
kubectl apply -f reviews-route-fallback-sample1.yaml
在瀏覽器中訪問
http://${YourGatewayIp}/productpage
,并不斷刷新頁面。可以看到請求一直在reviews的v3版本上。
執行以下命令,人為模擬reviews-v3版本故障,將reviews-v3的副本實例數修改為0。
kubectl scale deployment reviews-v3 --replicas=0
在瀏覽器中訪問
http://${YourGatewayIp}/productpage
,并不斷刷新頁面。可以看到請求正確回退到reviews的v2的版本上。您可以通過在自定義訪問日志格式中添加Fallback相關字段,然后查看日志,判斷是否進行了回退。
在自定義訪問日志格式中添加如下字段。具體操作,請參見自定義數據面訪問日志內容。
字段
取值
說明
fallback_path
%DYNAMIC_METADATA(com.aliyun.fallback:fallback-path)%
回退的具體路徑。例如A:B表示A回退到B;A:B:C表示A回退到B,因為B也不健康,所以回退到C。
fallback_final_cluster_name
%DYNAMIC_METADATA(com.aliyun.fallback:final-cluster)%
若回退,則回退到對應的目標集群。例如當service1|v1不存在時,回退到service|base。
fallback_result
%DYNAMIC_METADATA(com.aliyun.fallback:fallback-result)%
回退的結果,若失敗則發送給原路由的集群。
查看produpage-v1的istio-proxy的日志。
當reviews-v3回退到reviews-v2時,日志示例如下:
{ "authority":"reviews:9080", "authority_for":"reviews:9080", "bytes_received":"0", "bytes_sent":"442", "downstream_local_address":"192.168.255.46:9080", "downstream_remote_address":"172.16.0.252:57238", "duration":"10", "fallback_path":"outbound|9080|v3|reviews.default.svc.cluster.local:outbound|9080|v2|reviews.default.svc.cluster.local", "fallback_final_cluster_name":"outbound|9080|v2|reviews.default.svc.cluster.local", "fallback_result":"fallback successful", "istio_policy_status":"-", "method":"GET", "path":"/reviews/0", "protocol":"HTTP/1.1", "request_id":"15b2dffc-5f3f-4060-b9fa-898eab08****", "requested_server_name":"-", "response_code":"200", "response_flags":"-", "route_name":"-", "start_time":"2023-05-30T07:02:26.990Z", "trace_id":"18b3aed8af41****", "upstream_cluster":"outbound|9080|v2|reviews.default.svc.cluster.local", "upstream_host":"172.16.0.11:9080", "upstream_local_address":"172.16.0.252:44448", "upstream_service_time":"9", "upstream_transport_failure_reason":"-", "user_agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.X.X Safari/537.36", "x_forwarded_for":"-" }
您可以在日志中看到如下新增的日志字段。
"fallback_path":"outbound|9080|v3|reviews.default.svc.cluster.local:outbound|9080|v2|reviews.default.svc.cluster.local" "fallback_final_cluster_name":"outbound|9080|v2|reviews.default.svc.cluster.local" "fallback_result":"fallback successful"
通過日志可以看到原本的路由目標是v3,因為v3下實例不可用,請求回退到v2版本。
步驟三:在帶有權重的路由下配置回退規則
執行以下命令,將reviews-v3版本置為可用狀態。
kubectl scale deployment reviews-v3 --replicas=1
使用如下內容,創建reviews-route-fallback-sample2.yaml文件,修改reviews-route的定義。
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: reviews-route namespace: default spec: hosts: - reviews http: - route: - destination: host: reviews subset: v3 fallback: target: host: reviews subset: v2 weight: 50 - destination: host: reviews subset: v2 fallback: target: host: reviews subset: v1 weight: 50 retries: attempts: 0
執行以下命令,部署reviews新的路由和回退規則。
kubectl apply -f reviews-route-fallback-sample1.yaml
在瀏覽器中訪問
http://${YourGatewayIp}/productpage
,并不斷刷新頁面。可以看請求按50:50的比例落在reviews的v2和v3版本。為了讓顯示效果更明顯,本示例關閉了重試。
執行以下命令,將v3的副本實例個數調整為0,驗證v3的回退規則是否符合預期。
kubectl scale deployment reviews-v3 --replicas=0
不斷刷新productpage頁面,可以看到請求一直reviews的v2版本下,符合預期。
執行以下命令,將v2的副本實例數調整為0。
kubectl scale deployment reviews-v2 --replicas=0
不斷刷新productpage頁面,可以看到類似如下頁面,productpage訪問reviews失敗。該頁面出現的概率為50%,另外50%的概率請求到了v2版本。因為v2版本不健康,實際請求回退到v1版本。
執行以下命令,查看日志。
kubectl logs -f deployment/productpage-v1 -c istio-proxy --tail=10
預期輸出:
{ "authority":"reviews:9080", "authority_for":"reviews:9080", "bytes_received":"0", "bytes_sent":"19", "downstream_local_address":"192.168.255.46:9080", "downstream_remote_address":"172.16.0.252:47738", "duration":"0", "fallback_path":"outbound|9080|v3|reviews.default.svc.cluster.local:outbound|9080|v2|reviews.default.svc.cluster.local", "fallback_final_cluster_name":"-", "fallback_result":"fallback cluster is unhealthy", "istio_policy_status":"-", "method":"GET", "path":"/reviews/0", "protocol":"HTTP/1.1", "request_id":"b207a764-b6d7-4ef8-bc71-59f264c3****", "requested_server_name":"-", "response_code":"503", "response_flags":"UH", "route_name":"-", "start_time":"2023-05-30T07:32:08.999Z", "trace_id":"a40c32a7b2cf****", "upstream_cluster":"outbound|9080|v3|reviews.default.svc.cluster.local", "upstream_host":"-", "upstream_local_address":"-", "upstream_service_time":"-", "upstream_transport_failure_reason":"-", "user_agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.X.X Safari/537.36", "x_forwarded_for":"-" }
可以看到productpage-v1下有類似如上503日志。基于reviews-route帶權重的路由配置,productpage會有50%的概率請求v3版本的reviews。由于v3版本不可用,Sidecar(istio-proxy) 基于回退規則,嘗試從v3回退到v2版本。由于v2版本不健康,請求發往了v3版本。您可以通過字段
"upstream_cluster":"outbound|9080|v3|reviews.default.svc.cluster.local"
進行確認。