全部產品
Search
文件中心

Alibaba Cloud Service Mesh:配置串連池實現熔斷功能

更新時間:Sep 12, 2024

熔斷是一種流量管理的策略,用於在系統出現故障或超負荷的情況下,保護系統免受進一步的損害。在傳統的Java服務中,使用Resilience4j等架構可以實現熔斷功能。然而,與傳統方式相比,Istio的熔斷功能在網路層級提供支援,不需要在每個服務的應用程式代碼中進行整合。您可以通過配置串連池來實現熔斷功能,提高系統的穩定性和可靠性,保護目標服務免受異常請求的影響。

前提條件

已添加叢集到ASM執行個體

串連池參數說明

啟用熔斷功能前,您需要建立一個目標規則為目標服務配置熔斷。關於目標規則的欄位說明,請參見Destination Rule

串連池connectionPool欄位定義了與熔斷功能相關的參數。常見的串連池參數說明如下。

參數

類型

是否必選

說明

預設值

tcp.maxConnections

int32

到目標主機的最大HTTP1或TCP串連數。串連數限制會在用戶端及服務端 Sidecar 兩側均生效,即,單個用戶端Pod無法向該服務發起超過該配置的串連數,單個服務端也不能接受超過該串連數的串連。整個服務端應用服務可接受的串連數計算方法為min(client pod數量, server pod數量) * maxConnections。

2³²-1

http.http1MaxPendingRequests

int32

等待就緒的串連池串連時,可以排隊等待的最大請求數量。

1024

http.http2MaxRequests

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)

部署樣本應用

  1. 使用以下內容建立YAML檔案,然後執行kubectl apply -f ${YAML檔案名稱}.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
            
  2. 執行以下命令,查看用戶端和伺服器端對應的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。用戶端的日誌樣本如下:

----------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

  1. 啟動用戶端Pod並監控日誌。

    建議重啟下用戶端以獲得更直觀的統計結果。可以看到類似如下日誌:

    ----------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會導致過多的請求排隊,等待串連釋放。預設情況下,可以排隊的請求數為2³²-1。

  2. 使用以下內容,更新目標規則,僅允許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
  3. 重啟用戶端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個請求排隊,符合預期。

  4. 執行以下命令,查看用戶端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個請求排隊。

  1. 執行以下命令,將目標服務部署擴充到多個副本(例如3個)。

    kubectl scale deployment/circuit-breaker-sample-server  --replicas=3
  2. 重啟用戶端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

    可以看到如上類似的限制和排隊,表明增加目標服務的執行個體數量不會增加用戶端的串連數限制。因此,串連數限制應用於服務等級。

  3. 運行一段時間之後,執行以下命令,查看用戶端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

  1. 執行以下命令,調整目標服務和用戶端的副本數。

    kubectl scale deployment/circuit-breaker-sample-server --replicas=1 
    kubectl scale deployment/circuit-breaker-sample-client --replicas=3
  2. 重啟用戶端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個。

  3. 查看用戶端代理日誌。

    展開查看用戶端代理日誌

    {"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欄位包括了UOURX這兩個值。

    • UO:表示上遊溢出(斷路)。

    • URX:表示請求被拒絕,因為已達到上遊重試限制(HTTP)或最大串連嘗試次數(TCP)。

    根據日誌中的其他欄位的值(例如DURATIONUPSTREAM_HOSTUPSTREAM_CLUSTER),進一步得出結論:

    帶有UO標誌的請求由用戶端代理在本地進行限制,而帶有URX標誌的請求被目標服務代理拒絕。

  4. 驗證上一步結論的正確性,檢查目標服務端的代理日誌。

    展開查看目標服務端的代理日誌

    {"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個並發請求。通過此方式,可以觀察到用戶端和目標服務代理上的限制。

  1. 執行以下命令,將目標服務的副本數增加到2,將用戶端的副本數增加到3。

    kubectl scale deployment/circuit-breaker-sample-server --replicas=2
    kubectl scale deployment/circuit-breaker-sample-client --replicas=3

    可以看到所有三個用戶端代理在一個批次中產生的30個請求中有10個請求成功。

  2. 執行以下命令,將目標服務的副本數增加到3。

    kubectl scale deployment/circuit-breaker-sample-server --replicas=3

    可以看到15個成功的請求。

  3. 執行以下命令,將目標服務的副本數增加到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採集並查看熔斷相關指標。

  1. 通過proxyStatsMatcher配置Sidecar代理上報熔斷指標。在配置proxyStatsMatcher時,選中正則匹配,配置為.*circuit_breaker.*。具體操作,請參見proxyStatsMatcher

  2. 重新部署circuit-breaker-sample-server和 circuit-breaker-sample-client無狀態工作負載。具體操作,請參見重新部署工作負載

  3. 參照上文步驟,完成串連池熔斷配置及請求訪問。

  4. 執行以下命令,查看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版為例說明如何配置串連池熔斷指標採集和警示。

  1. 在可觀測監控Prometheus版中,為資料面叢集接入阿里雲ASM組件或升級至最新版,以保證可觀測監控Prometheus版可以採集到暴露的熔斷指標。有關更新接入組件的具體操作,參考接入組件管理。(如果參考整合自建Prometheus實現網格監控配置了通過自建Prometheus採集服務網格指標,則無需操作。)

  2. 建立針對串連池熔斷的警示規則。具體操作,請參見通過自訂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個來自用戶端代理的未完成請求。