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

Alibaba Cloud Service Mesh:AverageLatencySchedulingPolicy を使用して優先順位に基づくリクエストスケジューリングを実装する

最終更新日:Jan 13, 2025

Service Mesh(ASM)のトラフィックスケジューリングスイートは、優先順位に基づくリクエストスケジューリングポリシーをサポートしています。システムが過負荷状態になると、優先順位の高いリクエストが優先的に処理されます。このトピックでは、トラフィックスケジューリングスイートによって提供される AverageLatencySchedulingPolicy を使用して、優先順位に基づくリクエストスケジューリングを実装する方法について説明します。

背景情報

優先順位に基づくリクエストスケジューリングポリシーは、リアルタイムレイテンシと過去の平均レイテンシを比較して、トラフィックの過負荷が発生しているかどうかを判断します。トラフィックの過負荷が発生した場合、トークンバケットと優先順位に基づくスケジューリングメカニズムを使用してリクエストがスケジューリングされます。優先順位に基づくリクエストスケジューリングポリシーは、次の方法で機能します。

  1. 過負荷検出: このポリシーは、過去一定期間の平均レイテンシと現在のレイテンシを比較して、システムが過負荷状態になっているかどうかを判断します。

  2. トークン発行率の調整: 過負荷が発生した場合、前の手順で取得された監視データが専用の controller に送信され、トークンバケットの fill rate が制御されます。

  3. リクエストスケジューリング: リクエストごとに異なる優先順位が設定されています。過負荷が発生した場合、優先順位の高いリクエストほどトークンを取得できる可能性が高くなります。

このポリシーは、リクエストの同時実行数が高いためにサービスが輻輳し、応答レイテンシが継続的に増加している場合に、リクエストをキューイングするために使用できます。一般的に使用される throttling ポリシーとは異なり、このポリシーはリクエストを直接拒否するのではなく、優先順位付きキューに入れます。リクエストレートはトークンバケットメカニズムを使用して制限され、リクエストの処理順序はリクエストの優先順位に従って調整されます。

前提条件

手順 1: AverageLatencySchedulingPolicy を作成する

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

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

    apiVersion: istio.alibabacloud.com/v1
    kind: AverageLatencySchedulingPolicy
    metadata:
      name: workload-prioritization
      namespace: istio-system
    spec:
      load_scheduling_core:
        aimd_load_scheduler:
          load_scheduler:
            workload_latency_based_tokens: true
            selectors:
              - service: httpbin.default.svc.cluster.local
            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"
                  

    次の表に、いくつかのフィールドについて説明します。

    フィールド

    説明

    workload_latency_based_tokens

    ワークロードの平均レイテンシに基づいてトークン数を動的に調整するかどうかを示します。平均レイテンシを推定するための時間枠は、過去 30 分です。

    service

    スケジューリングポリシーが有効になるサービス。

    workloads

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

    AverageLatencySchedulingPolicy でサポートされているフィールドの詳細については、「AverageLatencySchedulingPolicy フィールドの説明」をご参照ください。

手順 2: テストを実行する

この例では、負荷テストツール fortio を使用します。詳細については、「fortio のインストール」をご参照ください。

まず、いくつかの通常のサービスリクエストをシミュレートして、リクエストの平均レイテンシを生成します。

fortio load -c 20 -qps 100000 -t 60m http://${ASM ゲートウェイの IP アドレス}/status/200

上記のコマンドを実行してから 3 分後に、2 つのターミナルを再度開き、テストリクエストを送信します。テスト全体を通して、fortio プロセスが常に実行されていることを確認し、対応するターミナルを閉じないでください。

2 つのターミナルで、それぞれ次の 2 つの負荷テストコマンドを実行します。(可能な限り同時に 2 つのテストの実行を開始してください。)

fortio load -c 40 -qps 100000  -H "user_type:guest" -t 3m http://${ASM ゲートウェイの IP アドレス}/status/201
fortio load -c 40 -qps 100000  -H "user_type:subscriber" -t 3m http://${ASM ゲートウェイの IP アドレス}/status/202

2 つのコマンドでは、アクセスログに基づいてテスト結果を容易に観測できるように、異なるリクエストパスが使用されています。

手順 3: テスト結果を分析する

次のコードブロックは、現在のテスト環境における 2 つのコマンドの出力の最後の数行を示しています。

Code 201 : 26852 (97.8 %)
Code 503 : 601 (2.2 %)
Response Header Sizes : count 27453 avg 242.91564 +/- 36.35 min 0 max 249 sum 6668763
Response Body/Total Sizes : count 27453 avg 246.17754 +/- 14.56 min 149 max 249 sum 6758312
All done 27453 calls (plus 40 warmup) 262.318 ms avg, 152.4 qps
Code 202 : 52765 (100.0 %)
Response Header Sizes : count 52765 avg 248.86358 +/- 0.5951 min 248 max 250 sum 13131287
Response Body/Total Sizes : count 52765 avg 248.86358 +/- 0.5951 min 248 max 250 sum 13131287
All done 52765 calls (plus 40 warmup) 136.472 ms avg, 292.9 qps

コードブロックは以下を示しています。

  • subscriber ユーザーからのすべてのリクエストは成功し、HTTP 503 ステータスコードは返されませんでした。guest ユーザーからのリクエストの 2.2 % に対して HTTP 503 ステータスコードが返されました。

  • subscriber ユーザーからのリクエストの平均レイテンシは約 136 ms です。guest ユーザーからのリクエストの平均レイテンシは約 262 ms です。さらに、2 人のユーザーの Queries Per Second (QPS) は大きく異なります。

リクエストレイテンシが増加した場合、AverageLatencySchedulingPolicy は subscriber ユーザーのリクエストを優先的に処理することが推測できます。

重要

このトピックのテスト結果は理論値です。実際のデータは運用環境によって異なります。負荷テストの結果は、テスト環境によって異なります。この例では、データの相対的な関係のみが分析されています。

(オプション) 手順 4: ASM ゲートウェイのアクセスログに基づいてテスト結果を分析する

  1. ASM コンソール にログインします。左側のナビゲーションペインで、[service Mesh] > [メッシュ管理] を選択します。

  2. [メッシュ管理] ページで、ASM インスタンスの名前をクリックします。左側のナビゲーションペインで、[ASM ゲートウェイ] > [イングレスゲートウェイ] を選択します。

  3. ASM ゲートウェイの名前をクリックして、[ゲートウェイの概要] ページに移動します。次に、[ゲートウェイログ] をクリックして、ASM ゲートウェイのアクセスログを表示します。

  4. guest ユーザーと subscriber ユーザーのアクセス パスは異なります。アクセス パスを使用して、2 人のユーザーのアクセス結果をそれぞれ取得できます。

image.png

image.png

参考資料

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

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

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

{
  "annotations": {
    "list": [
      {
        "builtIn": 1,
        "datasource": {
          "type": "grafana",
          "uid": "-- Grafana --"
        },
        "enable": true,
        "hide": true,
        "iconColor": "rgba(0, 211, 255, 1)",
        "name": "Annotations & Alerts",  // アノテーションとアラート
        "type": "dashboard"
      }
    ]
  },
  "editable": true,
  "fiscalYearStartMonth": 0,
  "graphTooltip": 0,
  "id": 40,
  "links": [],
  "liveNow": false,
  "panels": [
    {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "description": "",
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "palette-classic"
          },
          "custom": {
            "axisCenteredZero": false,
            "axisColorMode": "text",
            "axisLabel": "Decisions", // 決定
            "axisPlacement": "auto",
            "barAlignment": 0,
            "drawStyle": "line",
            "fillOpacity": 10,
            "gradientMode": "none",
            "hideFrom": {
              "legend": false,
              "tooltip": false,
              "viz": false
            },
            "lineInterpolation": "linear",
            "lineWidth": 1,
            "pointSize": 5,
            "scaleDistribution": {
              "type": "linear"
            },
            "showPoints": "auto",
            "spanNulls": false,
            "stacking": {
              "group": "A",
              "mode": "none"
            },
            "thresholdsStyle": {
              "mode": "off"
            }
          },
          "mappings": [],
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              },
              {
                "color": "red",
                "value": 80
              }
            ]
          },
          "unit": "reqps"
        },
        "overrides": []
      },
      "gridPos": {
        "h": 10,
        "w": 24,
        "x": 0,
        "y": 0
      },
      "id": 1,
      "interval": "10s",
      "options": {
        "legend": {
          "calcs": [],
          "displayMode": "list",
          "placement": "bottom",
          "showLegend": true
        },
        "tooltip": {
          "mode": "single",
          "sort": "none"
        }
      },
      "pluginVersion": "v10.1.0",
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "${datasource}"
          },
          "editorMode": "code",
          "expr": "sum by(decision_type, policy_name) (rate(workload_requests_total{component_id=\"root.0.4\"}[$__rate_interval]))", // ワークロードリクエスト合計
          "intervalFactor": 1,
          "range": true,
          "refId": "A"
        }
      ],
      "title": "Workload Decisions", // ワークロードの決定
      "type": "timeseries"
    },

    {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "description": "",
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "palette-classic"
          },
          "custom": {
            "axisCenteredZero": false,
            "axisColorMode": "text",
            "axisLabel": "Decisions", // 決定
            "axisPlacement": "auto",
            "barAlignment": 0,
            "drawStyle": "line",
            "fillOpacity": 10,
            "gradientMode": "none",
            "hideFrom": {
              "legend": false,
              "tooltip": false,
              "viz": false
            },
            "lineInterpolation": "linear",
            "lineWidth": 1,
            "pointSize": 5,
            "scaleDistribution": {
              "type": "linear"
            },
            "showPoints": "auto",
            "spanNulls": false,
            "stacking": {
              "group": "A",
              "mode": "none"
            },
            "thresholdsStyle": {
              "mode": "off"
            }
          },
          "mappings": [],
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              },
              {
                "color": "red",
                "value": 80
              }
            ]
          },
          "unit": "reqps"
        },
        "overrides": []
      },
      "gridPos": {
        "h": 10,
        "w": 24,
        "x": 0,
        "y": 10
      },
      "id": 2,
      "interval": "10s",
      "options": {
        "legend": {
          "calcs": [],
          "displayMode": "list",
          "placement": "bottom",
          "showLegend": true
        },
        "tooltip": {
          "mode": "single",
          "sort": "none"
        }
      },
      "pluginVersion": "v10.1.0",
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "${datasource}"
          },
          "editorMode": "code",
          "expr": "sum by(workload_index, decision_type, policy_name) (rate(workload_requests_total{component_id=\"root.0.4\",decision_type=\"DECISION_TYPE_ACCEPTED\"}[$__rate_interval]))", // ワークロードリクエスト合計(承認済み)
          "intervalFactor": 1,
          "range": true,
          "refId": "A"
        }
      ],
      "title": "Workload Decisions (accepted)", // ワークロードの決定(承認済み)
      "type": "timeseries"
    },

    {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "description": "",
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "palette-classic"
          },
          "custom": {
            "axisCenteredZero": false,
            "axisColorMode": "text",
            "axisLabel": "Decisions", // 決定
            "axisPlacement": "auto",
            "barAlignment": 0,
            "drawStyle": "line",
            "fillOpacity": 10,
            "gradientMode": "none",
            "hideFrom": {
              "legend": false,
              "tooltip": false,
              "viz": false
            },
            "lineInterpolation": "linear",
            "lineWidth": 1,
            "pointSize": 5,
            "scaleDistribution": {
              "type": "linear"
            },
            "showPoints": "auto",
            "spanNulls": false,
            "stacking": {
              "group": "A",
              "mode": "none"
            },
            "thresholdsStyle": {
              "mode": "off"
            }
          },
          "mappings": [],
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              },
              {
                "color": "red",
                "value": 80
              }
            ]
          },
          "unit": "reqps"
        },
        "overrides": []
      },
      "gridPos": {
        "h": 10,
        "w": 24,
        "x": 0,
        "y": 20
      },
      "id": 3,
      "interval": "10s",
      "options": {
        "legend": {
          "calcs": [],
          "displayMode": "list",
          "placement": "bottom",
          "showLegend": true
        },
        "tooltip": {
          "mode": "single",
          "sort": "none"
        }
      },
      "pluginVersion": "v10.1.0",
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "${datasource}"
          },
          "editorMode": "code",
          "expr": "sum by(workload_index, decision_type, policy_name) (rate(workload_requests_total{component_id=\"root.0.4\",decision_type=\"DECISION_TYPE_REJECTED\"}[$__rate_interval]))", // ワークロードリクエスト合計(拒否済み)
          "intervalFactor": 1,
          "range": true,
          "refId": "A"
        }
      ],
      "title": "Workload Decisions (rejected)", // ワークロードの決定(拒否済み)
      "type": "timeseries"
    },

    {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "thresholds"
          },
          "mappings": [],
          "noValue": "No data", // データなし
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "blue",
                "value": null
              }
            ]
          },
          "unit": "short"
        },
        "overrides": []
      },
      "gridPos": {
        "h": 10,
        "w": 8,
        "x": 0,
        "y": 30
      },
      "id": 4,
      "options": {
        "colorMode": "value",
        "graphMode": "area",
        "justifyMode": "center",
        "orientation": "horizontal",
        "reduceOptions": {
          "calcs": [
            "lastNotNull"
          ],
          "fields": "",
          "values": false
        },
        "textMode": "auto"
      },
      "pluginVersion": "10.0.9",
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "${datasource}"
          },
          "editorMode": "code",
          "expr": "sum by (policy_name) (increase(workload_requests_total{component_id=\"root.0.4\"}[$__range]))", // リクエスト合計
          "instant": false,
          "intervalFactor": 1,
          "legendFormat": "{{ instance }} - {{ policy_name }}",
          "range": true,
          "refId": "A"
        }
      ],
      "title": "Total Requests", // リクエスト合計
      "type": "stat"
    },

    {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "thresholds"
          },
          "mappings": [],
          "noValue": "No data", // データなし
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              }
            ]
          },
          "unit": "short"
        },
        "overrides": []
      },
      "gridPos": {
        "h": 10,
        "w": 8,
        "x": 8,
        "y": 30
      },
      "id": 5,
      "options": {
        "colorMode": "value",
        "graphMode": "area",
        "justifyMode": "center",
        "orientation": "horizontal",
        "reduceOptions": {
          "calcs": [
            "lastNotNull"
          ],
          "fields": "",
          "values": false
        },
        "textMode": "auto"
      },
      "pluginVersion": "10.0.9",
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "${datasource}"
          },
          "editorMode": "code",
          "expr": "sum by (policy_name)(increase(workload_requests_total{component_id=\"root.0.4\", decision_type=\"DECISION_TYPE_ACCEPTED\"}[$__range]))", // 承認されたリクエストの合計
          "instant": false,
          "intervalFactor": 1,
          "legendFormat": "{{ instance }} - {{ policy_name }}",
          "range": true,
          "refId": "A"
        }
      ],
      "title": "Total Accepted Requests", // 承認されたリクエストの合計
      "type": "stat"
    },

    {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "thresholds"
          },
          "mappings": [],
          "noValue": "No rejected requests", // 拒否されたリクエストはありません
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "red",
                "value": null
              }
            ]
          },
          "unit": "short"
        },
        "overrides": []
      },
      "gridPos": {
        "h": 10,
        "w": 8,
        "x": 16,
        "y": 30
      },
      "id": 6,
      "options": {
        "colorMode": "value",
        "graphMode": "area",
        "justifyMode": "center",
        "orientation": "horizontal",
        "reduceOptions": {
          "calcs": [
            "lastNotNull"
          ],
          "fields": "",
          "values": false
        },
        "textMode": "auto"
      },
      "pluginVersion": "10.0.9",
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "${datasource}"
          },
          "editorMode": "code",
          "expr": "sum by (policy_name) (increase(workload_requests_total{component_id=\"root.0.4\", decision_type=\"DECISION_TYPE_REJECTED\"}[$__range]))", // 拒否されたリクエストの合計
          "instant": false,
          "intervalFactor": 1,
          "legendFormat": "{{ instance }} - {{ policy_name }}",
          "range": true,
          "refId": "A"
        }
      ],
      "title": "Total Rejected Requests", // 拒否されたリクエストの合計
      "type": "stat"
    },

    {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "description": "",
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "palette-classic"
          },
          "custom": {
            "axisCenteredZero": false,
            "axisColorMode": "text",
            "axisLabel": "Latency", // レイテンシ
            "axisPlacement": "auto",
            "barAlignment": 0,
            "drawStyle": "line",
            "fillOpacity": 10,
            "gradientMode": "none",
            "hideFrom": {
              "legend": false,
              "tooltip": false,
              "viz": false
            },
            "lineInterpolation": "linear",
            "lineWidth": 1,
            "pointSize": 5,
            "scaleDistribution": {
              "type": "linear"
            },
            "showPoints": "auto",
            "spanNulls": false,
            "stacking": {
              "group": "A",
              "mode": "none"
            },
            "thresholdsStyle": {
              "mode": "off"
            }
          },
          "mappings": [],```json
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              },
              {
                "color": "red",
                "value": 80
              }
            ]
          },
          "unit": "ms"
        },
        "overrides": []
      },
      "gridPos": {
        "h": 10,
        "w": 24,
        "x": 0,
        "y": 40
      },
      "id": 7,
      "interval": "10s",
      "options": {
        "legend": {
          "calcs": [],
          "displayMode": "list",
          "placement": "bottom",
          "showLegend": true
        },
        "tooltip": {
          "mode": "single",
          "sort": "none"
        }
      },
      "pluginVersion": "v10.1.0",
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "${datasource}"
          },
          "editorMode": "code",
          "expr": "(sum by (workload_index, policy_name) (increase(workload_latency_ms_sum{component_id=\"root.0.4\"}[$__rate_interval])))/(sum by (workload_index, policy_name) (increase(workload_latency_ms_count{component_id=\"root.0.4\"}[$__rate_interval])))", // ワークロードレイテンシ
          "intervalFactor": 1,
          "range": true,
          "refId": "A"
        }
      ],
      "title": "Workload Latency", // ワークロードレイテンシ
      "type": "timeseries"
    },
        {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "description": "",
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "palette-classic"
          },
          "custom": {
            "axisCenteredZero": false,
            "axisColorMode": "text",
            "axisLabel": "Wait Time", // 待機時間
            "axisPlacement": "auto",
            "barAlignment": 0,
            "drawStyle": "line",
            "fillOpacity": 10,
            "gradientMode": "none",
            "hideFrom": {
              "legend": false,
              "tooltip": false,
              "viz": false
            },
            "lineInterpolation": "linear",
            "lineWidth": 1,
            "pointSize": 5,
            "scaleDistribution": {
              "type": "linear"
            },
            "showPoints": "auto",
            "spanNulls": false,
            "stacking": {
              "group": "A",
              "mode": "none"
            },
            "thresholdsStyle": {
              "mode": "off"
            }
          },
          "mappings": [],
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              },
              {
                "color": "red",
                "value": 80
              }
            ]
          },
          "unit": "ms"
        },
        "overrides": []
      },
      "gridPos": {
        "h": 10,
        "w": 12,
        "x": 0,
        "y": 50
      },
      "id": 8,
      "interval": "10s",
      "options": {
        "legend": {
          "calcs": [],
          "displayMode": "list",
          "placement": "bottom",
          "showLegend": true
        },
        "tooltip": {
          "mode": "single",
          "sort": "none"
        }
      },
      "pluginVersion": "v10.1.0",
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "${datasource}"
          },
          "editorMode": "code",
          "expr": "(sum by (workload_index, policy_name) (increase(request_in_queue_duration_ms_sum{component_id=\"root.0.4\"}[$__rate_interval])))/ ((sum by (workload_index, policy_name) (increase(request_in_queue_duration_ms_count{component_id=\"root.0.4\"}[$__rate_interval]))) != 0)", // キュー内のリクエスト時間
          "intervalFactor": 1,
          "range": true,
          "refId": "A"
        }
      ],
      "title": "Request in Queue Duration", // キュー内のリクエスト時間
      "type": "timeseries"
    },

```

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

image