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;
  }
}

컬을 통한 테스트:

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;
      }
    }

컬을 통한 테스트:

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는 실제로 10분의 1초당 하나의 요청이다.

관련 Stack Overflow 게시물은 다음과 같습니다.https://stackoverflow.com/questions/62262540/ideal-config-for-nginx-rate-limiting

다음은 nginx에서 참조한 기사입니다.https://www.nginx.com/blog/rate-limiting-nginx/

한 페이지에 몇 개의 Ajax 요청을 로드하는 것이 일반적이고 이것이 작동하는 방식은 속도 제한을 수행할 때 지연되기 때문에 나에게는 나쁜 결정인 것 같습니다.

기사에 따르면 'nodelay' 옵션을 사용하고 2단계 속도 제한을 수행하여 이 문제를 해결할 수 있는 방법이 있는 것 같습니다.

limit_req zone=ip burst=12 delay=8;

한 번에 8개의 요청을 허용한 다음 대기열에 12개가 될 때까지 요청을 지연한 다음 거부하기 시작합니다.

관련 정보