Rate Limiting
Basic Configuration
bash
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
server {
location /login/ {
limit_req zone=mylimit;
proxy_pass http://my_upstream;
}
}
limit_req_zone
: Defines the params for rate limiting.- Defined in the
http
block
- Defined in the
$binary_remote_addr
: Binary format remote address.- Limiting each unique IP address to the request rate.
- Less space than
remote_addr
(string format).
- Less space than
- Limiting each unique IP address to the request rate.
zone:mylimit:10m
: Defines a 10 megabyte shared memory.- About 16000 IPS per megabyte.
- If storage is exhausted, it removes the oldest entry.
- About 16000 IPS per megabyte.
limit_req
: Enables rate limiting.- Defined in
localtion
orserver
block.
- Defined in
rate=10r/s
: 10 requests per second.- NGINX actually tracks requests at millisecond.
- The actual limit is 1 request per 100 milliseconds (ms).
- NGINX actually tracks requests at millisecond.
Handling Bursts
bash
location /login/ {
limit_req zone=mylimit burst=20;
proxy_pass http://my_upstream;
}
burst=20
: Queue size 20, like a buffer.- If 22 requests arrive at the same time.
- 1 request will forward to the backend upstream.
- 20 requests will go to the buffer.
- 1 request will return 503 to the client.
- If 22 requests arrive at the same time.
Queueing with No Delay
bash
location /login/ {
limit_req zone=mylimit burst=20 nodelay;
proxy_pass http://my_upstream;
}
nodelay
: Forward it immediately if the queue is not full.- No queue pop action.
- Release queue slot after 100ms(rate=10r/s).
- No queue pop action.
Log Level
prolog
2015/06/13 04:20:00 [error] 120315#0: *32086 limiting requests, excess: 1.000 by zone “mylimit”, client: 192.168.1.2, server: nginx.com, request: “GET / HTTP/1.0”, host: “nginx.com”
By default, NGINX logs refused requests at the error
level.
bash
location /login/ {
limit_req zone=mylimit burst=20 nodelay;
limit_req_log_level warn;
proxy_pass http://my_upstream;
}
Error Code Sent to Client
bash
location /login/ {
limit_req zone=mylimit burst=20 nodelay;
limit_req_status 444;
}
Denying to a Location
bash
location /foo.php {
deny all;
}
Advanced Configuration
bash
geo $limit {
default 1;
10.0.0.0/8 0;
192.168.0.0/24 0;
}
map $limit $limit_key {
0 "";
1 $binary_remote_addr;
}
limit_req_zone $limit_key zone=req_zone:10m rate=5r/s;
server {
location / {
limit_req zone=req_zone burst=10 nodelay;
}
}
geo $limit
: Set$limit
value by client ip.- If client ip in range
10.0.0.0/8
, set$limit
to0
.- If client ip in range
192.168.0.0/24
, set$limit
to0
. - Otherwise, set
$limit
to1
.
- If client ip in range
- If client ip in range
map $limit $limit_key
: Set$limit_key
value by$limit
.- If
$limit
is0
, set$limit_key
to""
.- If
$limit
is1
, set$limit_key
to$binary_remote_addr
.
- If
- If
limit_req_zone
:- If
$limit_key
is""
, let it go.- If
$limit_key
is$binary_remote_addr
, check request rate.
- If
- If