全部产品
Search
文档中心

服务网格 ASM:使用ConcurrencyLimitingPolicy实现请求并发数控制

更新时间:Oct 25, 2024

您可以使用ASM流量调度套件的ConcurrencyLimitingPolicy功能来控制发往服务的请求并发度(即正在处理的请求数量),防止服务过载。该策略会追踪正在处理的请求数量,并在超过设定阈值时拒绝新请求。本文将详细介绍如何使用ConcurrencyLimitingPolicy实现请求并发度控制。

前提条件

步骤一:创建ConcurrencyLimitingPolicy并发数限制规则

  1. 使用kubectl连接到ASM实例,具体操作,请参见通过控制面kubectl访问Istio资源

  2. 使用以下内容,创建ConcurrencyLimitPolicy.yaml文件。

    apiVersion: istio.alibabacloud.com/v1
    kind: ConcurrencyLimitingPolicy
    metadata:
      name: concurrencylimit
      namespace: istio-system
    spec:
      concurrency_limiter:
        max_concurrency: 1
        parameters:
          max_inflight_duration: 60s
        selectors:
        - service: httpbin.default.svc.cluster.local

    部分字段说明如下。关于字段的更多信息,请参见ConcurrencyLimitingPolicy CRD说明

    字段

    说明

    max_concurrency

    最大请求并发数。示例中指定为1,即只允许服务同时处理1个请求。

    max_inflight_duration

    请求处理超时时间。由于集群中可能发生Pod重启等突发情况,导致ASM流量调度套件可能无法记录到请求结束事件,为防止此类请求影响并发数限制算法的判断,需要指定请求处理超时时间,超过此时间还未响应的请求将视作处理结束。您可以通过评估请求的期望最大响应时间来设定此值,示例中设定为60s。

    selectors

    指定应用限流策略的多个服务。示例中使用service: httpbin.default.svc.cluster.local 表示对httpbin.default.svc.cluster.local 服务进行并发数限制。

  3. 执行以下命令,开启ConcurrencyLimitingPolicy并发数限制规则。

    kubectl apply -f ConcurrencyLimitingPolicy.yaml 

    预期输出:

    concurrencylimitingpolicy.istio.alibabacloud.com/concurrencylimit created

步骤二:验证并发数限制效果

  1. 执行以下命令,进入sleep应用开启sh命令行。

    kubectl exec -it deploy/sleep -- sh
  2. 执行以下命令,首先通过后台发送一个需要处理30秒的请求,然后在30秒之内紧接着发送第二个请求。

    curl httpbin:8000/delay/30 -I &
    curl httpbin:8000 -I

    预期输出:

    HTTP/1.1 429 Too Many Requests
    date: Fri, 26 Jul 2024 13:50:55 GMT
    server: envoy
    x-envoy-upstream-service-time: 1
    transfer-encoding: chunked
    
    ~ $ HTTP/1.1 200 OK
    server: envoy
    date: Fri, 26 Jul 2024 13:51:05 GMT
    content-type: application/json
    content-length: 269
    access-control-allow-origin: *
    access-control-allow-credentials: true
    x-envoy-upstream-service-time: 10006
    
    [1]+  Done                       curl httpbin:8000/delay/30 -I

    可以看到第二次发送请求收到了429响应码,证明并发数限制生效。

相关操作

您可以通过Grafana大盘来观测ConcurrencyLimitingPolicy策略的执行效果。请确保Grafana使用的数据源Prometheus实例已经完成配置采集ASM流量调度套件相关指标

将以下内容导入到Grafana,创建ConcurrencyLimitingPolicy策略的大盘。

展开查看JSON内容

{
  "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": 41,
  "links": [],
  "liveNow": false,
  "panels": [
    {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "description": "Signal derived from periodic execution of query: (sum(rate(concurrency_limiter_counter_total{policy_name=\"concurrencylimit\",component_id=\"root.0\",decision_type=\"DECISION_TYPE_ACCEPTED\"}[30s])) / sum(rate(concurrency_limiter_counter_total{policy_name=\"concurrencylimit\",component_id=\"root.0\"}[30s]))) * 100",
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "palette-classic"
          },
          "custom": {
            "axisCenteredZero": false,
            "axisColorMode": "text",
            "axisLabel": "",
            "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": ""
        },
        "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 (policy_name) (rate(concurrency_limiter_counter_total{component_id=\"root.0\",decision_type=\"DECISION_TYPE_ACCEPTED\"}[30s])) / sum by (policy_name) (rate(concurrency_limiter_counter_total{component_id=\"root.0\"}[30s]))) * 10",
          "intervalFactor": 1,
          "legendFormat": "accepted percentage",
          "range": true,
          "refId": "A"
        }
      ],
      "title": "Accept Percentage",
      "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": 10
      },
      "id": 2,
      "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(concurrency_limiter_counter_total{component_id=\"root.0\"}[$__range]))",
          "instant": false,
          "intervalFactor": 1,
          "legendFormat": "{{ 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": 10
      },
      "id": 3,
      "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(concurrency_limiter_counter_total{component_id=\"root.0\", decision_type=\"DECISION_TYPE_ACCEPTED\"}[$__range]))",
          "instant": false,
          "intervalFactor": 1,
          "legendFormat": "{{ 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": 10
      },
      "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(concurrency_limiter_counter_total{component_id=\"root.0\", 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": "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": 5,
      "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(concurrency_limiter_counter_total{component_id=\"root.0\"}[$__rate_interval]))",
          "intervalFactor": 1,
          "range": true,
          "refId": "A"
        }
      ],
      "title": "Concurrency Limiter Decision Overview",
      "type": "timeseries"
    }
  ],
  "refresh": "",
  "schemaVersion": 38,
  "style": "dark",
  "tags": [],
  "templating": {
    "list": [
      {
        "hide": 0,
        "includeAll": false,
        "label": "Data Source",
        "multi": false,
        "name": "datasource",
        "options": [],
        "query": "prometheus",
        "refresh": 1,
        "regex": "",
        "skipUrlSync": false,
        "type": "datasource"
      }
    ]
  },
  "time": {
    "from": "now-5m",
    "to": "now"
  },
  "timepicker": {},
  "timezone": "browser",
  "title": "Policy Summary - concurrencylimit",
  "version": 1,
  "weekStart": ""
}

大盘效果如下。

image