熔斷是一種流量管理的策略,用于在系統出現故障或超負荷的情況下,保護系統免受進一步的損害。在傳統的Java服務中,使用Resilience4j等框架可以實現熔斷功能。然而,與傳統方式相比,Istio的熔斷功能在網絡級別提供支持,不需要在每個服務的應用程序代碼中進行集成。您可以通過配置連接池來實現熔斷功能,提高系統的穩定性和可靠性,保護目標服務免受異常請求的影響。
前提條件
連接池參數說明
啟用熔斷功能前,您需要創建一個目標規則為目標服務配置熔斷。關于目標規則的字段說明,請參見目標規則(Destination Rule)CRD說明。
連接池connectionPool
字段定義了與熔斷功能相關的參數。常見的連接池參數說明如下。
參數 | 類型 | 是否必選 | 說明 | 默認值 |
| int32 | 否 | 到目標主機的最大HTTP1或TCP連接數。連接數限制會在客戶端及服務端 Sidecar 兩側均生效,即,單個客戶端Pod無法向該服務發起超過該配置的連接數,單個服務端也不能接受超過該連接數的連接。整個服務端應用服務可接受的連接數計算方法為min(client pod數量, server pod數量) * maxConnections。 | 232-1 |
| int32 | 否 | 等待就緒的連接池連接時,可以排隊等待的最大請求數量。 | 1024 |
| int32 | 否 | 對后端服務的最大活躍請求數。 | 1024 |
在簡單場景中,例如一個客戶端和一個目標服務實例(在Kubernetes環境中,一個實例相當于一個Pod)的情況下參數的配置較為清晰。但在實際生產環境中,可能出現以下場景:
一個客戶端實例和多個目標服務實例。
多個客戶端實例和單個目標服務實例。
多個客戶端實例和多個目標服務實例。
在不同的場景中,需要根據實際需求來調整這些參數的值,以確保連接池能夠適應高負載和復雜的環境,并提供良好的性能和可靠性。下文將針對以上場景配置連接池,幫助您了解該配置對客戶端和目標服務端的約束情況,進而配置適用自身生產環境的熔斷策略。
示例介紹
本文創建兩個Python腳本,一個表示目標服務,另一個表示調用服務的客戶端。
服務器腳本使用Flask框架創建一個應用程序,并在根路由上定義一個API端點。當訪問根路由時,服務器會休眠5秒,然后返回一個包含
"Hello World!"
字符串的JSON響應。#! /usr/bin/env python3 from flask import Flask import time app = Flask(__name__) @app.route('/hello') def get(): time.sleep(5) return 'hello world!' if __name__ == '__main__': app.run(debug=True, host='0.0.0.0', port='9080', threaded = True)
客戶端腳本以10個為一組調用服務器端點,即10個并行請求。在發送下一批10個請求之前,客戶端腳本會休眠一段時間。該腳本會在無限循環中執行此操作。為了確保當運行客戶端的多個Pod時,它們都同時發送批處理,本示例使用系統時間(每分鐘的第0、20和40秒)發送批處理。
#! /usr/bin/env python3 import requests import time import sys from datetime import datetime import _thread def timedisplay(t): return t.strftime("%H:%M:%S") def get(url): try: stime = datetime.now() start = time.time() response = requests.get(url) etime = datetime.now() end = time.time() elapsed = end-start sys.stderr.write("Status: " + str(response.status_code) + ", Start: " + timedisplay(stime) + ", End: " + timedisplay(etime) + ", Elapsed Time: " + str(elapsed)+"\n") sys.stdout.flush() except Exception as myexception: sys.stderr.write("Exception: " + str(myexception)+"\n") sys.stdout.flush() time.sleep(30) while True: sc = int(datetime.now().strftime('%S')) time_range = [0, 20, 40] if sc not in time_range: time.sleep(1) continue sys.stderr.write("\n----------Info----------\n") sys.stdout.flush() # Send 10 requests in parallel for i in range(10): _thread.start_new_thread(get, ("http://circuit-breaker-sample-server:9080/hello", )) time.sleep(2)
部署示例應用
使用以下內容創建YAML文件,然后執行
kubectl apply -f ${YAML文件名稱}.yaml
命令,部署示例應用。################################################################################################## # circuit-breaker-sample-server services ################################################################################################## apiVersion: v1 kind: Service metadata: name: circuit-breaker-sample-server labels: app: circuit-breaker-sample-server service: circuit-breaker-sample-server spec: ports: - port: 9080 name: http selector: app: circuit-breaker-sample-server --- apiVersion: apps/v1 kind: Deployment metadata: name: circuit-breaker-sample-server labels: app: circuit-breaker-sample-server version: v1 spec: replicas: 1 selector: matchLabels: app: circuit-breaker-sample-server version: v1 template: metadata: labels: app: circuit-breaker-sample-server version: v1 spec: containers: - name: circuit-breaker-sample-server image: registry.cn-hangzhou.aliyuncs.com/acs/istio-samples:circuit-breaker-sample-server.v1 imagePullPolicy: Always ports: - containerPort: 9080 --- ################################################################################################## # circuit-breaker-sample-client services ################################################################################################## apiVersion: apps/v1 kind: Deployment metadata: name: circuit-breaker-sample-client labels: app: circuit-breaker-sample-client version: v1 spec: replicas: 1 selector: matchLabels: app: circuit-breaker-sample-client version: v1 template: metadata: labels: app: circuit-breaker-sample-client version: v1 spec: containers: - name: circuit-breaker-sample-client image: registry.cn-hangzhou.aliyuncs.com/acs/istio-samples:circuit-breaker-sample-client.v1 imagePullPolicy: Always
執行以下命令,查看客戶端和服務器端對應的Pod。
kubectl get po |grep circuit
預期輸出:
circuit-breaker-sample-client-d4f64d66d-fwrh4 2/2 Running 0 1m22s circuit-breaker-sample-server-6d6ddb4b-gcthv 2/2 Running 0 1m22s
在沒有明確定義目標規則限制的情況下,服務器端可以處理并發的10個客戶端請求,因此服務器的響應結果始終為200??蛻舳说娜罩臼纠缦拢?/p>
----------Info----------
Status: 200, Start: 02:39:20, End: 02:39:25, Elapsed Time: 5.016539812088013
Status: 200, Start: 02:39:20, End: 02:39:25, Elapsed Time: 5.012614488601685
Status: 200, Start: 02:39:20, End: 02:39:25, Elapsed Time: 5.015984535217285
Status: 200, Start: 02:39:20, End: 02:39:25, Elapsed Time: 5.015599012374878
Status: 200, Start: 02:39:20, End: 02:39:25, Elapsed Time: 5.012874364852905
Status: 200, Start: 02:39:20, End: 02:39:25, Elapsed Time: 5.018714904785156
Status: 200, Start: 02:39:20, End: 02:39:25, Elapsed Time: 5.010422468185425
Status: 200, Start: 02:39:20, End: 02:39:25, Elapsed Time: 5.012431621551514
Status: 200, Start: 02:39:20, End: 02:39:25, Elapsed Time: 5.011001348495483
Status: 200, Start: 02:39:20, End: 02:39:25, Elapsed Time: 5.01432466506958
配置連接池
通過服務網格技術啟用熔斷規則,只需要針對目標服務定義對應的目標規則DestinationRule即可。
使用以下內容,創建目標規則。具體操作,請參見管理目標規則。該目標規則定義與目標服務的最大TCP連接數為5。
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: circuit-breaker-sample-server
spec:
host: circuit-breaker-sample-server
trafficPolicy:
connectionPool:
tcp:
maxConnections: 5
場景一:一個客戶端Pod和一個目標服務Pod
啟動客戶端Pod并監控日志。
建議重啟下客戶端以獲得更直觀的統計結果??梢钥吹筋愃迫缦氯罩荆?/p>
----------Info---------- Status: 200, Start: 02:49:40, End: 02:49:45, Elapsed Time: 5.0167787075042725 Status: 200, Start: 02:49:40, End: 02:49:45, Elapsed Time: 5.011920690536499 Status: 200, Start: 02:49:40, End: 02:49:45, Elapsed Time: 5.017078161239624 Status: 200, Start: 02:49:40, End: 02:49:45, Elapsed Time: 5.018405437469482 Status: 200, Start: 02:49:40, End: 02:49:45, Elapsed Time: 5.018689393997192 Status: 200, Start: 02:49:40, End: 02:49:50, Elapsed Time: 10.018936395645142 Status: 200, Start: 02:49:40, End: 02:49:50, Elapsed Time: 10.016417503356934 Status: 200, Start: 02:49:40, End: 02:49:50, Elapsed Time: 10.019930601119995 Status: 200, Start: 02:49:40, End: 02:49:50, Elapsed Time: 10.022735834121704 Status: 200, Start: 02:49:40, End: 02:49:55, Elapsed Time: 15.02303147315979
可以看到所有請求都成功。但是,每批中只有5個請求的響應時間約為5秒,其余請求的響應較慢(大部分為10秒以上)。該結果表明僅使用
tcp.maxConnections
會導致過多的請求排隊,等待連接釋放。默認情況下,可以排隊的請求數為232-1。使用以下內容,更新目標規則,僅允許1個待處理請求。具體操作,請參見管理目標規則。
為了實現真正的熔斷行為(即快速失敗),您還需要設置
http.http1MaxPendingRequests
限制排隊的請求數量。該參數的默認值為1024。如果將該參數設置為0,將回滾到默認值。因此,必須至少將其設置為1。apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: circuit-breaker-sample-server spec: host: circuit-breaker-sample-server trafficPolicy: connectionPool: tcp: maxConnections: 5 http: http1MaxPendingRequests: 1
重啟客戶端Pod,避免統計結果出現偏差,并繼續觀察日志。
日志示例如下:
----------Info---------- Status: 503, Start: 02:56:40, End: 02:56:40, Elapsed Time: 0.005339622497558594 Status: 503, Start: 02:56:40, End: 02:56:40, Elapsed Time: 0.007254838943481445 Status: 503, Start: 02:56:40, End: 02:56:40, Elapsed Time: 0.0044133663177490234 Status: 503, Start: 02:56:40, End: 02:56:40, Elapsed Time: 0.008964776992797852 Status: 200, Start: 02:56:40, End: 02:56:45, Elapsed Time: 5.018309116363525 Status: 200, Start: 02:56:40, End: 02:56:45, Elapsed Time: 5.017424821853638 Status: 200, Start: 02:56:40, End: 02:56:45, Elapsed Time: 5.019804954528809 Status: 200, Start: 02:56:40, End: 02:56:45, Elapsed Time: 5.01643180847168 Status: 200, Start: 02:56:40, End: 02:56:45, Elapsed Time: 5.025975227355957 Status: 200, Start: 02:56:40, End: 02:56:50, Elapsed Time: 10.01716136932373
可以看到4個請求立即被限制,5個請求發送到目標服務,1個請求排隊,符合預期。
執行以下命令,查看客戶端Istio代理與目標服務中的Pod建立的活躍連接數。
kubectl exec $(kubectl get pod --selector app=circuit-breaker-sample-client --output jsonpath='{.items[0].metadata.name}') -c istio-proxy -- curl -X POST http://localhost:15000/clusters | grep circuit-breaker-sample-server | grep cx_active
預期輸出:
outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local::172.20.192.124:9080::cx_active::5
可以看到客戶端Istio代理與目標服務中的Pod建立的活躍連接數為5。
場景二:一個客戶端Pod和多個目標服務Pod
本小節將驗證連接數限制是否應用于Pod級別或服務級別。假設有一個客戶端Pod和三個目標服務Pod。
若連接數限制應用于Pod級別,目標服務的每個Pod最多5個連接。
該場景應該看不到限制或排隊,因為允許的最大連接數為15(3個Pod,每個Pod為5個連接)。由于一次只發送10個請求,所有請求都應該成功并在大約5秒內返回。
若連接數限制應用于服務級別,無論目標服務中的Pod數量為多少,總共最多5個連接。
該場景可以看到4個請求立即被限制,5個請求發送到目標服務,1個請求排隊。
執行以下命令,將目標服務部署擴展到多個副本(例如3個)。
kubectl scale deployment/circuit-breaker-sample-server --replicas=3
重啟客戶端Pod并監控日志。
日志示例如下:
----------Info---------- Status: 503, Start: 03:06:20, End: 03:06:20, Elapsed Time: 0.011791706085205078 Status: 503, Start: 03:06:20, End: 03:06:20, Elapsed Time: 0.0032286643981933594 Status: 503, Start: 03:06:20, End: 03:06:20, Elapsed Time: 0.012153387069702148 Status: 503, Start: 03:06:20, End: 03:06:20, Elapsed Time: 0.011871814727783203 Status: 200, Start: 03:06:20, End: 03:06:25, Elapsed Time: 5.012892484664917 Status: 200, Start: 03:06:20, End: 03:06:25, Elapsed Time: 5.013102769851685 Status: 200, Start: 03:06:20, End: 03:06:25, Elapsed Time: 5.016939163208008 Status: 200, Start: 03:06:20, End: 03:06:25, Elapsed Time: 5.014261484146118 Status: 200, Start: 03:06:20, End: 03:06:25, Elapsed Time: 5.01246190071106 Status: 200, Start: 03:06:20, End: 03:06:30, Elapsed Time: 10.021712064743042
可以看到如上類似的限制和排隊,表明增加目標服務的實例數量不會增加客戶端的連接數限制。因此,連接數限制應用于服務級別。
運行一段時間之后,執行以下命令,查看客戶端Istio代理與目標服務中的Pod建立的活躍連接數。
kubectl exec $(kubectl get pod --selector app=circuit-breaker-sample-client --output jsonpath='{.items[0].metadata.name}') -c istio-proxy -- curl -X POST http://localhost:15000/clusters | grep circuit-breaker-sample-server | grep cx_active
預期輸出:
outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local::172.20.192.124:9080::cx_active::2 outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local::172.20.192.158:9080::cx_active::2 outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local::172.20.192.26:9080::cx_active::2
可以看到客戶端代理與目標服務中的每個Pod有2個活動連接,總共6個連接,而不是5個。如Envoy和Istio文檔中所述,代理在連接數量方面具有一定的彈性。
場景三:多個客戶端Pod和一個目標服務Pod
執行以下命令,調整目標服務和客戶端的副本數。
kubectl scale deployment/circuit-breaker-sample-server --replicas=1 kubectl scale deployment/circuit-breaker-sample-client --replicas=3
重啟客戶端Pod并監控日志。
Client 1 ----------Info---------- Status: 503, Start: 03:10:40, End: 03:10:40, Elapsed Time: 0.008828878402709961 Status: 503, Start: 03:10:40, End: 03:10:40, Elapsed Time: 0.010806798934936523 Status: 503, Start: 03:10:40, End: 03:10:40, Elapsed Time: 0.012855291366577148 Status: 503, Start: 03:10:40, End: 03:10:40, Elapsed Time: 0.004465818405151367 Status: 503, Start: 03:10:40, End: 03:10:40, Elapsed Time: 0.007823944091796875 Status: 503, Start: 03:10:40, End: 03:10:40, Elapsed Time: 0.06221342086791992 Status: 503, Start: 03:10:40, End: 03:10:40, Elapsed Time: 0.06922149658203125 Status: 503, Start: 03:10:40, End: 03:10:40, Elapsed Time: 0.06859922409057617 Status: 200, Start: 03:10:40, End: 03:10:45, Elapsed Time: 5.015282392501831 Status: 200, Start: 03:10:40, End: 03:10:50, Elapsed Time: 9.378434181213379 Client 2 ----------Info---------- Status: 503, Start: 03:11:00, End: 03:11:00, Elapsed Time: 0.007795810699462891 Status: 503, Start: 03:11:00, End: 03:11:00, Elapsed Time: 0.00595545768737793 Status: 503, Start: 03:11:00, End: 03:11:00, Elapsed Time: 0.013380765914916992 Status: 503, Start: 03:11:00, End: 03:11:00, Elapsed Time: 0.004278898239135742 Status: 503, Start: 03:11:00, End: 03:11:00, Elapsed Time: 0.010999202728271484 Status: 200, Start: 03:11:00, End: 03:11:05, Elapsed Time: 5.015426874160767 Status: 200, Start: 03:11:00, End: 03:11:05, Elapsed Time: 5.0184690952301025 Status: 200, Start: 03:11:00, End: 03:11:05, Elapsed Time: 5.019806146621704 Status: 200, Start: 03:11:00, End: 03:11:05, Elapsed Time: 5.0175628662109375 Status: 200, Start: 03:11:00, End: 03:11:05, Elapsed Time: 5.031521558761597 Client 3 ----------Info---------- Status: 503, Start: 03:13:20, End: 03:13:20, Elapsed Time: 0.012019157409667969 Status: 503, Start: 03:13:20, End: 03:13:20, Elapsed Time: 0.012546539306640625 Status: 503, Start: 03:13:20, End: 03:13:20, Elapsed Time: 0.013760805130004883 Status: 503, Start: 03:13:20, End: 03:13:20, Elapsed Time: 0.014089822769165039 Status: 503, Start: 03:13:20, End: 03:13:20, Elapsed Time: 0.014792442321777344 Status: 503, Start: 03:13:20, End: 03:13:20, Elapsed Time: 0.015463829040527344 Status: 503, Start: 03:13:20, End: 03:13:20, Elapsed Time: 0.01661539077758789 Status: 200, Start: 03:13:20, End: 03:13:20, Elapsed Time: 0.02904224395751953 Status: 200, Start: 03:13:20, End: 03:13:20, Elapsed Time: 0.03912043571472168 Status: 200, Start: 03:13:20, End: 03:13:20, Elapsed Time: 0.06436014175415039
每個客戶端上的503錯誤數量增加。系統限制了來自所有三個客戶端實例Pod的并發請求為5個。
查看客戶端代理日志。
{"authority":"circuit-breaker-sample-server:9080","bytes_received":"0","bytes_sent":"81","downstream_local_address":"192.168.142.207:9080","downstream_remote_address":"172.20.192.31:44610","duration":"0","istio_policy_status":"-","method":"GET","path":"/hello","protocol":"HTTP/1.1","request_id":"d9d87600-cd01-421f-8a6f-dc0ee0ac8ccd","requested_server_name":"-","response_code":"503","response_flags":"UO","route_name":"default","start_time":"2023-02-28T03:14:00.095Z","trace_id":"-","upstream_cluster":"outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local","upstream_host":"-","upstream_local_address":"-","upstream_service_time":"-","upstream_transport_failure_reason":"-","user_agent":"python-requests/2.21.0","x_forwarded_for":"-"} {"authority":"circuit-breaker-sample-server:9080","bytes_received":"0","bytes_sent":"81","downstream_local_address":"192.168.142.207:9080","downstream_remote_address":"172.20.192.31:43294","duration":"58","istio_policy_status":"-","method":"GET","path":"/hello","protocol":"HTTP/1.1","request_id":"931d080a-3413-4e35-91f4-0c906e7ee565","requested_server_name":"-","response_code":"503","response_flags":"URX","route_name":"default","start_time":"2023-02-28T03:12:20.995Z","trace_id":"-","upstream_cluster":"outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local","upstream_host":"172.20.192.84:9080","upstream_local_address":"172.20.192.31:58742","upstream_service_time":"57","upstream_transport_failure_reason":"-","user_agent":"python-requests/2.21.0","x_forwarded_for":"-"}
可以看到有兩種不同類型的日志,用于解釋被限制的請求(503錯誤)。在日志中,
RESPONSE_FLAGS
字段包括了UO
和URX
這兩個值。UO
:表示上游溢出(斷路)。URX
:表示請求被拒絕,因為已達到上游重試限制(HTTP)或最大連接嘗試次數(TCP)。
根據日志中的其他字段的值(例如
DURATION
、UPSTREAM_HOST
和UPSTREAM_CLUSTER
),進一步得出結論:帶有
UO
標志的請求由客戶端代理在本地進行限制,而帶有URX
標志的請求被目標服務代理拒絕。驗證上一步結論的正確性,檢查目標服務端的代理日志。
{"authority":"circuit-breaker-sample-server:9080","bytes_received":"0","bytes_sent":"81","downstream_local_address":"172.20.192.84:9080","downstream_remote_address":"172.20.192.31:59510","duration":"0","istio_policy_status":"-","method":"GET","path":"/hello","protocol":"HTTP/1.1","request_id":"7684cbb0-8f1c-44bf-b591-40c3deff6b0b","requested_server_name":"outbound_.9080_._.circuit-breaker-sample-server.default.svc.cluster.local","response_code":"503","response_flags":"UO","route_name":"default","start_time":"2023-02-28T03:14:00.095Z","trace_id":"-","upstream_cluster":"inbound|9080||","upstream_host":"-","upstream_local_address":"-","upstream_service_time":"-","upstream_transport_failure_reason":"-","user_agent":"python-requests/2.21.0","x_forwarded_for":"-"} {"authority":"circuit-breaker-sample-server:9080","bytes_received":"0","bytes_sent":"81","downstream_local_address":"172.20.192.84:9080","downstream_remote_address":"172.20.192.31:58218","duration":"0","istio_policy_status":"-","method":"GET","path":"/hello","protocol":"HTTP/1.1","request_id":"2aa351fa-349d-4283-a5ea-dc74ecbdff8c","requested_server_name":"outbound_.9080_._.circuit-breaker-sample-server.default.svc.cluster.local","response_code":"503","response_flags":"UO","route_name":"default","start_time":"2023-02-28T03:12:20.996Z","trace_id":"-","upstream_cluster":"inbound|9080||","upstream_host":"-","upstream_local_address":"-","upstream_service_time":"-","upstream_transport_failure_reason":"-","user_agent":"python-requests/2.21.0","x_forwarded_for":"-"}
與預期一致,目標服務代理的日志出現了503響應碼。這也是導致客戶端代理日志中出現
"response_code":"503"
和"response_flags":"URX"
的原因。
總而言之,客戶端代理根據它們的連接數限制(每個Pod最多5個連接)發送請求,并對多余的請求進行排隊或限制(使用UO
響應標志)。在批處理開始時,所有三個客戶端代理最多可以發送15個并發請求。但是,只有5個請求成功,因為目標服務代理也在使用相同的配置(最多5個連接)進行限制。目標服務代理將僅接受5個請求并限制其余請求,這些請求在客戶端代理日志中帶有URX響應標志。
上述場景對應的示意圖如下:
場景四:多個客戶端Pod和多個目標服務Pod
當增加目標服務副本時,應該會看到請求的成功率整體增加,因為每個目標代理可以允許5個并發請求。通過此方式,可以觀察到客戶端和目標服務代理上的限制。
執行以下命令,將目標服務的副本數增加到2,將客戶端的副本數增加到3。
kubectl scale deployment/circuit-breaker-sample-server --replicas=2 kubectl scale deployment/circuit-breaker-sample-client --replicas=3
可以看到所有三個客戶端代理在一個批次中生成的30個請求中有10個請求成功。
執行以下命令,將目標服務的副本數增加到3。
kubectl scale deployment/circuit-breaker-sample-server --replicas=3
可以看到15個成功的請求。
執行以下命令,將目標服務的副本數增加到4。
kubectl scale deployment/circuit-breaker-sample-server --replicas=3
可以看到目標服務的副本數從3增加到4,仍然只有15個成功的請求。無論目標服務有多少個副本,客戶端代理上的限制都適用于整個目標服務。因此,無論有多少個副本,每個客戶端代理最多可以向目標服務發出5個并發請求。
相關操作
查看連接池熔斷相關指標
連接池熔斷通過限制到目標主機的最大TCP連接數來達到熔斷的目的。連接池熔斷可以產生一系列相關指標,以幫助判斷熔斷是否發生,部分指標的說明如下:
指標 | 指標類型 | 描述 |
envoy_cluster_circuit_breakers_default_cx_open | Gauge | 表示當前是否觸發了連接池熔斷。若觸發則為1,沒有觸發則為0. |
envoy_cluster_circuit_breakers_default_rq_pending_open | Gauge | 排隊等待就緒的連接池連接的請求數量是否已經超過給定值。若超過則為1,沒有超過則為0。 |
您可以通過配置Sidecar代理的proxyStatsMatcher使Sidecar代理上報相關指標,然后使用Prometheus采集并查看熔斷相關指標。
通過proxyStatsMatcher配置Sidecar代理上報熔斷指標。在配置proxyStatsMatcher時,選中正則匹配,配置為
.*circuit_breaker.*
。具體操作,請參見proxyStatsMatcher。重新部署circuit-breaker-sample-server和 circuit-breaker-sample-client無狀態工作負載。具體操作,請參見重新部署工作負載。
參照上文步驟,完成連接池熔斷配置及請求訪問。
執行以下命令,查看circuit-breaker-sample-client服務的連接池熔斷相關指標。
kubectl exec -it deploy/circuit-breaker-sample-client -c istio-proxy -- curl localhost:15090/stats/prometheus | grep circuit_breaker | grep circuit-breaker-sample-server
預期輸出:
kubectl exec -it deploy/circuit-breaker-sample-client -c istio-proxy -- curl localhost:15090/stats/prometheus | grep circuit_breaker | grep circuit-breaker-sample-server envoy_cluster_circuit_breakers_default_cx_open{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 1 envoy_cluster_circuit_breakers_default_cx_pool_open{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 0 envoy_cluster_circuit_breakers_default_remaining_cx{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 0 envoy_cluster_circuit_breakers_default_remaining_cx_pools{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 18446744073709551613 envoy_cluster_circuit_breakers_default_remaining_pending{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 1 envoy_cluster_circuit_breakers_default_remaining_retries{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 4294967295 envoy_cluster_circuit_breakers_default_remaining_rq{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 4294967295 envoy_cluster_circuit_breakers_default_rq_open{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 0 envoy_cluster_circuit_breakers_default_rq_pending_open{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 0 envoy_cluster_circuit_breakers_default_rq_retry_open{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 0 envoy_cluster_circuit_breakers_high_cx_open{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 0 envoy_cluster_circuit_breakers_high_cx_pool_open{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 0 envoy_cluster_circuit_breakers_high_rq_open{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 0 envoy_cluster_circuit_breakers_high_rq_pending_open{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 0 envoy_cluster_circuit_breakers_high_rq_retry_open{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 0
配置連接池熔斷指標采集及告警
配置完成連接池熔斷相關指標后,您可以配置采集相關指標到Prometheus,并基于關鍵指標配置告警規則,實現熔斷發生時的及時告警。以下以可觀測監控Prometheus版為例說明如何配置連接池熔斷指標采集和告警。
在可觀測監控Prometheus版中,為數據面集群接入阿里云ASM組件或升級至最新版,以保證可觀測監控Prometheus版可以采集到暴露的熔斷指標。有關更新接入組件的具體操作,參考接入組件管理。(如果參考集成自建Prometheus實現網格監控配置了通過自建Prometheus采集服務網格指標,則無需操作。)
創建針對連接池熔斷的告警規則。具體操作,請參見通過自定義PromQL創建Prometheus告警規則。配置告警規則的關鍵參數的填寫示例如下,其余參數可參考上述文檔根據自身需求填寫。
參數 | 示例 | 說明 |
自定義PromQL語句 | (sum by(cluster_name, pod_name,namespace) (envoy_cluster_circuit_breakers_default_cx_open)) != 0 | 示例通過查詢envoy_cluster_circuit_breakers_default_cx_open指標來判斷當前集群中是否正在發生連接池熔斷,基于上游服務主機名稱,上報指標的pod名稱來確定發生連接池熔斷的位置。 |
告警內容 | 發生連接池熔斷,代理建立的TCP連接已達到最大限制!命名空間:{{$labels.namespace}},觸發連接池熔斷的pod:{{$labels.pod_name}},連接的上游服務信息:{{ $labels.cluster_name }} | 示例的告警信息展示了觸發連接池熔斷的pod,pod連接的上游服務以及pod所在命名空間。 |
連接池約束
連接池配置對客戶端和目標服務端的約束如下。
角色 | 說明 |
客戶端 | 每個客戶端代理獨立應用該限制。如果限制為100,則每個客戶端代理在應用本地限制之前可以有100個未完成的請求。如果有N個客戶端調用目標服務,則總共最多可以有100*N個未完成的請求。 客戶端代理的限制是針對整個目標服務,而不是針對目標服務的單個副本。即使目標服務有200個活動Pod,限流仍然會是100。 |
目標服務端 | 每個目標服務代理應用該限制。如果該服務有50個活動的Pod,則在應用限流并返回503錯誤之前,每個Pod最多可以有100個來自客戶端代理的未完成請求。 |