From 1c7a1f24dea0b1abf37f2da63bf18ede52e52d51 Mon Sep 17 00:00:00 2001 From: traky Date: Mon, 30 Dec 2024 16:06:00 +0800 Subject: [PATCH 1/4] update docs --- docs/en/latest/plugins/limit-req.md | 338 ++++++++++++++------------ docs/zh/latest/plugins/limit-req.md | 357 +++++++++++++++------------- 2 files changed, 377 insertions(+), 318 deletions(-) diff --git a/docs/en/latest/plugins/limit-req.md b/docs/en/latest/plugins/limit-req.md index f5aa3e6ecc7a..4a5a09c4f96e 100644 --- a/docs/en/latest/plugins/limit-req.md +++ b/docs/en/latest/plugins/limit-req.md @@ -5,7 +5,7 @@ keywords: - API Gateway - Limit Request - limit-req -description: The limit-req Plugin limits the number of requests to your service using the leaky bucket algorithm. +description: The limit-req plugin uses the leaky bucket algorithm to rate limit the number of the requests and allow for throttling. --- + + + + ## Description -The `limit-req` Plugin limits the number of requests to your service using the [leaky bucket](https://en.wikipedia.org/wiki/Leaky_bucket) algorithm. +The `limit-req` plugin uses the [leaky bucket](https://en.wikipedia.org/wiki/Leaky_bucket) algorithm to rate limit the number of the requests and allow for throttling. ## Attributes -| Name | Type | Required | Default | Valid values | Description | +| Name | Type | Required | Default | Valid values | Description | |-------------------|---------|----------|---------|----------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| rate | integer | True | | rate > 0 | Threshold for number of requests per second. Requests exceeding this rate (and below `burst`) will be delayed to match this rate. | -| burst | integer | True | | burst >= 0 | Number of additional requests allowed to be delayed per second. If the number of requests exceeds this hard limit, they will get rejected immediately. | -| key_type | string | False | "var" | ["var", "var_combination"] | Type of user specified key to use. | -| key | string | True | | ["remote_addr", "server_addr", "http_x_real_ip", "http_x_forwarded_for", "consumer_name"] | User specified key to base the request limiting on. If the `key_type` attribute is set to `var`, the key will be treated as a name of variable, like `remote_addr` or `consumer_name`. If the `key_type` is set to `var_combination`, the key will be a combination of variables, like `$remote_addr $consumer_name`. If the value of the key is empty, `remote_addr` will be set as the default key. | -| rejected_code | integer | False | 503 | [200,...,599] | HTTP status code returned when the requests exceeding the threshold are rejected. | -| rejected_msg | string | False | | non-empty | Body of the response returned when the requests exceeding the threshold are rejected. | -| nodelay | boolean | False | false | | If set to `true`, requests within the burst threshold would not be delayed. | -| allow_degradation | boolean | False | false | | When set to `true` enables Plugin degradation when the Plugin is temporarily unavailable and allows requests to continue. | -| policy | string | False | "local" | ["local", "redis", "redis-cluster"] | Rate-limiting policies to use for retrieving and increment the limit count. When set to `local` the counters will be locally stored in memory on the node. When set to `redis` counters are stored on a Redis server and will be shared across the nodes. It is done usually for global speed limiting, and setting to `redis-cluster` uses a Redis cluster instead of a single instance. | -| redis_host | string | required when `policy` is `redis` | | | Address of the Redis server. Used when the `policy` attribute is set to `redis`. | -| redis_port | integer | False | 6379 | [1,...] | Port of the Redis server. Used when the `policy` attribute is set to `redis`. | -| redis_username | string | False | | | Username for Redis authentication if Redis ACL is used (for Redis version >= 6.0). If you use the legacy authentication method `requirepass` to configure Redis password, configure only the `redis_password`. Used when the `policy` is set to `redis`. | -| redis_password | string | False | | | Password for Redis authentication. Used when the `policy` is set to `redis` or `redis-cluster`. | -| redis_ssl | boolean | False | false | | If set to `true`, then uses SSL to connect to redis instance. Used when the `policy` attribute is set to `redis`. | -| redis_ssl_verify | boolean | False | false | | If set to `true`, then verifies the validity of the server SSL certificate. Used when the `policy` attribute is set to `redis`. See [tcpsock:sslhandshake](https://github.com/openresty/lua-nginx-module#tcpsocksslhandshake). | -| redis_database | integer | False | 0 | redis_database >= 0 | Selected database of the Redis server (for single instance operation or when using Redis cloud with a single entrypoint). Used when the `policy` attribute is set to `redis`. | -| redis_timeout | integer | False | 1000 | [1,...] | Timeout in milliseconds for any command submitted to the Redis server. Used when the `policy` attribute is set to `redis` or `redis-cluster`. | -| redis_cluster_nodes | array | required when `policy` is `redis-cluster` | | | Addresses of Redis cluster nodes. Used when the `policy` attribute is set to `redis-cluster`. | -| redis_cluster_name | string | required when `policy` is `redis-cluster` | | | Name of the Redis cluster service nodes. Used when the `policy` attribute is set to `redis-cluster`. | -| redis_cluster_ssl | boolean | False | false | | If set to `true`, then uses SSL to connect to redis-cluster. Used when the `policy` attribute is set to `redis-cluster`. | -| redis_cluster_ssl_verify | boolean | False | false | | If set to `true`, then verifies the validity of the server SSL certificate. Used when the `policy` attribute is set to `redis-cluster`. | - -## Enable Plugin - -You can enable the Plugin on a Route as shown below: +| rate | integer | True | | > 0 | The maximum number of requests allowed per second. Requests exceeding the rate and below burst will be delayed. | +| burst | integer | True | | >= 0 | The number of requests allowed to be delayed per second for throttling. Requests exceeding the rate and burst will get rejected. | +| key_type | string | False | var | ["var", "var_combination"] | The type of key. If the `key_type` is `var`, the `key` is interpreted a variable. If the `key_type` is `var_combination`, the `key` is interpreted as a combination of variables. | +| key | string | True | remote_addr | | The key to count requests by. If the `key_type` is `var`, the `key` is interpreted a variable. The variable does not need to be prefixed by a dollar sign (`$`). If the `key_type` is `var_combination`, the `key` is interpreted as a combination of variables. All variables should be prefixed by dollar signs (`$`). For example, to configure the `key` to use a combination of two request headers `custom-a` and `custom-b`, the `key` should be configured as `$http_custom_a $http_custom_b`. | +| rejected_code | integer | False | 503 | [200,...,599] | The HTTP status code returned when a request is rejected for exceeding the threshold. | +| rejected_msg | string | False | | non-empty | The response body returned when a request is rejected for exceeding the threshold. | +| nodelay | boolean | False | false | | If true, do not delay requests within the burst threshold. | +| allow_degradation | boolean | False | false | | If true, allow APISIX to continue handling requests without the plugin when the plugin or its dependencies become unavailable. | +| policy | string | False | local | ["local", "redis", "redis-cluster"] | The policy for rate limiting counter. If it is `local`, the counter is stored in memory locally. If it is `redis`, the counter is stored on a Redis instance. If it is `redis-cluster`, the counter is stored in a Redis cluster. | +| redis_host | string | False | | | The address of the Redis node. Required when `policy` is `redis`. | +| redis_port | integer | False | 6379 | [1,...] | The port of the Redis node when `policy` is `redis`. | +| redis_username | string | False | | | The username for Redis if Redis ACL is used. If you use the legacy authentication method `requirepass`, configure only the `redis_password`. Used when `policy` is `redis`. | +| redis_password | string | False | | | The password of the Redis node when `policy` is `redis` or `redis-cluster`. | +| redis_ssl | boolean | False | false | | If true, use SSL to connect to Redis cluster when `policy` is `redis`. | +| redis_ssl_verify | boolean | False | false | | If true, verify the server SSL certificate when `policy` is `redis`. | +| redis_database | integer | False | 0 | >= 0 | The database number in Redis when `policy` is `redis`. | +| redis_timeout | integer | False | 1000 | [1,...] | The Redis timeout value in milliseconds when `policy` is `redis` or `redis-cluster`. | +| redis_cluster_nodes | array[string] | False | | | The list of the Redis cluster nodes with at least two addresses. Required when policy is redis-cluster. | +| redis_cluster_name | string | False | | | The name of the Redis cluster. Required when `policy` is `redis-cluster`. | +| redis_cluster_ssl | boolean | False | false | | If true, use SSL to connect to Redis cluster when `policy` is | +| redis_cluster_ssl_verify | boolean | False | false | | If true, verify the server SSL certificate when `policy` is `redis-cluster`. | + +## Examples + +The examples below demonstrate how you can configure `limit-req` in different scenarios. :::note You can fetch the `admin_key` from `config.yaml` and save to an environment variable with the following command: @@ -68,177 +72,213 @@ You can fetch the `admin_key` from `config.yaml` and save to an environment vari admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g') ``` -::: +### Apply Rate Limiting by Remote Address + +The following example demonstrates the rate limiting of HTTP requests by a single variable, `remote_addr`. + +Create a Route with `limit-req` plugin that allows for 1 QPS per remote address: ```shell -curl http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -d ' -{ - "methods": ["GET"], - "uri": "/index.html", +curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \ + -H "X-API-KEY: ${admin_key}" \ + -d ' + { + "id": "limit-req-route", + "uri": "/get", "plugins": { - "limit-req": { - "rate": 3, - "burst": 2, - "rejected_code": 503, - "key_type": "var", - "key": "remote_addr" - } + "limit-req": { + "rate": 1, + "burst": 0, + "key": "remote_addr", + "key_type": "var", + "rejected_code": 429, + "nodelay": true + } }, "upstream": { - "type": "roundrobin", - "nodes": { - "127.0.0.1:9001": 1 - } + "type": "roundrobin", + "nodes": { + "httpbin.org:80": 1 + } } -}' + }' +``` + +Send a request to verify: + +```shell +curl -i "http://127.0.0.1:9080/get" ``` -You can also configure the `key_type` to `var_combination` as shown: +You should see an `HTTP/1.1 200 OK` response. + +The request has consumed all the quota allowed for the time window. If you send the request again within the same second, you should receive an `HTTP/1.1 429 Too Many Requests` response, indicating the request surpasses the quota threshold. + +### Implement API Throttling + +The following example demonstrates how to configure `burst` to allow overrun of the rate limiting threshold by the configured value and achieve request throttling. You will also see a comparison against when throttling is not implemented. -```json -{ - "methods": ["GET"], - "uri": "/index.html", +Create a Route with `limit-req` plugin that allows for 1 QPS per remote address, with a `burst` of 1 to allow for 1 request exceeding the `rate` to be delayed for processing: + +```shell +curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \ + -H "X-API-KEY: ${admin_key}" \ + -d '{ + "id": "limit-req-route", + "uri": "/get", "plugins": { - "limit-req": { - "rate": 3, - "burst": 2, - "rejected_code": 503, - "key_type": "var_combination", - "key": "$consumer_name $remote_addr" - } + "limit-req": { + "rate": 1, + "burst": 1, + "key": "remote_addr", + "rejected_code": 429 + } }, "upstream": { - "type": "roundrobin", - "nodes": { - "127.0.0.1:9001": 1 - } + "type": "roundrobin", + "nodes": { + "httpbin.org:80": 1 + } } -} + }' ``` -You can also configure the Plugin on specific consumers to limit their requests. - -First, you can create a Consumer and enable the `limit-req` Plugin on it: +Generate three requests to the route: ```shell -curl http://127.0.0.1:9180/apisix/admin/consumers -H "X-API-KEY: $admin_key" -X PUT -d ' -{ - "username": "consumer_jack", - "plugins": { - "key-auth": { - "key": "auth-jack" - }, - "limit-req": { - "rate": 3, - "burst": 2, - "rejected_code": 403, - "key": "consumer_name" - } - } -}' +resp=$(seq 3 | xargs -I{} curl -i "http://127.0.0.1:9080/get" -o /dev/null -s -w "%{http_code}\n") && \ + count_200=$(echo "$resp" | grep "200" | wc -l) && \ + count_429=$(echo "$resp" | grep "429" | wc -l) && \ + echo "200 responses: $count_200 ; 429 responses: $count_429" ``` -In this example, the [key-auth](./key-auth.md) Plugin is used to authenticate the Consumer. +You are likely to see that all three requests are successful: -Next, create a Route and enable the `key-auth` Plugin: +```text +200 responses: 3 ; 429 responses: 0 +``` + +To see the effect without `burst`, update `burst` to 0 or set `nodelay` to `true` as follows: ```shell -curl http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -d ' -{ - "methods": ["GET"], - "uri": "/index.html", +curl "http://127.0.0.1:9180/apisix/admin/routes/limit-req-route" -X PATCH \ + -H "X-API-KEY: ${admin_key}" \ + -d '{ "plugins": { - "key-auth": { - "key": "auth-jack" - } - }, - "upstream": { - "type": "roundrobin", - "nodes": { - "127.0.0.1:1980": 1 - } + "limit-req": { + "nodelay": true + } } -}' + }' +``` + +Generate three requests to the Route again: + +```shell +resp=$(seq 3 | xargs -I{} curl -i "http://127.0.0.1:9080/get" -o /dev/null -s -w "%{http_code}\n") && \ + count_200=$(echo "$resp" | grep "200" | wc -l) && \ + count_429=$(echo "$resp" | grep "429" | wc -l) && \ + echo "200 responses: $count_200 ; 429 responses: $count_429" +``` + +You should see a response similar to the following, showing requests surpassing the rate have been rejected: + +```text +200 responses: 1 ; 429 responses: 2 ``` -## Example usage +### Apply Rate Limiting by Remote Address and Consumer Name + +The following example demonstrates the rate limiting of requests by a combination of variables, `remote_addr` and `consumer_name`. -Once you have configured the Plugin as shown above, you can test it out. The above configuration limits to 3 request per second. If the number of requests is greater than 3 but less than 5, a delay will be added. And if the number of requests per second exceeds 5, it will be rejected. +Create a Route with `limit-req` plugin that allows for 1 QPS per remote address and for each Consumer. -Now if you send a request: +Create a Consumer `john`: ```shell -curl -i http://127.0.0.1:9080/index.html +curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \ + -H "X-API-KEY: ${admin_key}" \ + -d '{ + "username": "john" + }' ``` -For authenticated requests: +Create `key-auth` Credential for the consumer: ```shell -curl -i http://127.0.0.1:9080/index.html -H 'apikey: auth-jack' +curl "http://127.0.0.1:9180/apisix/admin/consumers/john/credentials" -X PUT \ + -H "X-API-KEY: ${admin_key}" \ + -d '{ + "id": "cred-john-key-auth", + "plugins": { + "key-auth": { + "key": "john-key" + } + } + }' ``` -If you exceed the limit, you will receive a response with a 503 code: - -```html -HTTP/1.1 503 Service Temporarily Unavailable -Content-Type: text/html -Content-Length: 194 -Connection: keep-alive -Server: APISIX web server - - -503 Service Temporarily Unavailable - -

503 Service Temporarily Unavailable

-
openresty
- - +Create a second Consumer `jane`: + +```shell +curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \ + -H "X-API-KEY: ${admin_key}" \ + -d '{ + "username": "jane" + }' ``` -You can set a custom rejected message by configuring the `rejected_msg` attribute. You will then receive a response like: +Create `key-auth` Credential for the consumer: ```shell -HTTP/1.1 503 Service Temporarily Unavailable -Content-Type: text/html -Content-Length: 194 -Connection: keep-alive -Server: APISIX web server - -{"error_msg":"Requests are too frequent, please try again later."} +curl "http://127.0.0.1:9180/apisix/admin/consumers/jane/credentials" -X PUT \ + -H "X-API-KEY: ${admin_key}" \ + -d '{ + "id": "cred-jane-key-auth", + "plugins": { + "key-auth": { + "key": "jane-key" + } + } + }' ``` -## Delete Plugin - -To remove the `limit-req` Plugin, you can delete the corresponding JSON configuration from the Plugin configuration. APISIX will automatically reload and you do not have to restart for this to take effect. +Create a Route with `key-auth` and `limit-req` plugins, and specify in the `limit-req` plugin to use a combination of variables as the rate limiting key: ```shell -curl http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -d ' -{ - "methods": ["GET"], - "uri": "/index.html", - "id": 1, +curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \ + -H "X-API-KEY: ${admin_key}" \ + -d '{ + "id": "limit-req-route", + "uri": "/get", "plugins": { + "key-auth": {}, + "limit-req": { + "rate": 1, + "burst": 0, + "key": "$remote_addr $consumer_name", + "key_type": "var_combination", + "rejected_code": 429 + } }, "upstream": { - "type": "roundrobin", - "nodes": { - "127.0.0.1:1980": 1 - } + "type": "roundrobin", + "nodes": { + "httpbin.org:80": 1 + } } -}' + }' ``` -Similarly for removing the Plugin from a Consumer: +Send two requests simultaneously, each for one consumer: ```shell -curl http://127.0.0.1:9180/apisix/admin/consumers -H "X-API-KEY: $admin_key" -X PUT -d ' -{ - "username": "consumer_jack", - "plugins": { - "key-auth": { - "key": "auth-jack" - } - } -}' +curl -i "http://127.0.0.1:9080/get" -H 'apikey: jane-key' & \ +curl -i "http://127.0.0.1:9080/get" -H 'apikey: john-key' & ``` + +You should receive `HTTP/1.1 200 OK` for both requests, indicating the request has not exceeded the threshold for each consumer. + +If you send more requests as either Consumer within the same second, you should receive an `HTTP/1.1 429 Too Many Requests` response. + +This verifies the plugin rate limits by the combination of variables, `remote_addr` and `consumer_name`. diff --git a/docs/zh/latest/plugins/limit-req.md b/docs/zh/latest/plugins/limit-req.md index 564e38edc275..26e8084e01f9 100644 --- a/docs/zh/latest/plugins/limit-req.md +++ b/docs/zh/latest/plugins/limit-req.md @@ -5,7 +5,7 @@ keywords: - API 网关 - Limit Request - limit-req -description: limit-req 插件使用漏桶算法限制对用户服务的请求速率。 +description: limit-req 插件使用漏桶算法来限制请求的数量并允许节流。 --- + + + + ## 描述 -`limit-req` 插件使用[漏桶算法](https://baike.baidu.com/item/%E6%BC%8F%E6%A1%B6%E7%AE%97%E6%B3%95/8455361)限制单个客户端对服务的请求速率。 +`limit-req` 插件使用 [leaky bucket](https://en.wikipedia.org/wiki/Leaky_bucket) 算法来限制请求的数量并允许节流。 ## 属性 | 名称 | 类型 | 必选项 | 默认值 | 有效值 | 描述 | | ------------- | ------- | ------ | ------ | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -| rate | integer | 是 | | rate > 0 | 指定的请求速率(以秒为单位),请求速率超过 `rate` 但没有超过(`rate` + `burst`)的请求会被延时处理。| -| burst | integer | 是 | | burst >= 0 | 请求速率超过(`rate` + `burst`)的请求会被直接拒绝。| -| key_type | string | 否 | "var" | ["var", "var_combination"] | 要使用的用户指定 `key` 的类型。 | -| key | string | 是 | | ["remote_addr", "server_addr", "http_x_real_ip", "http_x_forwarded_for", "consumer_name"] | 用来做请求计数的依据,当前接受的 `key` 有:`remote_addr`(客户端 IP 地址),`server_addr`(服务端 IP 地址), 请求头中的 `X-Forwarded-For` 或 `X-Real-IP`,`consumer_name`(Consumer 的 `username`)。 | -| rejected_code | integer | 否 | 503 | [200,...,599] | 当超过阈值的请求被拒绝时,返回的 HTTP 状态码。| -| rejected_msg | string | 否 | | 非空 | 当超过阈值的请求被拒绝时,返回的响应体。| -| nodelay | boolean | 否 | false | | 当设置为 `true` 时,请求速率超过 `rate` 但没有超过(`rate` + `burst`)的请求不会加上延迟;当设置为 `false`,则会加上延迟。 | -| allow_degradation | boolean | 否 | false | | 当设置为 `true` 时,如果限速插件功能临时不可用,将会自动允许请求继续。| -| policy | string | 否 | "local" | ["local", "redis", "redis-cluster"] | 用于检索和增加限制计数的策略。当设置为 `local` 时,计数器被以内存方式保存在节点本地;当设置为 `redis` 时,计数器保存在 Redis 服务节点上,从而可以跨节点共享结果,通常用它来完成全局限速;当设置为 `redis-cluster` 时,使用 Redis 集群而不是单个实例。| -| redis_host | string | 否 | | | 当使用 `redis` 限速策略时,Redis 服务节点的地址。**当 `policy` 属性设置为 `redis` 时必选。** | -| redis_port | integer | 否 | 6379 | [1,...] | 当使用 `redis` 限速策略时,Redis 服务节点的端口。 | -| redis_username | string | 否 | | | 若使用 Redis ACL 进行身份验证(适用于 Redis 版本 >=6.0),则需要提供 Redis 用户名。若使用 Redis legacy 方式 `requirepass` 进行身份验证,则只需将密码配置在 `redis_password`。当 `policy` 设置为 `redis` 时使用。 | -| redis_password | string | 否 | | | 当使用 `redis` 或者 `redis-cluster` 限速策略时,Redis 服务节点的密码。 | -| redis_ssl | boolean | 否 | false | | 当使用 `redis` 限速策略时,如果设置为 true,则使用 SSL 连接到 `redis` | -| redis_ssl_verify | boolean | 否 | false | | 当使用 `redis` 限速策略时,如果设置为 true,则验证服务器 SSL 证书的有效性,具体请参考 [tcpsock:sslhandshake](https://github.com/openresty/lua-nginx-module#tcpsocksslhandshake). | -| redis_database | integer | 否 | 0 | redis_database >= 0 | 当使用 `redis` 限速策略时,Redis 服务节点中使用的 `database`,并且只针对非 Redis 集群模式(单实例模式或者提供单入口的 Redis 公有云服务)生效。 | -| redis_timeout | integer | 否 | 1000 | [1,...] | 当 `policy` 设置为 `redis` 或 `redis-cluster` 时,Redis 服务节点的超时时间(以毫秒为单位)。 | -| redis_cluster_nodes | array | 否 | | | 当使用 `redis-cluster` 限速策略时,Redis 集群服务节点的地址列表(至少需要两个地址)。**当 `policy` 属性设置为 `redis-cluster` 时必选。** | -| redis_cluster_name | string | 否 | | | 当使用 `redis-cluster` 限速策略时,Redis 集群服务节点的名称。**当 `policy` 设置为 `redis-cluster` 时必选。** | -| redis_cluster_ssl | boolean | 否 | false | | 当使用 `redis-cluster` 限速策略时,如果设置为 true,则使用 SSL 连接到 `redis-cluster` | -| redis_cluster_ssl_verify | boolean | 否 | false | | 当使用 `redis-cluster` 限速策略时,如果设置为 true,则验证服务器 SSL 证书的有效性 | - -## 启用插件 - -### 在 Route 或 Service 上启用插件 - -以下示例展示了如何在指定路由上启用 `limit-req` 插件,并设置 `key_type` 的值为 `var`: +| rate | integer | True | | > 0 | 每秒允许的最大请求数。超过速率且低于突发的请求将被延迟。| +| bust | integer | True | | >= 0 | 每秒允许延迟的请求数,以进行限制。超过速率和突发的请求将被拒绝。| +| key_type | string | 否 | var | ["var","var_combination"] | key 的类型。如果 `key_type` 为 `var`,则 `key` 将被解释为变量。如果 `key_type` 为 `var_combination`,则 `key` 将被解释为变量的组合。 | +| key | string | 否 | remote_addr | | 用于计数请求的key。如果 `key_type` 为 `var`,则 `key` 将被解释为变量。变量不需要以美元符号(`$`)为前缀。如果 `key_type` 为 `var_combination`,则 `key` 会被解释为变量的组合。所有变量都应该以美元符号 (`$`) 为前缀。例如,要配置 `key` 使用两个请求头 `custom-a` 和 `custom-b` 的组合,则 `key` 应该配置为 `$http_custom_a $http_custom_b`。如果 `key_type` 为 `constant`,则 `key` 会被解释为常量值。| +| rejection_code | integer | 否 | 503 | [200,...,599] | 请求因超出阈值而被拒绝时返回的 HTTP 状态代码。| +| rejection_msg | string | 否 | | 非空 | 请求因超出阈值而被拒绝时返回的响应主体。| +| nodelay | boolean | 否 | false | | 如果为 true,则不要延迟突发阈值内的请求。 | +| allow_degradation | boolean | 否 | false | | 如果为 true,则允许 APISIX 在插件或其依赖项不可用时继续处理没有插件的请求。| +| policy | string | 否 | local | ["local","re​​dis","re​​dis-cluster"] | 速率限制计数器的策略。如果是 `local`,则计数器存储在本地内存中。如果是 `redis`,则计数器存储在 Redis 实例上。如果是 `redis-cluster`,则计数器存储在 Redis 集群中。| +| allow_degradation | boolean | 否 | false | | 如果为 true,则允许 APISIX 在插件或其依赖项不可用时继续处理没有插件的请求。| +| show_limit_quota_header | boolean | 否 | true | | 如果为 true,则在响应标头中包含 `X-RateLimit-Limit` 以显示总配额和 `X-RateLimit-Remaining` 以显示剩余配额。| +| redis_host | string | 否 | | | Redis 节点的地址。当 `policy` 为 `redis` 时必填。 | +| redis_port | integer | 否 | 6379 | [1,...] | 当 `policy` 为 `redis` 时,Redis 节点的端口。 | +| redis_username | string | 否 | | | 如果使用 Redis ACL,则为 Redis 的用户名。如果使用旧式身份验证方法 `requirepass`,则仅配置 `redis_password`。当 `policy` 为 `redis` 时使用。 | +| redis_password | string | 否 | | | 当 `policy` 为 `redis` 或 `redis-cluster` 时,Redis 节点的密码。 | +| redis_ssl | 布尔值 | 否 | false |如果为 true,则在 `policy` 为 `redis` 时使用 SSL 连接到 Redis 集群。| +| redis_ssl_verify | boolean | 否 | false | | 如果为 true,则在 `policy` 为 `redis` 时验证服务器 SSL 证书。| +| redis_database | integer | 否 | 0 | >= 0 | 当 `policy` 为 `redis` 时,Redis 中的数据库编号。| +| redis_timeout | integer | 否 | 1000 | [1,...] | 当 `policy` 为 `redis` 或 `redis-cluster` 时,Redis 超时值(以毫秒为单位)。 | +| redis_cluster_nodes | array[string] | 否 | | | 具有至少两个地址的 Redis 群集节点列表。当 policy 为 redis-cluster 时必填。 | +redis_cluster_name | string | 否 | | | | Redis 集群的名称。当 `policy` 为 `redis-cluster` 时必须使用。| +| redis_cluster_ssl | boolean | 否 | false | | 如果为 `true`,当 `policy` 为 `redis-cluster`时,使用 SSL 连接 Redis 集群。| +| redis_cluster_ssl_verify | boolean | 否 | false | | 如果为 `true`,当 `policy` 为 `redis-cluster` 时,验证服务器 SSL 证书。 | + +## 示例 + +以下示例演示了如何在不同场景中配置 `limit-req`。 :::note @@ -73,198 +77,213 @@ admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"/ ::: +### 通过远程地址应用速率限制 + +以下示例演示了通过单个变量 `remote_addr` 对 HTTP 请求进行速率限制。 + +使用 `limit-req` 插件创建允许每个远程地址 1 QPS 的路由: + ```shell -curl http://127.0.0.1:9180/apisix/admin/routes/1 \ --H "X-API-KEY: $admin_key" -X PUT -d ' -{ - "methods": ["GET"], - "uri": "/index.html", +curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \ + -H "X-API-KEY: ${admin_key}" \ + -d ' + { + "id": "limit-req-route", + "uri": "/get", "plugins": { - "limit-req": { - "rate": 3, - "burst": 2, - "rejected_code": 503, - "key_type": "var", - "key": "remote_addr" - } + "limit-req": { + "rate": 1, + "burst": 0, + "key": "remote_addr", + "key_type": "var", + "rejected_code": 429, + "nodelay": true + } }, "upstream": { - "type": "roundrobin", - "nodes": { - "127.0.0.1:1980": 1 - } + "type": "roundrobin", + "nodes": { + "httpbin.org:80": 1 + } } -}' + }' ``` -上述示例表示,APISIX 将客户端的 IP 地址作为限制请求速率的条件,当请求速率小于等于 3 次每秒(`rate`)时,请求正常;当请求速率大于 3 次每秒(`rate`),小于等于 5 次每秒(`rate + burst`)时,将会对超出部分的请求进行延迟处理;当请求速率大于 5 次每秒(`rate + burst`)时,超出规定数量的请求将返回 HTTP 状态码 `503`。 +发送请求以验证: + +```shell +curl -i "http://127.0.0.1:9080/get" +``` + +您应该会看到一个 `HTTP/1.1 200 OK` 响应。 + +该请求已消耗了时间窗口允许的所有配额。如果您在同一秒内再次发送请求,您应该会收到 `HTTP/1.1 429 Too Many Requests` 响应,表示请求超出了配额阈值。 + +### 允许速率限制阈值 + +以下示例演示了如何配置 `burst` 以允许速率限制阈值超出配置的值并实现请求限制。您还将看到与未实施限制时的比较。 -你也可以设置 `key_type` 的值为 `var_combination`: +使用 `limit-req` 插件创建一个路由,允许每个远程地址 1 QPS,并将 `burst` 设置为 1,以允许 1 个超过 `rate` 的请求延迟处理: -```json -{ - "methods": ["GET"], - "uri": "/index.html", +```shell +curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \ + -H "X-API-KEY: ${admin_key}" \ + -d '{ + "id": "limit-req-route", + "uri": "/get", "plugins": { - "limit-req": { - "rate": 3, - "burst": 2, - "rejected_code": 503, - "key_type": "var_combination", - "key": "$consumer_name $remote_addr" - } + "limit-req": { + "rate": 1, + "burst": 1, + "key": "remote_addr", + "rejected_code": 429 + } }, "upstream": { - "type": "roundrobin", - "nodes": { - "127.0.0.1:9001": 1 - } + "type": "roundrobin", + "nodes": { + "httpbin.org:80": 1 + } } -} + }' ``` -**测试插件** - -通过以下命令发送请求: +生成三个对路由的请求: ```shell -curl -i http://127.0.0.1:9080/index.html +resp=$(seq 3 | xargs -I{} curl -i "http://127.0.0.1:9080/get" -o /dev/null -s -w "%{http_code}\n") && \ + count_200=$(echo "$resp" | grep "200" | wc -l) && \ + count_429=$(echo "$resp" | grep "429" | wc -l) && \ + echo "200 responses: $count_200 ; 429 responses: $count_429" ``` -当请求速率超出限制时,返回如下包含 503 HTTP 状态码的响应头,插件生效: - -```html -HTTP/1.1 503 Service Temporarily Unavailable -Content-Type: text/html -Content-Length: 194 -Connection: keep-alive -Server: APISIX web server - - -503 Service Temporarily Unavailable - -

503 Service Temporarily Unavailable

-
openresty
- - -``` - -同时,如果你设置了 `rejected_msg` 属性的值为 `"Requests are too frequent, please try again later."`,当请求速率超出限制时,返回如下包含 `503` HTTP 状态码的响应体: - -```shell -HTTP/1.1 503 Service Temporarily Unavailable -Content-Type: text/html -Content-Length: 194 -Connection: keep-alive -Server: APISIX web server +您可能会看到所有三个请求都成功: -{"error_msg":"Requests are too frequent, please try again later."} +```text +200 responses: 3 ; 429 responses: 0 ``` -### 在 Consumer 上启用插件 - -在 [Consumer](../terminology/consumer.md) 上启用 `limit-req` 插件需要与认证插件一起配合使用,以 [`key-auth`](./key-auth.md) 授权插件为例。 - -首先,将 `limit-req` 插件绑定到 Consumer 上: +现在,将 `burst` 更新为 0 或将 `nodelay` 设置为 `true`,如下所示: ```shell -curl http://127.0.0.1:9180/apisix/admin/consumers \ --H "X-API-KEY: $admin_key" -X PUT -d ' -{ - "username": "consumer_jack", +curl "http://127.0.0.1:9180/apisix/admin/routes/limit-req-route" -X PATCH \ + -H "X-API-KEY: ${admin_key}" \ + -d '{ "plugins": { - "key-auth": { - "key": "auth-jack" - }, - "limit-req": { - "rate": 1, - "burst": 1, - "rejected_code": 403, - "key": "consumer_name" - } + "limit-req": { + "nodelay": true + } } -}' + }' ``` -然后,在指定路由上启用并配置 `key-auth` 插件: +再次向路由生成三个请求: ```shell -curl http://127.0.0.1:9180/apisix/admin/routes/1 \ --H "X-API-KEY: $admin_key" -X PUT -d ' -{ - "methods": ["GET"], - "uri": "/index.html", - "plugins": { - "key-auth": { - "key": "auth-jack" - } - }, - "upstream": { - "type": "roundrobin", - "nodes": { - "127.0.0.1:1980": 1 - } - } -}' +resp=$(seq 3 | xargs -I{} curl -i "http://127.0.0.1:9080/get" -o /dev/null -s -w "%{http_code}\n") && \ + count_200=$(echo "$resp" | grep "200" | wc -l) && \ + count_429=$(echo "$resp" | grep "429" | wc -l) && \ + echo "200 responses: $count_200 ; 429 responses: $count_429" +``` + +您应该会看到类似以下内容的响应,表明超出速率的请求已被拒绝: + +```text +200 responses: 1 ; 429 responses: 2 ``` -**测试插件** +### 通过远程地址和消费者名称应用速率限制 + +以下示例演示了通过变量组合 `remote_addr` 和 `consumer_name` 来限制请求的速率。 -通过以下命令发送请求: +使用 `limit-req` 插件创建一个路由,允许每个远程地址和每个消费者 有 1 QPS。 + +创建消费者 `john`: ```shell -curl -i http://127.0.0.1:9080/index.html -H 'apikey: auth-jack' +curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \ + -H "X-API-KEY: ${admin_key}" \ + -d '{ + "username": "john" + }' ``` -当请求速率未超过 `rate + burst` 的值时,返回 `200` HTTP 状态码,说明请求成功,插件生效: +为消费者创建 `key-auth` 凭证: ```shell -HTTP/1.1 200 OK +curl "http://127.0.0.1:9180/apisix/admin/consumers/john/credentials" -X PUT \ + -H "X-API-KEY: ${admin_key}" \ + -d '{ + "id": "cred-john-key-auth", + "plugins": { + "key-auth": { + "key": "john-key" + } + } + }' ``` -当请求速率超过 `rate + burst` 的值时,返回 `403` HTTP 状态码,说明请求被阻止,插件生效: +创建第二个消费者 `jane`: ```shell -HTTP/1.1 403 Forbidden -... - -403 Forbidden - -

403 Forbidden

-
openresty
- - +curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \ + -H "X-API-KEY: ${admin_key}" \ + -d '{ + "username": "jane" + }' ``` -## 删除插件 - -当你需要删除该插件时,可以通过以下命令删除相应的 JSON 配置,APISIX 将会自动重新加载相关配置,无需重启服务: +为消费者创建 `key-auth` 凭证: ```shell -curl http://127.0.0.1:9180/apisix/admin/routes/1 \ --H "X-API-KEY: $admin_key" -X PUT -d ' -{ - "methods": ["GET"], - "uri": "/index.html", - "upstream": { - "type": "roundrobin", - "nodes": { - "127.0.0.1:1980": 1 - } +curl "http://127.0.0.1:9180/apisix/admin/consumers/jane/credentials" -X PUT \ + -H "X-API-KEY: ${admin_key}" \ + -d '{ + "id": "cred-jane-key-auth", + "plugins": { + "key-auth": { + "key": "jane-key" + } } -}' + }' ``` -你也可以通过以下命令移除 Consumer 上的 `limit-req` 插件: +创建一个带有 `key-auth` 和 `limit-req` 插件的路由,并在 `limit-req` 插件中指定使用变量组合作为速率限制 key: ```shell -curl http://127.0.0.1:9180/apisix/admin/consumers -H "X-API-KEY: $admin_key" -X PUT -d ' -{ - "username": "consumer_jack", +curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \ + -H "X-API-KEY: ${admin_key}" \ + -d '{ + "id": "limit-req-route", + "uri": "/get", "plugins": { - "key-auth": { - "key": "auth-jack" - } + "key-auth": {}, + "limit-req": { + "rate": 1, + "burst": 0, + "key": "$remote_addr $consumer_name", + "key_type": "var_combination", + "rejected_code": 429 + } + }, + "upstream": { + "type": "roundrobin", + "nodes": { + "httpbin.org:80": 1 + } } -}' + }' +``` + +同时发送两个请求,每个请求针对一个消费者: + +```shell +curl -i "http://127.0.0.1:9080/get" -H 'apikey: jane-key' & \ +curl -i "http://127.0.0.1:9080/get" -H 'apikey: john-key' & ``` + +您应该会收到两个请求的 `HTTP/1.1 200 OK`,表明请求未超过每个消费者的阈值。 + +如果您在同一秒内以任一消费者身份发送更多请求,应该会收到 `HTTP/1.1 429 Too Many Requests` 响应。 + +这验证了插件速率限制是通过变量 `remote_addr` 和 `consumer_name` 的来实现的。 From 18d90bbdaa04626f90876fae1553ddcfd9c85a3b Mon Sep 17 00:00:00 2001 From: traky Date: Mon, 30 Dec 2024 16:08:22 +0800 Subject: [PATCH 2/4] capitalize plugin --- docs/en/latest/plugins/limit-req.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/en/latest/plugins/limit-req.md b/docs/en/latest/plugins/limit-req.md index 4a5a09c4f96e..6aab2e76791a 100644 --- a/docs/en/latest/plugins/limit-req.md +++ b/docs/en/latest/plugins/limit-req.md @@ -5,7 +5,7 @@ keywords: - API Gateway - Limit Request - limit-req -description: The limit-req plugin uses the leaky bucket algorithm to rate limit the number of the requests and allow for throttling. +description: The limit-req Plugin uses the leaky bucket algorithm to rate limit the number of the requests and allow for throttling. ---