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

Alibaba Cloud Service Mesh:ASMAdaptiveConcurrency を使用した適応型同時実行制御の実装

最終更新日:Mar 11, 2026

静的サーキットブレーカーでは、各サービスごとに固定の同時実行数しきい値を推定し、手動で設定する必要があります。この推定値が低すぎると正当なトラフィックがブロックされ、高すぎるとサーキットブレーカーが作動する前にサービスが過負荷状態になります。ASMAdaptiveConcurrency カスタムリソース定義 (CRD) は、リアルタイムのレイテンシ測定に基づいて同時実行数の上限を動的に調整することで、このような推定作業を不要にし、手動チューニングなしでサービスの実際の処理能力に近い上限値を維持します。

同時リクエスト数が計算された上限値を超えると、サイドカープロキシは HTTP ステータスコード 503 およびエラーメッセージ reached concurrency limit を返します。

仕組み

適応型同時実行制御コントローラーは、勾配ベースのアルゴリズムを使用して、サービスのベースラインレイテンシ(MinRTT)を定期的に測定し、サンプリングされたリクエストのレイテンシ(SampleRTT)と比較して、同時実行数の上限値を調整します。

勾配の計算

コントローラーは、サンプリングされたレイテンシから以下の式で勾配値を計算します。

gradient = (minRTT + buffer) / sampleRTT

バッファーは通常のレイテンシ分散を吸収するため、サンプリングされたレイテンシがベースラインを有意に上回った場合にのみ勾配が低下します。

buffer = minRTT * buffer_pct

その後、この勾配を使って同時実行数の上限値が更新されます。

new_limit = gradient * current_limit + headroom

サービスが正常な状態では、sampleRTTminRTT に近い値を維持し、勾配は 1.0 近辺で安定するため、上限値も安定または増加します。一方、サービスが過負荷になると sampleRTT が上昇し、勾配が 1.0 未満に低下して上限値が減少します。これにより、サービスの状態がさらに悪化する前に超過分のリクエストが拒否されます。

MinRTT の再計算

コントローラーは、同時実行数の上限を一時的に min_concurrency 値まで下げることで、定期的に MinRTT を再計算します。この期間中は、ごく少数のリクエストのみが転送されるため、サービスは真の最小レイテンシで応答できます。

重要

MinRTT 再計算中は同時実行数の上限が大幅に低下するため、HTTP 503 応答が一時的に急増する可能性があります。これを軽減するには、対象サービスに対してリトライを有効にする宛先ルールを作成してください。これにより、サイドカープロキシは MinRTT 再計算ウィンドウにない他のホストに対して拒否されたリクエストを再試行できます。

前提条件

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

ステップ 1:サンプルアプリケーションのデプロイ

本チュートリアルでは、適応型同時実行制御をデモンストレーションするために、以下の 2 つのアプリケーションを使用します。

アプリケーション役割構成
testserver対象サービス最大 500 の同時リクエストを処理可能。各リクエストの処理時間は 1,000 ms。同時実行数の上限を超えたリクエストはキューイングされます。
gotest負荷生成ツール各レプリカが testserver に対して 200 の同時リクエストを送信します。

testserver のデプロイ

  1. 以下の内容で testserver.yaml という名前のファイルを作成します。

    testserver.yaml の表示

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: testserver
      name: testserver
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: testserver
      template:
        metadata:
          creationTimestamp: null
          labels:
            app: testserver
        spec:
          containers:
          - args:
            - -m
            - "500"
            - -t
            - "1000"
            command:
            - /usr/local/bin/limited-concurrency-http-server
            image: registry.cn-hangzhou.aliyuncs.com/acs/asm-limited-concurrency-http-server:v0.1.1-gee0b08f-aliyun
            imagePullPolicy: IfNotPresent
            name: testserver
            ports:
            - containerPort: 8080
              protocol: TCP

    -m フラグは最大同時リクエスト数(500)を設定します。-t フラグは各リクエストの処理時間をミリ秒単位(1,000)で設定します。

  2. デプロイメントを適用します。

    kubectl apply -f testserver.yaml

testserver サービスの作成

  1. 以下の内容で testservice.yaml という名前のファイルを作成します。

    testservice.yaml の表示

    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app: testserver
      name: testserver
      namespace: default
    spec:
      internalTrafficPolicy: Cluster
      ipFamilies:
        - IPv4
      ipFamilyPolicy: SingleStack
      ports:
        - name: http
          port: 8080
          protocol: TCP
          targetPort: 8080
        - name: metrics
          port: 15020
          protocol: TCP
          targetPort: 15020
      selector:
        app: testserver
      type: ClusterIP
  2. サービスを適用します。

    kubectl apply -f testservice.yaml

gotest のデプロイ

  1. 以下の内容で gotest.yaml という名前のファイルを作成します。

    gotest.yaml の表示

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: gotest
      name: gotest
      namespace: default
    spec:
      replicas: 0
      selector:
        matchLabels:
          app: gotest
      template:
        metadata:
          creationTimestamp: null
          labels:
            app: gotest
        spec:
          containers:
          - args:
            - -c
            - "200"
            - -n
            - "10000"
            - -u
            - testserver:8080
            command:
            - /root/go-stress-testing-linux
            image: xocoder/go-stress-testing-linux:v0.1
            imagePullPolicy: Always
            name: gotest
            resources:
              limits:
                cpu: 500m

    初期レプリカ数は 0 に設定されています。ステップ 4 で負荷を生成するためにスケールアップします。

  2. デプロイメントを適用します。

    kubectl apply -f gotest.yaml

ステップ 2:ASMAdaptiveConcurrency CRD の作成

  1. kubectl をご利用の ASM インスタンスに接続します。詳細については、「コントロールプレーン上の kubectl を使用した Istio リソースへのアクセス」をご参照ください。

  2. 以下の内容で adaptiveconcurrency.yaml という名前のファイルを作成します。

    apiVersion: istio.alibabacloud.com/v1beta1
    kind: ASMAdaptiveConcurrency
    metadata:
      name: sample-adaptive-concurrency
      namespace: default
    spec:
      workload_selector:
        labels:
          app: testserver
      sample_aggregate_percentile:
        value: 60
      concurrency_limit_params:
        max_concurrency_limit: 500
        concurrency_update_interval: 15s
      min_rtt_calc_params:
        interval: 60s
        request_count: 100
        jitter:
          value: 15
        min_concurrency: 50
        buffer:
          value: 25

    この構成の意味は以下のとおりです。

    • testserver ワークロードを対象とし、同時リクエスト数の上限を 500 に設定します。

    • サンプリングされたレイテンシの 60 パーセンタイルを SampleRTT として使用し、15 秒ごとに同時実行数の上限を更新します。

    • MinRTT を 60 秒ごと(最大 15% のランダムジッター付き)に再計算し、その際に 100 件のサンプリングリクエストを使用します。MinRTT 再計算中は、同時実行数を 50 リクエストに制限します。

    • MinRTT の 25% 以内のレイテンシ変動は正常範囲と見なします。

  3. CRD を適用します。

    kubectl apply -f adaptiveconcurrency.yaml

パラメーター リファレンス

パラメータータイプ必須デフォルト説明
workload_selectorWorkloadSelectorはい--ラベルで対象の Pod を選択します。
labelsmapはい--対象の Pod と一致させるラベルです。
sample_aggregate_percentilePercentはい--サンプリングされたレイテンシを集約して SampleRTT を算出する際に使用するパーセンタイルです。有効値:0 ~ 100。
concurrency_limit_paramsObjectはい--同時実行数の上限に関する設定です。
max_concurrency_limitintいいえ1000同時リクエスト数の上限値です。
concurrency_update_intervaldurationはい--コントローラーが同時実行数の上限を更新する間隔です。例:60s
min_rtt_calc_paramsObjectはい--MinRTT 計算に関する設定です。
intervaldurationいいえ--MinRTT を再計算する間隔です。例:120s
request_countintいいえ50MinRTT 計算のためにサンプリングするリクエスト数です。
jitterPercentいいえ15MinRTT 再計算間隔に追加されるランダムジッターです。例えば、interval120sjitter50 の場合、実際の間隔は random(120, 120 + 120 * 50%) 秒となります。
min_concurrencyintいいえ3MinRTT 再計算中の同時実行数の上限です。また、コントローラー起動時の初期上限値としても使用されます。正確なベースライン測定を行うため、サービスの実際の処理能力よりも十分に低い値に設定してください。
bufferPercentいいえ25MinRTT に対する許容レイテンシ変動の割合(パーセント)です。例えば、MinRTT が 100 ms、buffer が 10 の場合、110 ms までのレイテンシは正常と見なされます。

ステップ 3:Prometheus によるモニタリングの設定

Managed Service for Prometheus に適応型同時実行制御のメトリックをエクスポートし、コントローラーの動作を観測してパラメーターをチューニングします。

  1. ご利用のクラスターに対して Managed Service for Prometheus を有効化します。詳細については、「Managed Service for Prometheus の使用」をご参照ください。

  2. testserver のサイドカープロキシからメトリックをスクレイプするための ServiceMonitor を作成します。

    1. 以下の内容で servicemonitor.yaml という名前のファイルを作成します。

      apiVersion: monitoring.coreos.com/v1
      kind: ServiceMonitor
      metadata:
        name: testserver-envoy-metrics
        namespace: default
      spec:
        endpoints:
          - interval: 5s
            path: /stats/prometheus
            port: metrics
        namespaceSelector:
          any: true
        selector:
          matchLabels:
            app: testserver
    2. kubectl を ACK クラスターに接続し、ServiceMonitor を適用します。

      kubectl apply -f servicemonitor.yaml
  3. コントローラーメトリックを可視化するための Grafana ダッシュボードをインポートします。ダッシュボードの JSON ファイルをダウンロードし、Managed Service for Grafana コンソールでインポートしてください。インポート手順の詳細については、「ARMS ドキュメント」をご参照ください。

    Grafana ダッシュボード JSON の表示

    {
      "annotations": {
        "list": [
          {
            "builtIn": 1,
            "datasource": "-- Grafana --",
            "enable": true,
            "hide": true,
            "iconColor": "rgba(0, 211, 255, 1)",
            "name": "Annotations & Alerts",
            "type": "dashboard"
          }
        ]
      },
      "description": "monitoring ASM Adaptive Concurrency",
      "editable": true,
      "gnetId": 6693,
      "graphTooltip": 0,
      "id": 3239002,
      "iteration": 1651922323976,
      "links": [],
      "panels": [
        {
          "aliasColors": {},
          "bars": false,
          "dashLength": 10,
          "dashes": false,
          "datasource": "$cluster",
          "fieldConfig": {
            "defaults": { "custom": {} },
            "overrides": []
          },
          "fill": 1,
          "fillGradient": 0,
          "gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 },
          "hiddenSeries": false,
          "id": 22,
          "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false },
          "lines": true,
          "linewidth": 1,
          "nullPointMode": "null",
          "options": { "alertThreshold": true },
          "percentage": false,
          "pluginVersion": "7.4.0-pre",
          "pointradius": 2,
          "points": false,
          "renderer": "flot",
          "seriesOverrides": [],
          "spaceLength": 10,
          "stack": false,
          "steppedLine": false,
          "targets": [
            {
              "expr": "envoy_http_inbound_0_0_0_0_8080_adaptive_concurrency_gradient_controller_rq_blocked{service=\"$service\", pod=\"$pod\"}",
              "interval": "",
              "legendFormat": "{{service}}-{{pod}}",
              "queryType": "randomWalk",
              "refId": "A"
            }
          ],
          "thresholds": [],
          "timeFrom": null,
          "timeRegions": [],
          "timeShift": null,
          "title": "RqBlocked",
          "tooltip": { "shared": true, "sort": 0, "value_type": "individual" },
          "type": "graph",
          "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] },
          "yaxes": [
            { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true },
            { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }
          ],
          "yaxis": { "align": false, "alignLevel": null }
        },
        {
          "aliasColors": {},
          "bars": false,
          "dashLength": 10,
          "dashes": false,
          "datasource": "$cluster",
          "fieldConfig": {
            "defaults": { "custom": {} },
            "overrides": []
          },
          "fill": 1,
          "fillGradient": 0,
          "gridPos": { "h": 8, "w": 12, "x": 12, "y": 0 },
          "hiddenSeries": false,
          "id": 24,
          "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false },
          "lines": true,
          "linewidth": 1,
          "nullPointMode": "null",
          "options": { "alertThreshold": true },
          "percentage": false,
          "pluginVersion": "7.4.0-pre",
          "pointradius": 2,
          "points": false,
          "renderer": "flot",
          "seriesOverrides": [],
          "spaceLength": 10,
          "stack": false,
          "steppedLine": false,
          "targets": [
            {
              "expr": "envoy_http_inbound_0_0_0_0_8080_adaptive_concurrency_gradient_controller_burst_queue_size{service=\"$service\", pod=\"$pod\"}",
              "format": "time_series",
              "interval": "",
              "legendFormat": "{{service}}-{{pod}}",
              "queryType": "randomWalk",
              "refId": "A"
            }
          ],
          "thresholds": [],
          "timeFrom": null,
          "timeRegions": [],
          "timeShift": null,
          "title": "HeadRoom",
          "tooltip": { "shared": true, "sort": 0, "value_type": "individual" },
          "type": "graph",
          "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] },
          "yaxes": [
            { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true },
            { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }
          ],
          "yaxis": { "align": false, "alignLevel": null }
        },
        {
          "aliasColors": {},
          "bars": false,
          "dashLength": 10,
          "dashes": false,
          "datasource": "$cluster",
          "fieldConfig": {
            "defaults": { "custom": {} },
            "overrides": []
          },
          "fill": 1,
          "fillGradient": 0,
          "gridPos": { "h": 8, "w": 12, "x": 0, "y": 8 },
          "hiddenSeries": false,
          "id": 26,
          "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false },
          "lines": true,
          "linewidth": 1,
          "nullPointMode": "null",
          "options": { "alertThreshold": true },
          "percentage": false,
          "pluginVersion": "7.4.0-pre",
          "pointradius": 2,
          "points": false,
          "renderer": "flot",
          "seriesOverrides": [],
          "spaceLength": 10,
          "stack": false,
          "steppedLine": false,
          "targets": [
            {
              "expr": "envoy_http_inbound_0_0_0_0_8080_adaptive_concurrency_gradient_controller_concurrency_limit{service=\"$service\",pod=\"$pod\"}",
              "interval": "",
              "legendFormat": "{{service}}-{{pod}}",
              "queryType": "randomWalk",
              "refId": "A"
            }
          ],
          "thresholds": [],
          "timeFrom": null,
          "timeRegions": [],
          "timeShift": null,
          "title": "ConcurrencyLimit",
          "tooltip": { "shared": true, "sort": 0, "value_type": "individual" },
          "type": "graph",
          "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] },
          "yaxes": [
            { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true },
            { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }
          ],
          "yaxis": { "align": false, "alignLevel": null }
        },
        {
          "aliasColors": {},
          "bars": false,
          "dashLength": 10,
          "dashes": false,
          "datasource": "$cluster",
          "fieldConfig": {
            "defaults": { "custom": {} },
            "overrides": []
          },
          "fill": 1,
          "fillGradient": 0,
          "gridPos": { "h": 8, "w": 12, "x": 12, "y": 8 },
          "hiddenSeries": false,
          "id": 28,
          "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false },
          "lines": true,
          "linewidth": 1,
          "nullPointMode": "null",
          "options": { "alertThreshold": true },
          "percentage": false,
          "pluginVersion": "7.4.0-pre",
          "pointradius": 2,
          "points": false,
          "renderer": "flot",
          "seriesOverrides": [],
          "spaceLength": 10,
          "stack": false,
          "steppedLine": false,
          "targets": [
            {
              "expr": "envoy_http_inbound_0_0_0_0_8080_adaptive_concurrency_gradient_controller_gradient{service=\"$service\",pod=\"$pod\"}",
              "interval": "",
              "legendFormat": "{{service}}-{{pod}}",
              "queryType": "randomWalk",
              "refId": "A"
            }
          ],
          "thresholds": [],
          "timeFrom": null,
          "timeRegions": [],
          "timeShift": null,
          "title": "Gradient",
          "tooltip": { "shared": true, "sort": 0, "value_type": "individual" },
          "type": "graph",
          "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] },
          "yaxes": [
            { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true },
            { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }
          ],
          "yaxis": { "align": false, "alignLevel": null }
        },
        {
          "aliasColors": {},
          "bars": false,
          "dashLength": 10,
          "dashes": false,
          "datasource": "$cluster",
          "fieldConfig": {
            "defaults": { "custom": {} },
            "overrides": []
          },
          "fill": 1,
          "fillGradient": 0,
          "gridPos": { "h": 8, "w": 12, "x": 0, "y": 16 },
          "hiddenSeries": false,
          "id": 32,
          "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false },
          "lines": true,
          "linewidth": 1,
          "nullPointMode": "null",
          "options": { "alertThreshold": true },
          "percentage": false,
          "pluginVersion": "7.4.0-pre",
          "pointradius": 2,
          "points": false,
          "renderer": "flot",
          "seriesOverrides": [],
          "spaceLength": 10,
          "stack": false,
          "steppedLine": false,
          "targets": [
            {
              "expr": "envoy_http_inbound_0_0_0_0_8080_adaptive_concurrency_gradient_controller_min_rtt_msecs{service=\"$service\",pod=\"$pod\"}",
              "interval": "",
              "legendFormat": "{{service}}-{{pod}}",
              "queryType": "randomWalk",
              "refId": "A"
            }
          ],
          "thresholds": [],
          "timeFrom": null,
          "timeRegions": [],
          "timeShift": null,
          "title": "MinRTT(msec)",
          "tooltip": { "shared": true, "sort": 0, "value_type": "individual" },
          "type": "graph",
          "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] },
          "yaxes": [
            { "format": "ms", "label": null, "logBase": 1, "max": null, "min": null, "show": true },
            { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }
          ],
          "yaxis": { "align": false, "alignLevel": null }
        },
        {
          "aliasColors": {},
          "bars": false,
          "dashLength": 10,
          "dashes": false,
          "datasource": "$cluster",
          "fieldConfig": {
            "defaults": { "custom": {} },
            "overrides": []
          },
          "fill": 1,
          "fillGradient": 0,
          "gridPos": { "h": 8, "w": 12, "x": 12, "y": 16 },
          "hiddenSeries": false,
          "id": 34,
          "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false },
          "lines": true,
          "linewidth": 1,
          "nullPointMode": "null",
          "options": { "alertThreshold": true },
          "percentage": false,
          "pluginVersion": "7.4.0-pre",
          "pointradius": 2,
          "points": false,
          "renderer": "flot",
          "seriesOverrides": [],
          "spaceLength": 10,
          "stack": false,
          "steppedLine": false,
          "targets": [
            {
              "expr": "envoy_http_inbound_0_0_0_0_8080_adaptive_concurrency_gradient_controller_sample_rtt_msecs{service=\"$service\",pod=\"$pod\"}",
              "interval": "",
              "legendFormat": "{{service}}-{{pod}}",
              "queryType": "randomWalk",
              "refId": "A"
            }
          ],
          "thresholds": [],
          "timeFrom": null,
          "timeRegions": [],
          "timeShift": null,
          "title": "SampleRTT(msec)",
          "tooltip": { "shared": true, "sort": 0, "value_type": "individual" },
          "type": "graph",
          "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] },
          "yaxes": [
            { "format": "ms", "label": null, "logBase": 1, "max": null, "min": null, "show": true },
            { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }
          ],
          "yaxis": { "align": false, "alignLevel": null }
        },
        {
          "aliasColors": {},
          "bars": false,
          "dashLength": 10,
          "dashes": false,
          "datasource": "test-adaptive-concurrency_1217520382582089",
          "fieldConfig": {
            "defaults": { "custom": {} },
            "overrides": []
          },
          "fill": 1,
          "fillGradient": 0,
          "gridPos": { "h": 8, "w": 12, "x": 0, "y": 24 },
          "hiddenSeries": false,
          "id": 30,
          "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false },
          "lines": true,
          "linewidth": 1,
          "nullPointMode": "null",
          "options": { "alertThreshold": true },
          "percentage": false,
          "pluginVersion": "7.4.0-pre",
          "pointradius": 2,
          "points": false,
          "renderer": "flot",
          "seriesOverrides": [],
          "spaceLength": 10,
          "stack": false,
          "steppedLine": false,
          "targets": [
            {
              "expr": "envoy_http_inbound_0_0_0_0_8080_adaptive_concurrency_gradient_controller_min_rtt_calculation_active{service=\"$service\",pod=\"$pod\"}",
              "interval": "",
              "legendFormat": "{{service}}-{{pod}}",
              "queryType": "randomWalk",
              "refId": "A"
            }
          ],
          "thresholds": [],
          "timeFrom": null,
          "timeRegions": [],
          "timeShift": null,
          "title": "MinRTTCalc",
          "tooltip": { "shared": true, "sort": 0, "value_type": "individual" },
          "type": "graph",
          "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] },
          "yaxes": [
            { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true },
            { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }
          ],
          "yaxis": { "align": false, "alignLevel": null }
        }
      ],
      "refresh": "5s",
      "schemaVersion": 26,
      "style": "dark",
      "tags": [],
      "templating": {
        "list": [
          {
            "current": { "selected": true, "text": "edas120_1217520382582089", "value": "edas120_1217520382582089" },
            "error": null,
            "hide": 0,
            "includeAll": false,
            "label": null,
            "multi": false,
            "name": "cluster",
            "options": [],
            "query": "prometheus",
            "queryValue": "",
            "refresh": 1,
            "regex": "",
            "skipUrlSync": false,
            "type": "datasource"
          },
          {
            "allValue": null,
            "current": { "isNone": true, "selected": false, "text": "None", "value": "" },
            "datasource": "$cluster",
            "definition": "label_values(envoy_http_inbound_0_0_0_0_8080_adaptive_concurrency_gradient_controller_burst_queue_size,service)",
            "error": null,
            "hide": 0,
            "includeAll": false,
            "label": null,
            "multi": false,
            "name": "service",
            "options": [],
            "query": "label_values(envoy_http_inbound_0_0_0_0_8080_adaptive_concurrency_gradient_controller_burst_queue_size,service)",
            "refresh": 2,
            "regex": "",
            "skipUrlSync": false,
            "sort": 1,
            "tagValuesQuery": "",
            "tags": [],
            "tagsQuery": "",
            "type": "query",
            "useTags": false
          },
          {
            "allValue": null,
            "current": { "selected": false, "text": "All", "value": "$__all" },
            "datasource": "$cluster",
            "definition": "label_values(envoy_http_inbound_0_0_0_0_8080_adaptive_concurrency_gradient_controller_concurrency_limit, pod)",
            "error": null,
            "hide": 0,
            "includeAll": true,
            "label": null,
            "multi": true,
            "name": "pod",
            "options": [],
            "query": "label_values(envoy_http_inbound_0_0_0_0_8080_adaptive_concurrency_gradient_controller_concurrency_limit, pod)",
            "refresh": 2,
            "regex": "",
            "skipUrlSync": false,
            "sort": 0,
            "tagValuesQuery": "",
            "tags": [],
            "tagsQuery": "",
            "type": "query",
            "useTags": false
          }
        ]
      },
      "time": { "from": "now-15m", "to": "now" },
      "timepicker": {
        "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
        "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
      },
      "timezone": "",
      "title": "ASM Adaptive Concurrency",
      "uid": "000000084",
      "version": 3
    }

ステップ 4:同時実行制御コントローラーの検証

testserver に対して負荷をかけ、ASMAdaptiveConcurrency CRD が期待通りに同時実行数を制限することを確認します。

  1. gotest デプロイメントを 5 レプリカにスケールします。各レプリカが 200 の同時リクエストを送信するため、合計で 1,000 の同時リクエストが生成され、testserver の処理能力(500 リクエスト)の 2 倍になります。

    1. ACK コンソール にログインします。左側のナビゲーションウィンドウで、クラスター をクリックします。

    2. クラスター ページで、ご利用のクラスターを見つけ、その名前をクリックするか、操作 列の 詳細 をクリックします。

    3. 左側のナビゲーションウィンドウで、ワークロード > デプロイメント を選択します。

    4. デプロイメント ページで、名前空間 を default に設定します。gotest アプリケーションの 操作 列で、その他 > YAML で表示 を選択します。

    5. YAML の編集 ダイアログボックスで、replicas5 に設定し、更新 をクリックします。

  2. ステップ 3 でインポートした Grafana ダッシュボードを開きます。サービスtestserverPodALL に設定します。

  3. ConcurrencyLimit パネルを確認します。同時実行数の上限が 500 未満で安定していることを確認し、コントローラーが testserver を過負荷から保護していることを検証します。RqBlocked パネルには、拒否されたリクエストの累積数が表示されます。

メトリック リファレンス

適応型同時実行制御コントローラーは、以下の Prometheus メトリックをサイドカープロキシ経由で公開します。これらのメトリックを使用してコントローラーの動作を監視し、CRD パラメーターをチューニングできます。

メトリックタイプ説明
rq_blockedCounter同時実行制御コントローラーによって拒否されたリクエストの総数です。
burst_queue_sizeGauge同時実行数の上限計算に使用される現在のヘッドルーム値です。
concurrency_limitGaugeコントローラーによって適用されている現在の同時実行数の上限です。
gradientGauge現在の勾配値です。
min_rtt_msecsGaugeミリ秒単位の現在の MinRTT 測定値です。
sample_rtt_msecsGaugeミリ秒単位の現在の SampleRTT 集計値です。
min_rtt_calculation_activeGaugeコントローラーが MinRTT を再計算しているときに 1 に設定されます。

すべてのメトリックには、envoy_http_inbound_0_0_0_0_8080_adaptive_concurrency_gradient_controller_ という名前空間プレフィックスが付与されます。

本番環境に適用

  • リトライを有効化する:MinRTT 再計算ウィンドウ中に発生する 503 応答を処理するため、対象サービスに対してリトライポリシーを含む宛先ルールを作成します。

  • パラメーターをチューニングする:Grafana ダッシュボードの観測結果に基づき、concurrency_update_intervalmin_concurrencybuffer を調整します。buffer を小さくするとコントローラーはレイテンシ変化に対してより敏感になり、大きくするとより多くの変動を許容します。

  • 自社のワークロードに適用するworkload_selector のラベルを自社の本番ワークロードを指すように変更します。保守的な設定(min_concurrency を想定処理能力よりも十分に低く設定)から始め、メトリックに基づいて段階的に調整してください。