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

Alibaba Cloud Service Mesh:制御された同時実行下で ConcurrencySchedulingPolicy を使用して優先順位に基づくリクエスト スケジューリングを実装する

最終更新日:Jan 13, 2025

このトピックでは、トラフィック スケジューリング スイートによって提供される ConcurrencySchedulingPolicy を使用して、制御された同時実行下で優先順位に基づくリクエスト スケジューリングを実装する方法について説明します。

背景情報

ConcurrencySchedulingPolicy は、同時リクエストの制限に基づいてトラフィックが過負荷になっているかどうかを判断します。同時リクエスト数が指定された上限を超えると、後続のリクエストはキューに入れられ、優先順位に基づいてスケジュールされます。ConcurrencySchedulingPolicy は次の方法で動作します。

  • ConcurrencySchedulingPolicy は、同時実行リミッターを使用して、処理中の同時リクエスト数を記録し、同時リクエスト数が上限に達しているかどうかを判断します。

  • 同時リクエスト数が上限に達すると、後続のリクエストはキューに入れられ、前のリクエストが処理された後に宛先サービスに送信されます。これにより、特定の数の同時リクエストが維持されます。さらに、優先順位の高いリクエストは、キューから取り出されて宛先サービスに送信される可能性が高くなります。

同時リクエスト数がシステムで処理できるリクエストの上限を超えた場合、ConcurrencySchedulingPolicy はリクエストを直接拒否するのではなく、優先順位キューに入れます。これは、指定されたしきい値に達したときにリクエストを拒否する ConcurrencyLimitingPolicy とは異なります。ConcurrencySchedulingPolicy は、同時リクエスト数が上限内にあることを保証しながら、優先順位に基づいてリクエストをスケジュールします。

前提条件

手順 1:ConcurrencySchedulingPolicy を作成する

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

  2. 次の内容を含む concurrencyschedulingpoilcy.yaml ファイルを作成します。

    apiVersion: istio.alibabacloud.com/v1
    kind: ConcurrencySchedulingPolicy
    metadata:
      name: concurrencyscheduling
      namespace: istio-system
    spec:
      concurrency_scheduler:
        max_concurrency: 10
        concurrency_limiter:
          max_inflight_duration: 60s
        scheduler:
          workloads:
            - label_matcher:
                match_labels:
                  http.request.header.user_type: guest
              parameters:
                priority: 50.0
              name: guest
            - label_matcher:
                match_labels:
                  http.request.header.user_type: subscriber
              parameters:
                priority: 200.0
              name: subscriber
        selectors:
        - service: httpbin.default.svc.cluster.local

    次の表に、いくつかのパラメータを示します。構成項目の詳細については、「ConcurrencySchedulingPolicy フィールドの説明」をご参照ください。

    フィールド

    説明

    max_concurrency

    同時リクエストの最大数。この例では、このフィールドは 10 に設定されています。これは、サービスが一度に 10 個のリクエストを処理できることを示しています。

    max_inflight_duration

    リクエスト処理のタイムアウト期間。クラスタ内のポッドの再起動などの予期しないイベントが原因で、ASM トラフィック スケジューリング スイートがリクエスト終了イベントの記録に失敗する可能性があります。このようなリクエストが同時実行制限アルゴリズムの判断に影響を与えるのを防ぐため、リクエスト処理のタイムアウト期間を指定する必要があります。このタイムアウト期間の前にリクエストが応答されていない場合、システムはそのようなリクエストが処理されたと見なします。リクエストの予想される最大応答時間を評価することで、このフィールドを設定できます。この例では、このフィールドは 60 秒に設定されています。

    workloads

    リクエスト ヘッダーの user_type に基づいて、2 種類のリクエスト(guest と subscriber)が定義されます。guest タイプのリクエストの優先度は 50 で、subscriber タイプのリクエストの優先度は 200 です。

    selectors

    調整ポリシーが適用されるサービス。この例では、service: httpbin.default.svc.cluster.local が使用されています。これは、同時実行制限ポリシーが httpbin.default.svc.cluster.local サービスに適用されることを示しています。

  3. 次のコマンドを実行して、ConcurrencySchedulingPolicy を作成します。

    kubectl apply -f concurrencyschedulingpoilcy.yaml

手順 2:同時リクエストが制御されているシナリオで、優先順位に基づくリクエスト スケジューリングの結果を確認する

この例では、ストレステスト ツールである Fortio を使用します。詳細については、GitHub Web サイトの Fortio の「インストール」セクションをご参照ください。

  1. 2 つのターミナルを開き、同時に次の 2 つのストレステスト コマンドを実行して、テストを開始します。テスト全体を通して、2 つのターミナルが予期どおりに動作していることを確認してください。2 つのターミナルでのテストでは、10 個の同時リクエストがサービスに送信され、1 秒あたりのクエリ数(QPS)は 10,000 です。これは、サービスが耐えられる同時リクエスト数を大幅に超えています。

    fortio load -c 10 -qps 10000  -H "user_type:guest" -t 30s -timeout 60s -a http://${ASMイングレス ゲートウェイの IP アドレス}/status/201
    fortio load -c 10 -qps 10000  -H "user_type:subscriber" -t 30s -timeout 60s -a http://${ASMイングレス ゲートウェイの IP アドレス}/status/202
    説明

    上記のコマンドの ${ASM ゲートウェイの IP アドレス} を、ASMイングレス ゲートウェイの IP アドレスに置き換えます。ASMイングレス ゲートウェイの IP アドレスを取得する方法の詳細については、「Istio リソースを使用してトラフィックをサービスの異なるバージョンにルーティングする」トピックの手順 3 のサブステップ 1 をご参照ください。

    テスト 1 からの予期される出力:

    ...
    # target 50% 4.35294
    # target 75% 5.39689
    # target 90% 5.89697
    # target 99% 6.19701
    # target 99.9% 6.22702
    Sockets used: 10 (for perfect keepalive, would be 10)
    Uniform: false, Jitter: false
    Code 201 : 84 (100.0 %)
    Response Header Sizes : count 84 avg 249.88095 +/- 0.3587 min 248 max 250 sum 20990
    Response Body/Total Sizes : count 84 avg 249.88095 +/- 0.3587 min 248 max 250 sum 20990
    All done 84 calls (plus 10 warmup) 3802.559 ms avg, 2.6 qps
    Successfully wrote 5186 bytes of Json data to xxxxxx.json

    テスト 1 によって出力された JSON ファイルの名前(例:xxxxxx.json)を記録します。

    テスト 2 からの予期される出力:

    ...
    # target 50% 1.18121
    # target 75% 1.63423
    # target 90% 1.90604
    # target 99% 2.22941
    # target 99.9% 2.28353
    Sockets used: 10 (for perfect keepalive, would be 10)
    Uniform: false, Jitter: false
    Code 202 : 270 (100.0 %)
    Response Header Sizes : count 270 avg 250.52963 +/- 0.5418 min 249 max 251 sum 67643
    Response Body/Total Sizes : count 270 avg 250.52963 +/- 0.5418 min 249 max 251 sum 67643
    All done 270 calls (plus 10 warmup) 1117.614 ms avg, 8.8 qps
    Successfully wrote 5305 bytes of Json data to yyyyyy.json

    テスト 2 によって出力された JSON ファイルの名前(例:yyyyyy.json)を記録します。

    上記の出力は、テスト 2 の平均リクエスト レイテンシがテスト 1 の約 4 分の 1 であり、QPS がテスト 1 の約 4 倍であることを示しています。これは、以前に定義されたポリシーでは、subscriber タイプのリクエストの優先度が guest タイプのリクエストの 4 倍であるためです。

  2. (オプション)結果を視覚的に表示します。

    1. 前の手順で 2 つのコマンドを実行したオンプレミス ディレクトリで次のコマンドを実行して、ローカル Fortio サーバーを開きます。

      fortio server
    2. ブラウザを使用して http://localhost:8080/fortio/browse にアクセスし、サブステップ 1 で記録した対応する JSON ファイルの名前をクリックして、視覚化されたテスト結果を表示します。

      テスト 1 の視覚化された結果の例:

      image

      テスト 2 の視覚化された結果の例:

      image

      上記の視覚化された結果は、少数の無制限のリクエストを除いて、ほとんどの guest タイプのリクエストのレイテンシが 4,000 ~ 6,000 ms であることを示しています。ただし、ほとんどの subscriber タイプのリクエストのレイテンシは 1,000 ~ 2,000 ms です。サービスへのリクエストが上限を超えると、subscriber タイプのリクエストが最初に応答されます。さらに、サービスに送信される同時リクエストは特定の値に制限されます。

参考資料

Grafana で ConcurrencySchedulingPolicy が有効になっているかどうかを確認できます。Grafana の Prometheus インスタンスが ASM トラフィック スケジューリング スイート で構成されていることを確認する必要があります。

次の内容を Grafana にインポートして、ConcurrencySchedulingPolicy のダッシュボードを作成できます。

詳細を表示するにはクリックしてください

{
  "annotations": {
    "list": [
      {
        "builtIn": 1,
        "datasource": {
          "type": "grafana",
          "uid": "-- Grafana --"
        },
        "enable": true,
        "hide": true,
        "iconColor": "rgba(0, 211, 255, 1)",
        "name": "注釈とアラート",
        "type": "dashboard"
      }
    ]
  },
  "editable": true,
  "fiscalYearStartMonth": 0,
  "graphTooltip": 0,
  "id": 42,
  "links": [],
  "liveNow": false,
  "panels": [
    {
      "datasource": {
        "type": "prometheus",
        "uid": "${データソース}"
      },
      "description": "クエリを定期的に実行することによって得られたシグナル: (sum(rate(workload_requests_total{policy_name=\"concurrencyscheduling\",component_id=\"root.0\",decision_type=\"DECISION_TYPE_ACCEPTED\"}[30s])) / sum(rate(workload_requests_total{policy_name=\"concurrencyscheduling\",component_id=\"root.0\"}[30s]))) * 100",
      "fieldConfig": { /* 省略 */ },
      "gridPos": { /* 省略 */ },
      "id": 1,
      "interval": "10s",
      "options": { /* 省略 */ },
      "pluginVersion": "v10.1.0",
      "targets": [ /* 省略 */ ],
      "title": "承認率",
      "type": "timeseries"
    },
    { /* 省略 - その他のパネル */ }
  ],
  "refresh": "",
  "schemaVersion": 38,
  "style": "dark",
  "tags": [],
  "templating": { /* 省略 */ },
  "time": {
    "from": "now-5m",
    "to": "now"
  },
  "timepicker": {},
  "timezone": "browser",
  "title": "ポリシーの概要 - concurrencyscheduling",
  "version": 2,
  "weekStart": ""
}

ダッシュボードは次のとおりです。

image