nginx 速率限制未按预期工作

nginx 速率限制未按预期工作

我正在尝试限制 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 个请求时,它才会开始拒绝这些请求。

相关内容