すべてのプロダクト
Search
ドキュメントセンター

Alibaba Cloud Service Mesh:接続プールを設定してサーキットブレーカーを実装

最終更新日:Mar 11, 2026

マイクロサービスが過負荷状態または部分的な障害に陥った場合、制御されていないトラフィックがシステム全体にカスケードし、健全なサービスまで停止させる可能性があります。ネットワークレベルでのサーキットブレーカー機能(Service Mesh (ASM) のサイドカープロキシ経由)は、バックエンドに到達する前に過剰なトラフィックを拒否します。この方法では、各サービスのアプリケーションコードを変更する必要はありません。Resilience4j などの従来のアプローチでは、サーキットブレーカーのロジックをアプリケーションコードに直接埋め込む必要があります。

connectionPool フィールドを 宛先ルール (DestinationRule) で設定することで、送信先サービスへの同時接続数および保留中のリクエスト数を制限できます。以下のセクションでは、関連パラメーターを説明し、4 種類の Pod スケーリング構成における動作を検証し、本番環境でのサーキットブレーカーのモニタリング方法について解説します。

前提条件

開始する前に、以下の条件を満たしていることを確認してください。

接続プールによるサーキットブレーカーの仕組み

対象サービスに対してサーキットブレーカーを有効化するには、connectionPool 設定を含む 宛先ルール (DestinationRule) を作成します。フィールドの完全なリファレンスについては、「」および「宛先ルール (Destination Rule)」をご参照ください。

接続プールの動作を制御するパラメーターは以下の 3 つです。

パラメーター必須デフォルト値説明
tcp.maxConnectionsint32いいえ2^32−1送信先ホストへの HTTP/1.1 または TCP 接続の最大数。クライアント側およびサーバー側の両方のサイドカープロキシで適用されます。単一のクライアント Pod が開ける接続数はこの値を超えることができず、単一のサーバー Pod が受け入れられる接続数も同様に制限されます。サーバー側の実効的なキャパシティは、min(クライアント Pod 数, サーバー Pod 数) × maxConnections となります。
http.http1MaxPendingRequestsint32いいえ1024利用可能な接続を待機中のキューに格納される最大リクエスト数。この値を 0 に設定するとデフォルト値 (1024) が使用されるため、少なくとも 1 を指定してください。
http.http2MaxRequestsint32いいえ1024バックエンドへのアクティブなリクエストの最大数。
connectionPool フィールドは接続数およびキューイングされたリクエスト数を制限しますが、ロードバランシングプールから不健全なホストを除外しません。エラー率に基づくホスト除外を行うには、同一の 宛先ルール (DestinationRule) 内で connectionPooloutlierDetection を併用してください。「宛先ルール (Destination Rule)」の outlierDetection フィールドについて詳しくは、こちらをご参照ください。

クライアント Pod とサーバー Pod がそれぞれ 1 つの場合、これらのパラメーターは予測可能な動作を示します。しかし、本番環境では通常、サービスが複数の Pod で実行されます。以下に、4 つの一般的なトポロジーにおけるサーキットブレーカーの動作を示します。

  • クライアント Pod が 1 つ、送信先サービスの Pod が 1 つ

  • クライアント Pod が 1 つ、送信先サービスの Pod が複数

  • クライアント Pod が複数、送信先サービスの Pod が 1 つ

  • クライアント Pod が複数、送信先サービスの Pod が複数

サンプルアプリケーションのデプロイ

サンプルセットアップには以下の 2 つのコンポーネントがあります。

  • サーバー:ポート 9080 で /hello エンドポイントをリッスンする Flask アプリケーション。各リクエストの処理には 5 秒かかります(遅いバックエンドを模擬)。

  • クライアント:1 回のバッチで 10 件の並列リクエストを送信する Python スクリプト。バッチは毎分の 0 秒、20 秒、40 秒に発行されるため、複数のクライアント Pod が同時にリクエストを送信します。

  1. 以下の YAML を保存し、kubectl apply -f <file-name>.yaml を実行して、サンプルアプリケーションをデプロイします。

    サーバースクリプト

    #!/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)

    クライアントスクリプト

    #!/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

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

宛先ルール (DestinationRule) を設定していない場合、サーバーはすべての 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) の作成

送信先サービスに対してサーキットブレーカーを有効化するには、宛先ルール (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

シナリオ 1:クライアント Pod が 1 つ、送信先サービスの Pod が 1 つ

  1. クライアント Pod を再起動し、そのログを確認します。10 件のリクエストすべてが成功しますが、約 5 秒で完了するのは 5 件のみです。残りのリクエストは、接続が解放されるまでキューに待機するため、10 秒以上かかります。tcp.maxConnections のみを設定した場合、過剰なリクエストは失敗するのではなくキューに格納されます。デフォルトのキュー深さは 2^32 − 1 です。

    ----------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
  2. 即時失敗(fail-fast)型のサーキットブレーカーを実現するには、http.http1MaxPendingRequests も制限します。宛先ルール (DestinationRule) を更新してください。詳細については、「宛先ルールの管理」をご参照ください。

    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 を再起動し、そのログを確認します。4 件のリクエストは即時に拒否され(ステータスコード 503)、5 件が送信先に到達し、1 件はキューに格納されて(空き接続を待って)約 10 秒後に完了します。

    ----------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. クライアントのサイドカープロキシからアクティブ接続数を確認します。想定される出力:クライアントプロキシから送信先 Pod へのアクティブ接続が 5 件であり、maxConnections 制限と一致します。

    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

シナリオ 2:クライアント Pod が 1 つ、送信先サービスの Pod が複数

このシナリオでは、接続制限が Pod 単位で適用されるか、サービス単位で適用されるかを検証します。クライアント Pod が 1 つ、送信先サービスの Pod が 3 つの場合:

  • Pod 単位の制限:各 Pod が 5 接続を許可するため、合計で 15 接続になります。10 件のリクエストすべてが約 5 秒で成功するはずです。

  • サービス単位の制限:Pod 数に関係なく、合計で 5 接続のみ許可されます。スロットル動作はシナリオ 1 と一致します。

  1. 送信先サービスを 3 レプリカにスケールします。

    kubectl scale deployment/circuit-breaker-sample-server --replicas=3
  2. クライアント Pod を再起動し、そのログを確認します。スロットルパターンはシナリオ 1 と同一です。送信先 Pod を増やしても、クライアントの接続制限は向上しません。接続制限は 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. アクティブ接続の分散状況を確認します。想定される出力:プロキシは接続を各 Pod に分散しており、各 Pod に 2 接続、合計 6 接続(5 接続ではない)となっています。Envoy および Istio のドキュメントにも記載されている通り、プロキシは接続数に関して若干の許容範囲を設けています。

    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

シナリオ 3:クライアント Pod が複数、送信先サービスの Pod が 1 つ

  1. レプリカの調整: サーバーを 1 に、クライアントを 3 にスケール

    kubectl scale deployment/circuit-breaker-sample-server --replicas=1
    kubectl scale deployment/circuit-breaker-sample-client --replicas=3
  2. クライアント Pod を再起動し、そのログを確認します。

    クライアントのログ

    クライアント 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

    クライアント 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

    クライアント 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 エラーの発生率が上昇します。各クライアントのサイドカープロキシは、独自に 5 接続の制限を適用しますが、単一の送信先サービスのサイドカープロキシもまた 5 接続の制限を適用します。すべてのクライアントからのリクエストの中で、同時に成功できるのは最大 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 を返します。

    フラグ意味発生箇所
    UOUpstream overflow(サーキットブレーカー)クライアントのサイドカープロキシがリクエストをローカルでスロットル
    URXUpstream retry/connection limit exceeded送信先サービスのサイドカープロキシがリクエストを拒否

    アクセスログの DURATIONUPSTREAM_HOST、および UPSTREAM_CLUSTER を確認することで、これら 2 つのフラグを区別できます。UO のリクエストは upstream host が存在せず(送信前にスロットル)、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":"-"}

    送信先サービスのサイドカープロキシも、UO フラグとともにステータスコード 503 を返します。これは、クライアントのサイドカープロキシのログに表示される URX エントリが、送信先サービスのサイドカープロキシによって過剰な接続が拒否された結果であることを確認します。

リクエストフローのまとめ

各クライアントのサイドカープロキシは、独自に 5 接続の制限を適用します。クライアントが 3 つある場合、クライアントのサイドカープロキシから並列で送出されるリクエストは最大 15 件になります。しかし、単一の送信先サービスのサイドカープロキシもまた 5 接続の制限を適用するため、5 件のみを受け入れ、残りは拒否します。拒否されたリクエストは、クライアントのサイドカープロキシのログに URX として表示されます。

image

シナリオ 4:クライアント Pod が複数、送信先サービスの Pod が複数

送信先サービスのスケーリングにより、全体的な成功確率が向上します。これは、各送信先 Pod のサイドカープロキシが独立して 5 接続を許可するためです。

  1. 送信先サービスを 2 レプリカ、クライアントを 3 レプリカに設定します。送信先 Pod が 2 つ(それぞれ 5 接続を許可)の場合、3 クライアントから送信される合計 30 件のリクエストのうち、1 バッチあたり 10 件が成功します。

    kubectl scale deployment/circuit-breaker-sample-server --replicas=2
    kubectl scale deployment/circuit-breaker-sample-client --replicas=3
  2. 送信先サービスを 3 レプリカにスケールします。1 バッチあたり 15 件のリクエストが成功します。

    kubectl scale deployment/circuit-breaker-sample-server --replicas=3
  3. 送信先サービスを 4 レプリカにスケールします。それでも成功するのは依然として 15 件のみです。クライアントのサイドカープロキシの制限は、利用可能な送信先 Pod 数に関係なくクライアントごとに 5 接続で固定されています。クライアントが 3 つある場合、成功する同時リクエストの最大数は 3 × 5 = 15 件です。

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

クライアントおよびサーバーの制約のまとめ

役割制限の適用方法
クライアント各クライアントのサイドカープロキシが独立して制限を適用します。maxConnections が 100 で、クライアント Pod 数が N の場合、すべてのクライアント間で最大 N × 100 件のリクエストが並列で送信可能です。この制限は個々の送信先 Pod ではなく、送信先サービス全体に適用されます。送信先 Pod が 200 個あっても、単一のクライアントのサイドカープロキシは 100 接続で上限となります。
送信先サービス各送信先 Pod のサイドカープロキシが独立して制限を適用します。アクティブな Pod が 50 個あり、maxConnections が 100 に設定されている場合、各 Pod はクライアントのサイドカープロキシから最大 100 接続を受け入れ、それ以上の接続はステータスコード 503 で拒否します。

サーキットブレーカーのメトリックのモニタリング

サーキットブレーカーが作動すると、Envoy はスロットルの検出および診断のためのメトリックを生成します。

メトリックタイプ説明
envoy_cluster_circuit_breakers_default_cx_openGauge1 の場合、接続プールのサーキットブレーカーがオープン(作動中)です。0 の場合は、閉じています。
envoy_cluster_circuit_breakers_default_rq_pending_openGauge1 の場合、保留中のリクエストキューがその上限に達しています。0 の場合は、上限未達です。

サーキットブレーカーのメトリックの有効化

  1. サイドカープロキシの proxyStatsMatcher を設定します。正規表現マッチ を選択し、値を .*circuit_breaker.* に設定します。詳細については、「proxyStatsMatcher」をご参照ください。

  2. circuit-breaker-sample-server および circuit-breaker-sample-client のデプロイメントを再デプロイします。詳細については、「ワークロードの再デプロイ」をご参照ください。

  3. 前述のシナリオからサーキットブレーカーのテストを再実行します。

  4. クライアントのサイドカープロキシからメトリックを照会します。想定される出力:

    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

サーキットブレーカーのアラート設定

Managed Service for Prometheus を使用してサーキットブレーカーのメトリックを収集し、アラートルールを設定します。コンポーネント統合の詳細については、「コンポーネントの管理」をご参照ください。

すでに自己管理型の Prometheus インスタンスを使用して ASM のメトリックを収集している場合(「自己管理型 Prometheus インスタンスを使用した ASM インスタンスのモニタリング」をご参照ください)は、ステップ 1 をスキップしてください。
  1. Managed Service for Prometheus で、データプレーンのクラスターを Alibaba Cloud ASM コンポーネントに接続するか、最新バージョンにアップグレードします。

  2. カスタム PromQL 文を使用してアラートルールを作成します。詳細については、「カスタム PromQL 文を使用したアラートルールの作成」をご参照ください。以下のパラメーターを参考にしてください。

    パラメーター説明
    カスタム PromQL 文(sum by(cluster_name, pod_name, namespace) (envoy_cluster_circuit_breakers_default_cx_open)) != 0任意の接続プールでサーキットブレーカーが作動しているかどうかをチェックします。上流サービス名、Pod、名前空間でグループ化することで、スロットルが発生している場所を特定できます。
    アラートメッセージサーキットブレーカーが作動しています。TCP 接続制限に達しました。名前空間:{{$labels.namespace}}、Pod:{{$labels.pod_name}}、上流サービス:{{$labels.cluster_name}}影響を受ける Pod、その名前空間、および上流サービスを特定します。