Skip to main content

limit-conn

The limit-conn plugin limits the rate of requests by the number of concurrent connections. Requests exceeding the threshold will be delayed or rejected based on the configuration, ensuring controlled resource usage and preventing overload.

Examples

The examples below demonstrate how you can configure limit-conn in different scenarios.

Apply Rate Limiting by Remote Address

The following example demonstrates how to use limit-conn to rate limit requests by remote_addr, with example connection and burst thresholds.

Create a route with limit-conn plugin as such:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "limit-conn-route",
"uri": "/get",
"plugins": {
"limit-conn": {
"conn": 2,
"burst": 1,
"default_conn_delay": 0.1,
"key_type": "var",
"key": "remote_addr",
"policy": "local",
"rejected_code": 429
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

conn: allow 2 concurrent requests.

burst: allow 1 excessive concurrent request.

default_conn_delay: Allow 0.1 second of processing latency for concurrent requests exceeding conn + burst.

key_type: set to vars to interpret key as a variable.

key: calculate rate limiting count by request's remote_address.

policy: use the local counter in memory.

rejected_code: set the rejection status code to 429.

Send five concurrent requests to the route:

seq 1 5 | xargs -n1 -P5 bash -c 'curl -s -o /dev/null -w "Response: %{http_code}\n" "http://127.0.0.1:9080/get"'

You should see responses similar to the following, where excessive requests are rejected:

Response: 200
Response: 200
Response: 200
Response: 429
Response: 429

Apply Rate Limiting by Remote Address and Consumer Name

The following example demonstrates how to use limit-conn to rate limit requests by a combination of variables, remote_addr and consumer_name.

Create a consumer john:

curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"username": "john"
}'

Create key-auth credential for the consumer:

curl "http://127.0.0.1:9180/apisix/admin/consumers/john/credentials" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "cred-john-key-auth",
"plugins": {
"key-auth": {
"key": "john-key"
}
}
}'

Create a second consumer jane:

curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"username": "jane"
}'

Create key-auth credential for the consumer:

curl "http://127.0.0.1:9180/apisix/admin/consumers/jane/credentials" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "cred-jane-key-auth",
"plugins": {
"key-auth": {
"key": "jane-key"
}
}
}'

Create a route with key-auth and limit-conn plugins:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "limit-conn-route",
"uri": "/get",
"plugins": {
"key-auth": {},
"limit-conn": {
"conn": 2,
"burst": 1,
"default_conn_delay": 0.1,
"rejected_code": 429,
"key_type": "var_combination",
"key": "$remote_addr $consumer_name"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

key-auth: enable key authentication on the route.

key_type: set to var_combination to interpret the key is as a combination of variables.

key: set to $remote_addr $consumer_name to apply rate limiting quota by remote address and consumer.

Send five concurrent requests as the consumer john:

seq 1 5 | xargs -n1 -P5 bash -c 'curl -s -o /dev/null -w "Response: %{http_code}\n" "http://127.0.0.1:9080/get" -H "apikey: john-key"'

You should see responses similar to the following, where excessive requests are rejected:

Response: 200
Response: 200
Response: 200
Response: 429
Response: 429

Immediately send five concurrent requests as the consumer jane:

seq 1 5 | xargs -n1 -P5 bash -c 'curl -s -o /dev/null -w "Response: %{http_code}\n" "http://127.0.0.1:9080/get" -H "apikey: jane-key"'

You should also see responses similar to the following, where excessive requests are rejected:

Response: 200
Response: 200
Response: 200
Response: 429
Response: 429

In this case, the plugin rate limits by the combination of variables remote_addr and consumer_name, which means each consumer's quota is independent.

Rate Limit WebSocket Connections

The following example demonstrates how you can use the limit-conn plugin to limit the number of concurrent WebSocket connections.

Start a sample upstream WebSocket server:

docker run -d \
-p 8080:8080 \
--name websocket-server \
--network=apisix-quickstart-net \
jmalloc/echo-server

Create a route to the server WebSocket endpoint and enable WebSocket for the route:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT -d '
{
"id": "ws-route",
"uri": "/.ws",
"plugins": {
"limit-conn": {
"conn": 2,
"burst": 1,
"default_conn_delay": 0.1,
"key_type": "var",
"key": "remote_addr",
"rejected_code": 429
}
},
"enable_websocket": true,
"upstream": {
"type": "roundrobin",
"nodes": {
"websocket-server:8080": 1
}
}
}'

❶ Enable WebSocket for the route.

❷ Replace with your WebSocket server address.

Install a WebSocket client, such as websocat, if you have not already. Establish connection with the WebSocket server through the route:

websocat "ws://127.0.0.1:9080/.ws"

Send a "hello" message in the terminal, you should see the WebSocket server echoes back the same message:

Request served by 1cd244052136
hello
hello

Open three more terminal sessions and run:

websocat "ws://127.0.0.1:9080/.ws"

You should see the last terminal session prints 429 Too Many Requests when you try to establish a WebSocket connection with the server, due to the rate limiting effect.

Share Quota Among APISIX Nodes with a Redis Server

The following example demonstrates the rate limiting of requests across multiple APISIX nodes with a Redis server, such that different APISIX nodes share the same rate limiting quota.

On each APISIX instance, create a route with the following configurations. Adjust the address of the Admin API accordingly.

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "limit-conn-route",
"uri": "/get",
"plugins": {
"limit-conn": {
"conn": 1,
"burst": 1,
"default_conn_delay": 0.1,
"rejected_code": 429,
"key_type": "var",
"key": "remote_addr",
"policy": "redis",
"redis_host": "192.168.xxx.xxx",
"redis_port": 6379,
"redis_password": "p@ssw0rd",
"redis_database": 1
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

policy: set to redis to use a Redis instance for rate limiting.

redis_host: set to Redis instance IP address.

redis_port: set to Redis instance listening port.

redis_password: set to the password of the Redis instance, if any.

redis_database: set to the database number in the Redis instance.

Send five concurrent requests to the route:

seq 1 5 | xargs -n1 -P5 bash -c 'curl -s -o /dev/null -w "Response: %{http_code}\n" "http://127.0.0.1:9080/get"'

You should see responses similar to the following, where excessive requests are rejected:

Response: 200
Response: 200
Response: 429
Response: 429
Response: 429

This shows the two routes configured in different APISIX instances share the same quota.

Share Quota Among APISIX Nodes with a Redis Cluster

You can also use a Redis cluster to apply the same quota across multiple APISIX nodes, such that different APISIX nodes share the same rate limiting quota.

Ensure that your Redis instances are running in cluster mode. A minimum of two nodes are required for the limit-conn plugin configurations.

On each APISIX instance, create a route with the following configurations. Adjust the address of the Admin API accordingly.

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "limit-conn-route",
"uri": "/get",
"plugins": {
"limit-conn": {
"conn": 1,
"burst": 1,
"default_conn_delay": 0.1,
"rejected_code": 429,
"key_type": "var",
"key": "remote_addr",
"policy": "redis-cluster",
"redis_cluster_nodes": [
"192.168.xxx.xxx:6379",
"192.168.xxx.xxx:16379"
],
"redis_password": "p@ssw0rd",
"redis_cluster_name": "redis-cluster-1",
"redis_cluster_ssl": true
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

policy: set to redis-cluster to use a Redis cluster for rate limiting.

redis_cluster_nodes: set to Redis node addresses in the Redis cluster.

redis_password: set to the password of the Redis cluster, if any.

redis_cluster_name: set to the Redis cluster name.

redis_cluster_ssl: enable SSL/TLS communication with Redis cluster.

Send five concurrent requests to the route:

seq 1 5 | xargs -n1 -P5 bash -c 'curl -s -o /dev/null -w "Response: %{http_code}\n" "http://127.0.0.1:9080/get"'

You should see responses similar to the following, where excessive requests are rejected:

Response: 200
Response: 200
Response: 429
Response: 429
Response: 429

This shows the two routes configured in different APISIX instances share the same quota.


API7.ai Logo

API Management for Modern Architectures with Edge, API Gateway, Kubernetes, and Service Mesh.

Product

API7 Cloud

SOC2 Type IIISO 27001HIPAAGDPRRed Herring

Copyright © APISEVEN PTE. LTD 2019 – 2024. Apache, Apache APISIX, APISIX, and associated open source project names are trademarks of the

Apache Software Foundation