limit-count

Description

The limit-count Plugin limits the number of requests to your service by a given count per time.

Attributes

NameTypeRequiredDefaultValid valuesDescription
countintegerTruecount > 0Maximum number of requests to allow.
time_windowintegerTruetime_window > 0Time in seconds before count is reset.
key_typestringFalse“var”[“var”, “var_combination”, “constant”]Type of user specified key to use.
keystringFalse“remote_addr”User specified key to base the request limiting on. If the key_type attribute is set to constant, the key will be treated as a constant value. 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_codeintegerFalse503[200,…,599]HTTP status code returned when the requests exceeding the threshold are rejected.
rejected_msgstringFalsenon-emptyBody of the response returned when the requests exceeding the threshold are rejected.
policystringFalse“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.
allow_degradationbooleanFalsefalseWhen set to true enables Plugin degradation when the Plugin is temporarily unavailable (for example, a Redis timeout) and allows requests to continue.
show_limit_quota_headerbooleanFalsetrueWhen set to true, adds X-RateLimit-Limit (total number of requests) and X-RateLimit-Remaining (remaining number of requests) to the response header.
groupstringFalsenon-emptyGroup to share the counter with. Routes configured with the same group will share the counter.
redis_hoststringrequired when policy is redisAddress of the Redis server. Used when the policy attribute is set to redis.
redis_portintegerFalse6379[1,…]Port of the Redis server. Used when the policy attribute is set to redis.
redis_passwordstringFalsePassword of the Redis server. Used when the policy is set to redis or redis-cluster.
redis_databaseintegerFalse0redis_database >= 0Selected 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_timeoutintegerFalse1000[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_nodesarrayrequired when policy is redis-clusterAddresses of Redis cluster nodes. Used when the policy attribute is set to redis-cluster.
redis_cluster_namestringrequired when policy is redis-clusterName of the Redis cluster service nodes. Used when the policy attribute is set to redis-cluster.

Enabling the Plugin

You can enable the Plugin on a Route as shown below:

  1. curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
  2. {
  3. "uri": "/index.html",
  4. "plugins": {
  5. "limit-count": {
  6. "count": 2,
  7. "time_window": 60,
  8. "rejected_code": 503,
  9. "key_type": "var",
  10. "key": "remote_addr"
  11. }
  12. },
  13. "upstream": {
  14. "type": "roundrobin",
  15. "nodes": {
  16. "127.0.0.1:9001": 1
  17. }
  18. }
  19. }'

You can also configure the key_type to var_combination as shown:

  1. curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
  2. {
  3. "uri": "/index.html",
  4. "plugins": {
  5. "limit-count": {
  6. "count": 2,
  7. "time_window": 60,
  8. "rejected_code": 503,
  9. "key_type": "var_combination",
  10. "key": "$consumer_name $remote_addr"
  11. }
  12. },
  13. "upstream": {
  14. "type": "roundrobin",
  15. "nodes": {
  16. "127.0.0.1:9001": 1
  17. }
  18. }
  19. }'

You can also create a group to share the same counter across multiple Routes:

  1. curl -i http://127.0.0.1:9080/apisix/admin/services/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
  2. {
  3. "plugins": {
  4. "limit-count": {
  5. "count": 1,
  6. "time_window": 60,
  7. "rejected_code": 503,
  8. "key": "remote_addr",
  9. "group": "services_1#1640140620"
  10. }
  11. },
  12. "upstream": {
  13. "type": "roundrobin",
  14. "nodes": {
  15. "127.0.0.1:1980": 1
  16. }
  17. }
  18. }'

Now every Route which belongs to group services_1#1640140620 (or the service with ID 1) will share the same counter.

  1. curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
  2. {
  3. "service_id": "1",
  4. "uri": "/hello"
  5. }'
  1. curl -i http://127.0.0.1:9080/apisix/admin/routes/2 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
  2. {
  3. "service_id": "1",
  4. "uri": "/hello2"
  5. }'
  1. curl -i http://127.0.0.1:9080/hello
  1. HTTP/1.1 200 ...

You can also share the same limit counter for all your requests by setting the key_type to constant:

  1. curl -i http://127.0.0.1:9080/apisix/admin/services/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
  2. {
  3. "plugins": {
  4. "limit-count": {
  5. "count": 1,
  6. "time_window": 60,
  7. "rejected_code": 503,
  8. "key": "remote_addr",
  9. "key_type": "constant",
  10. "group": "services_1#1640140621"
  11. }
  12. },
  13. "upstream": {
  14. "type": "roundrobin",
  15. "nodes": {
  16. "127.0.0.1:1980": 1
  17. }
  18. }
  19. }'

Now every request will share the same count limitation regardless of their remote address.

For cluster-level traffic limiting, you can use a Redis server. The counter will be shared between different APISIX nodes to achieve traffic limiting.

The example below shows how you can use the redis policy:

  1. curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
  2. {
  3. "uri": "/index.html",
  4. "plugins": {
  5. "limit-count": {
  6. "count": 2,
  7. "time_window": 60,
  8. "rejected_code": 503,
  9. "key": "remote_addr",
  10. "policy": "redis",
  11. "redis_host": "127.0.0.1",
  12. "redis_port": 6379,
  13. "redis_password": "password",
  14. "redis_database": 1,
  15. "redis_timeout": 1001
  16. }
  17. },
  18. "upstream": {
  19. "type": "roundrobin",
  20. "nodes": {
  21. "127.0.0.1:1980": 1
  22. }
  23. }
  24. }'

Similarly you can also configure the redis-cluster policy:

  1. curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
  2. {
  3. "uri": "/index.html",
  4. "plugins": {
  5. "limit-count": {
  6. "count": 2,
  7. "time_window": 60,
  8. "rejected_code": 503,
  9. "key": "remote_addr",
  10. "policy": "redis-cluster",
  11. "redis_cluster_nodes": [
  12. "127.0.0.1:5000",
  13. "127.0.0.1:5001"
  14. ],
  15. "redis_password": "password",
  16. "redis_cluster_name": "redis-cluster-1"
  17. }
  18. },
  19. "upstream": {
  20. "type": "roundrobin",
  21. "nodes": {
  22. "127.0.0.1:1980": 1
  23. }
  24. }
  25. }'

Example usage

The above configuration limits to 2 requests in 60 seconds. The first two requests will work and the response headers will contain the headers X-RateLimit-Limit and X-RateLimit-Remaining:

  1. curl -i http://127.0.0.1:9080/index.html
  1. HTTP/1.1 200 OK
  2. Content-Type: text/html
  3. Content-Length: 13175
  4. Connection: keep-alive
  5. X-RateLimit-Limit: 2
  6. X-RateLimit-Remaining: 0
  7. Server: APISIX web server

When you visit for a third time in the 60 seconds, you will receive a response with 503 code:

  1. HTTP/1.1 503 Service Temporarily Unavailable
  2. Content-Type: text/html
  3. Content-Length: 194
  4. Connection: keep-alive
  5. Server: APISIX web server
  6. <html>
  7. <head><title>503 Service Temporarily Unavailable</title></head>
  8. <body>
  9. <center><h1>503 Service Temporarily Unavailable</h1></center>
  10. <hr><center>openresty</center>
  11. </body>
  12. </html>

You can also set a custom response by configuring the rejected_msg attribute:

  1. HTTP/1.1 503 Service Temporarily Unavailable
  2. Content-Type: text/html
  3. Content-Length: 194
  4. Connection: keep-alive
  5. Server: APISIX web server
  6. {"error_msg":"Requests are too frequent, please try again later."}

Disable Plugin

To disable the limit-count 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.

  1. curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
  2. {
  3. "methods": ["GET"],
  4. "uri": "/index.html",
  5. "upstream": {
  6. "type": "roundrobin",
  7. "nodes": {
  8. "127.0.0.1:1980": 1
  9. }
  10. }
  11. }'