我正在尝试限制 nginx 连接的速度,但似乎没有按预期工作。我尝试使用每秒 2 和 10 个请求进行测试。
首先,每秒 2 个请求
limit_req_zone $binary_remote_addr zone=myzone:10m rate=2r/s;
limit_req_status 429;
server {
listen *:80;
server_name 172.23.97.94;
root /var/www/html;
index index.html;
location / {
limit_req zone=myzone;
try_files $uri $uri/ =404;
}
}
通过 curl 测试:
for i in {1..2}; do curl -I -s "http://172.23.97.94" | head -n 1; done
HTTP/1.1 200 OK
HTTP/1.1 429 Too Many Requests
Access.log 确认同一时间只有 2 个请求,但是第二个请求却得到 429:
172.23.106.65 - - [08/Feb/2023:17:10:35 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.68.0"
172.23.106.65 - - [08/Feb/2023:17:10:35 +0000] "HEAD / HTTP/1.1" 429 0 "-" "curl/7.68.0"
但是如果我以 0.5 秒的睡眠时间执行相同的请求,则一切顺利:
for i in {1..2}; do curl -I -s "http://172.23.97.94" | head -n 1; sleep 0.5; done
HTTP/1.1 200 OK
HTTP/1.1 200 OK
秒,每秒 10 个请求
limit_req_zone $binary_remote_addr zone=myzone:10m rate=10r/s;
limit_req_status 429;
server {
listen *:80;
server_name 172.23.97.94;
root /var/www/html;
index index.html;
location / {
limit_req zone=myzone;
try_files $uri $uri/ =404;
}
}
通过 curl 测试:
for i in {1..10}; do curl -I -s "http://172.23.97.94" | head -n 1; done
HTTP/1.1 200 OK
HTTP/1.1 429 Too Many Requests
HTTP/1.1 429 Too Many Requests
HTTP/1.1 429 Too Many Requests
HTTP/1.1 429 Too Many Requests
HTTP/1.1 429 Too Many Requests
HTTP/1.1 429 Too Many Requests
HTTP/1.1 429 Too Many Requests
HTTP/1.1 429 Too Many Requests
HTTP/1.1 429 Too Many Requests
Access.log 确认同时只有 10 个连接,但只有第一个获得了 200 个:
172.23.106.65 - - [08/Feb/2023:17:14:53 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.68.0"
172.23.106.65 - - [08/Feb/2023:17:14:53 +0000] "HEAD / HTTP/1.1" 429 0 "-" "curl/7.68.0"
172.23.106.65 - - [08/Feb/2023:17:14:53 +0000] "HEAD / HTTP/1.1" 429 0 "-" "curl/7.68.0"
172.23.106.65 - - [08/Feb/2023:17:14:53 +0000] "HEAD / HTTP/1.1" 429 0 "-" "curl/7.68.0"
172.23.106.65 - - [08/Feb/2023:17:14:53 +0000] "HEAD / HTTP/1.1" 429 0 "-" "curl/7.68.0"
172.23.106.65 - - [08/Feb/2023:17:14:53 +0000] "HEAD / HTTP/1.1" 429 0 "-" "curl/7.68.0"
172.23.106.65 - - [08/Feb/2023:17:14:53 +0000] "HEAD / HTTP/1.1" 429 0 "-" "curl/7.68.0"
172.23.106.65 - - [08/Feb/2023:17:14:53 +0000] "HEAD / HTTP/1.1" 429 0 "-" "curl/7.68.0"
172.23.106.65 - - [08/Feb/2023:17:14:53 +0000] "HEAD / HTTP/1.1" 429 0 "-" "curl/7.68.0"
172.23.106.65 - - [08/Feb/2023:17:14:53 +0000] "HEAD / HTTP/1.1" 429 0 "-" "curl/7.68.0"
但是如果我以 0.01 秒的睡眠时间执行相同的请求,其中一些是 200,而其他是 429:
for i in {1..10}; do curl -I -s "http://172.23.97.94/device/1" | head -n 1; sleep 0.01; done
HTTP/1.1 200 OK
HTTP/1.1 429 Too Many Requests
HTTP/1.1 429 Too Many Requests
HTTP/1.1 429 Too Many Requests
HTTP/1.1 429 Too Many Requests
HTTP/1.1 200 OK
HTTP/1.1 429 Too Many Requests
HTTP/1.1 429 Too Many Requests
HTTP/1.1 429 Too Many Requests
HTTP/1.1 200 OK
我做错了什么吗?还是速率限制根本就没有按预期发挥作用?
答案1
我也遇到了这个问题 - 10r/s 实际上是指每十分之一秒发出一个请求。
以下是相关的 Stack Overflow 帖子:https://stackoverflow.com/questions/62262540/ideal-config-for-nginx-rate-limiting
以下是他们引用的 nginx 中有关此问题的文章:https://www.nginx.com/blog/rate-limiting-nginx/
在我看来这是一个糟糕的决定,因为一个页面通常需要加载几个 ajax 请求,而这种工作方式会导致在进行任何速率限制时这些请求受到延迟。
从文章来看,似乎有办法解决这个问题,即使用“nodelay”选项,然后进行两阶段速率限制。
limit_req zone=ip burst=12 delay=8;
它会同时允许 8 个请求,然后会延迟这些请求,直到队列中有 12 个请求时,它才会开始拒绝这些请求。