All Products
Search
Document Center

Alibaba Cloud Service Mesh:Gunakan RateLimitingPolicy untuk menerapkan pembatasan aliran spesifik pengguna

Last Updated:Jul 02, 2025

Suite penjadwalan lalu lintas Service Mesh (ASM) menyediakan kebijakan pembatasan canggih untuk mengimplementasikan fitur seperti pembatasan global, pembatasan spesifik pengguna, konfigurasi jendela burst, dan laju konsumsi token khusus. Topik ini menjelaskan cara menggunakan RateLimitingPolicy dari suite penjadwalan lalu lintas ASM untuk menerapkan pembatasan aliran spesifik pengguna.

Informasi Latar Belakang

Kebijakan pembatasan dalam suite penjadwalan lalu lintas ASM menggunakan algoritma token bucket. Sistem menghasilkan token pada laju tetap dan menambahkannya ke bucket hingga kapasitas maksimum tercapai. Permintaan antar layanan memerlukan konsumsi token. Jika token cukup, permintaan akan dikirim; jika tidak, permintaan mungkin diantrikan atau dibuang. Algoritma ini memastikan laju transmisi rata-rata tidak melebihi laju pembuatan token sambil menangani burst tertentu.

Prasyarat

Persiapan

Sebarkan layanan HTTPBin dan sleep contoh, lalu periksa apakah layanan sleep dapat mengakses layanan HTTPBin.

  1. Buat file httpbin.yaml dengan konten berikut:

    Tampilkan File YAML

    ##################################################################################################
    # Contoh layanan HTTPBin 
    ##################################################################################################
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: httpbin
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: httpbin
      labels:
        app: httpbin
        service: httpbin
    spec:
      ports:
      - name: http
        port: 8000
        targetPort: 80
      selector:
        app: httpbin
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: httpbin
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: httpbin
          version: v1
      template:
        metadata:
          labels:
            app: httpbin
            version: v1
        spec:
          serviceAccountName: httpbin
          containers:
          - image: registry.cn-hangzhou.aliyuncs.com/acs/httpbin:latest
            imagePullPolicy: IfNotPresent
            name: httpbin
            ports:
            - containerPort: 80
  2. Jalankan perintah berikut untuk menerapkan layanan HTTPBin:

    kubectl apply -f httpbin.yaml -n default
  3. Buat file sleep.yaml dengan konten berikut:

    Tampilkan File YAML

    ##################################################################################################
    # Contoh layanan sleep 
    ##################################################################################################
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: sleep
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: sleep
      labels:
        app: sleep
        service: sleep
    spec:
      ports:
      - port: 80
        name: http
      selector:
        app: sleep
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: sleep
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: sleep
      template:
        metadata:
          labels:
            app: sleep
        spec:
          terminationGracePeriodSeconds: 0
          serviceAccountName: sleep
          containers:
          - name: sleep
            image: registry.cn-hangzhou.aliyuncs.com/acs/curl:8.1.2
            command: ["/bin/sleep", "infinity"]
            imagePullPolicy: IfNotPresent
            volumeMounts:
            - mountPath: /etc/sleep/tls
              name: secret-volume
          volumes:
          - name: secret-volume
            secret:
              secretName: sleep-secret
              optional: true
    ---
  4. Jalankan perintah berikut untuk menerapkan layanan sleep:

    kubectl apply -f sleep.yaml -n default
  5. Jalankan perintah berikut untuk mengakses pod sleep:

    kubectl exec -it deploy/sleep -- sh
  6. Jalankan perintah berikut untuk mengirim permintaan ke layanan HTTPBin:

    curl -I http://httpbin:8000/headers

    Output yang Diharapkan:

    HTTP/1.1 200 OK
    server: envoy
    date: Tue, 26 Dec 2023 07:23:49 GMT
    content-type: application/json
    content-length: 353
    access-control-allow-origin: *
    access-control-allow-credentials: true
    x-envoy-upstream-service-time: 1

    Respons 200 OK menunjukkan bahwa akses berhasil.

Langkah 1: Buat kebijakan pembatasan menggunakan RateLimitingPolicy

  1. Gunakan kubectl untuk terhubung ke instance ASM. Untuk informasi lebih lanjut, lihat Gunakan kubectl pada Bidang Kontrol untuk Mengakses Sumber Daya Istio.

  2. Buat file ratelimitingpolicy.yaml dengan konten berikut:

    apiVersion: istio.alibabacloud.com/v1
    kind: RateLimitingPolicy
    metadata:
      name: ratelimit
      namespace: istio-system
    spec:
      rate_limiter:
        bucket_capacity: 2
        fill_amount: 2
        parameters:
          interval: 30s
          limit_by_label_key: http.request.header.user_id
        selectors:
        - agent_group: default
          control_point: ingress
          service: httpbin.default.svc.cluster.local

    Tabel berikut menjelaskan beberapa bidang. Untuk informasi lebih lanjut, lihat Deskripsi Bidang RateLimitingPolicy.

    Bidang

    Deskripsi

    fill_amount

    Jumlah token yang akan ditambahkan dalam interval waktu yang ditentukan oleh bidang interval. Dalam contoh ini, nilainya adalah 2, yang menunjukkan bahwa bucket token diisi dengan dua token setelah setiap interval yang ditentukan oleh bidang interval.

    interval

    Interval di mana token ditambahkan ke bucket token. Dalam contoh ini, nilainya adalah 30s, yang menunjukkan bahwa bucket token diisi dengan dua token setiap 30 detik.

    bucket_capacity

    Jumlah maksimum token dalam bucket token. Saat laju permintaan lebih rendah daripada laju pengisian bucket token, jumlah token dalam bucket token akan terus bertambah, hingga jumlah maksimum bucket_capacity tercapai. bucket_capacity digunakan untuk mengizinkan sejumlah lalu lintas burst. Dalam contoh ini, nilainya adalah 2, sama dengan nilai bidang fill_amount. Dalam hal ini, tidak ada lalu lintas burst yang diizinkan.

    limit_by_label_key

    Label yang digunakan untuk mengelompokkan permintaan dalam kebijakan pembatasan. Setelah Anda menentukan label ini, permintaan dengan label berbeda akan dibatasi secara terpisah dan bucket token terpisah digunakan untuk mereka. Dalam contoh ini, http.request.header.user_id digunakan, yang menunjukkan bahwa permintaan dikelompokkan menggunakan header permintaan user_id. Ini mensimulasikan skenario pembatasan aliran spesifik pengguna. Contoh ini mengasumsikan bahwa permintaan yang dimulai oleh pengguna berbeda memiliki header permintaan used_id yang berbeda.

    selectors

    Layanan tempat kebijakan pembatasan diterapkan. Dalam contoh ini, service: httpbin.default.svc.cluster.local digunakan, yang menunjukkan bahwa pembatasan dilakukan pada layanan httpbin.default.svc.cluster.local.

  1. Jalankan perintah berikut untuk membuat kebijakan pembatasan menggunakan RateLimitingPolicy:

    kubectl apply -f ratelimitingpolicy.yaml

Langkah 2: Verifikasi hasil pembatasan aliran spesifik pengguna

  1. Gunakan kubectl untuk terhubung ke kluster ACK, lalu jalankan perintah berikut untuk mengaktifkan bash pada layanan sleep:

    kubectl exec -it deploy/sleep -- sh
  2. Jalankan perintah berikut untuk mengakses path /headers layanan HTTPBin dua kali berturut-turut sebagai user1:

    curl -H "user_id: user1" httpbin:8000/headers -v
    curl -H "user_id: user1" httpbin:8000/headers -v

    Output yang Diharapkan:

    < HTTP/1.1 429 Too Many Requests
    < retry-after: 14
    < date: Mon, 17 Jun 2024 11:48:53 GMT
    < server: envoy
    < content-length: 0
    < x-envoy-upstream-service-time: 1
    <
    * Koneksi #0 ke host httpbin ditinggalkan utuh
  3. Dalam waktu 30 detik setelah langkah sebelumnya dieksekusi, jalankan perintah berikut untuk mengakses path /headers layanan HTTPBin sekali sebagai user2:

    curl -H "user_id: user2" httpbin:8000/headers -v

    Output yang Diharapkan:

    < HTTP/1.1 200 OK
    < server: envoy
    < date: Mon, 17 Jun 2024 12:42:17 GMT
    < content-type: application/json
    < content-length: 378
    < access-control-allow-origin: *
    < access-control-allow-credentials: true
    < x-envoy-upstream-service-time: 5
    <
    {
      "headers": {
        "Accept": "*/*",
        "Host": "httpbin:8000",
        "User-Agent": "curl/8.1.2",
        "User-Id": "user2",
        "X-Envoy-Attempt-Count": "1",
        "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/httpbin;Hash=ddab183a1502e5ededa933f83e90d3d5266e2ddf87555fb3da1ad40dde3c722e;Subject=\"\";URI=spiffe://cluster.local/ns/default/sa/sleep"
      }
    }
    * Koneksi #0 ke host httpbin ditinggalkan utuh

    Output menunjukkan bahwa pembatasan tidak dipicu ketika user2 mengakses path yang sama. Ini menunjukkan bahwa pembatasan aliran spesifik pengguna berhasil.

Referensi

Anda dapat memverifikasi apakah RateLimitingPolicy berlaku pada Grafana. Pastikan bahwa instance Prometheus untuk Grafana telah dikonfigurasi dengan suite penjadwalan lalu lintas ASM.

Anda dapat mengimpor konten berikut ke Grafana untuk membuat dasbor untuk RateLimitingPolicy.

Klik untuk Melihat Detail

{
  "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": 38,
  "links": [],
  "liveNow": false,
  "panels": [
    {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "description": "Sinyal berasal dari eksekusi periodik query: (sum(rate(rate_limiter_counter_total{policy_name=\"ratelimit\",component_id=\"root.0\",decision_type=\"DECISION_TYPE_ACCEPTED\"}[30s])) / sum(rate(rate_limiter_counter_total{policy_name=\"ratelimit\",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(rate_limiter_counter_total{component_id=\"root.0\",decision_type=\"DECISION_TYPE_ACCEPTED\"}[30s])) / sum by (policy_name) (rate(rate_limiter_counter_total{component_id=\"root.0\"}[30s]))) * 100",
          "intervalFactor": 1,
          "legendFormat": "policy_name={{policy_name}}",
          "range": true,
          "refId": "A"
        }
      ],
      "title": "Persentase Penerimaan",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "thresholds"
          },
          "mappings": [],
          "noValue": "Tidak ada 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(rate_limiter_counter_total{component_id=\"root.0\"}[$__range]))",
          "instant": false,
          "intervalFactor": 1,
          "legendFormat": "{{ policy_name }}",
          "range": true,
          "refId": "A"
        }
      ],
      "title": "Total Permintaan",
      "type": "stat"
    },
    {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "thresholds"
          },
          "mappings": [],
          "noValue": "Tidak ada 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(rate_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 Permintaan Diterima",
      "type": "stat"
    },
    {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "thresholds"
          },
          "mappings": [],
          "noValue": "Tidak ada permintaan yang ditolak",
          "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(rate_limiter_counter_total{component_id=\"root.0\", decision_type=\"DECISION_TYPE_REJECTED\"}[$__range]))",
          "instant": false,
          "intervalFactor": 1,
          "legendFormat": "{{policy_name}}",
          "range": true,
          "refId": "A"
        }
      ],
      "title": "Total Permintaan Ditolak",
      "type": "stat"
    },
    {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "description": "",
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "palette-classic"
          },
          "custom": {
            "axisCenteredZero": false,
            "axisColorMode": "text",
            "axisLabel": "Keputusan",
            "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(rate_limiter_counter_total{component_id=\"root.0\"}[$__rate_interval]))",
          "intervalFactor": 1,
          "range": true,
          "refId": "A"
        }
      ],
      "title": "Ikhtisar Keputusan Pembatas",
      "type": "timeseries"
    }
  ],
  "refresh": "",
  "schemaVersion": 38,
  "style": "dark",
  "tags": [],
  "templating": {
    "list": [
      {
        "hide": 0,
        "includeAll": false,
        "label": "Data Source",
        "multi": false,
        "name": "datasource",
        "options": [],
        "query": "prometheus",
        "queryValue": "",
        "refresh": 1,
        "regex": "",
        "skipUrlSync": false,
        "type": "datasource"
      }
    ]
  },
  "time": {
    "from": "now-1h",
    "to": "now"
  },
  "timepicker": {},
  "timezone": "browser",
  "title": "Ringkasan Kebijakan - ratelimit",
  "version": 15,
  "weekStart": ""
}

Dasbor adalah sebagai berikut.

image