![nginx 속도 제한이 예상대로 작동하지 않습니다](https://rvso.com/image/1684440/nginx%20%EC%86%8D%EB%8F%84%20%EC%A0%9C%ED%95%9C%EC%9D%B4%20%EC%98%88%EC%83%81%EB%8C%80%EB%A1%9C%20%EC%9E%91%EB%8F%99%ED%95%98%EC%A7%80%20%EC%95%8A%EC%8A%B5%EB%8B%88%EB%8B%A4.png)
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개가 될 때까지 요청을 지연한 다음 거부하기 시작합니다.