서버가 과도한 요청에 의해 과부하되는 것을 방지하기 위해 Nginx로 요청 횟수 제한을 설정하는 방법을 소개합니다. 이 방법을 통해 특정 경로(/api/
)에 대해 요청을 제한하고, 서버의 안정성을 유지할 수 있습니다. Nginx의 limit_req
모듈을 사용하면 쉽게 구현할 수 있습니다.
먼저, 요청 속도를 제한하기 위해 Nginx 설정 파일을 수정해야 합니다. 기본적으로 요청 속도 제한을 위한 limit_req_zone
을 설정하고, 특정 경로(/api/
)에 대해 limit_req
를 적용합니다.
limit_req_zone
설정limit_req_zone
은 요청 속도를 추적하기 위한 메모리 영역(zone)을 정의합니다. 이 설정은 http
블록에 추가되어야 합니다.
cd /etc/nginx/
sudo vim nginx.conf
limit_req_zone
을 설정합니다.user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
# 요청 속도 제한을 위한 zone 정의 (1초에 100번 요청)
limit_req_zone $binary_remote_addr zone=api_limit:5m rate=100r/s;
# 다른 설정들...
}
limit_req_zone
:
api_limit
: 요청을 추적할 메모리 영역의 이름입니다.zone=api_limit:5m
: 이 메모리 영역은 5MB의 크기를 가집니다.rate=100r/s
: 1초에 최대 100개의 요청을 허용합니다.$binary_remote_addr
: 클라이언트의 IP 주소를 기준으로 요청을 추적합니다.limit_req
설정이제 server
또는 location
블록 내에서 실제로 요청 제한을 적용합니다. 예를 들어 /api/
경로에 대해 요청 횟수를 제한하고, 초과된 요청은 거부하도록 설정할 수 있습니다.
server {
listen 443 ssl;
server_name your-domain.com;
ssl_certificate /etc/letsencrypt/live/your-domain/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain/privkey.pem;
# API 요청을 Spring 백엔드로 프록시
location /api/ {
# 초과 요청을 200개까지 허용, 초과는 즉시 거부
limit_req zone=api_limit burst=200 nodelay;
proxy_pass http://localhost:8080; # Spring 서버로 요청을 프록시
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
limit_req zone=api_limit
: 앞에서 정의한 api_limit
메모리 영역을 사용하여 요청 제한을 적용합니다.burst=200
: burst
*는 초과할 수 있는 요청 수를 설정합니다. 예를 들어, 1초에 100번 요청을 허용하는데 200개**까지는 일시적으로 허용합니다.nodelay
: 초과된 요청을 즉시 거부하도록 설정합니다. 즉, 200번을 초과한 요청은 지연 없이 바로 503 오류가 발생합니다.설정을 완료한 후에는 Nginx를 재로드하여 변경사항을 적용해야 합니다.
sudo nginx -s reload
설정이 제대로 적용되었는지 확인하려면 ab
(Apache Benchmark) 도구를 사용하여 요청을 보내고, HTTP 503 오류가 발생하는지 확인할 수 있습니다.
ab -n 200 -c 200 https://matal.kro.kr/api/store/1
n 200
: 총 201개의 요청을 보냅니다.c 200
: 한 번에 201개의 요청을 동시 실행합니다.이 명령을 실행한 후 503 Service Unavailable 오류가 발생하면, 요청 제한이 제대로 작동하고 있다는 것을 확인할 수 있습니다.
nodelay
와 delay
는 요청 초과 시 처리하는 방식에서 중요한 차이를 보입니다.
nodelay
: 초과 요청을 즉시 503 오류로 처리합니다. 이 방식은 서버 부하를 바로 줄일 수 있지만, 사용자에게 갑작스러운 오류를 경험하게 할 수 있습니다.delay
: 초과된 요청을 대기열에 쌓아 두고 처리합니다. 이 방식은 사용자에게 더 부드러운 경험을 제공하지만, 요청이 대기열에 쌓이는 동안 응답 시간이 지연될 수 있습니다.1번째 테스트
ab -n 200 -c 200 https://matal.kro.kr/api/store/1
2번째 테스트
ab -n 300 -c 300 https://matal.kro.kr/api/store/1
nodelay인 경우 - 실패 횟수 27회
delay = 10인 경우 - 25회
💡 Apache Benchmark 도구를 사용한 테스트가 정확하다고 할 수 없습니다. 네트워크가 어떻게 구성되어 있고 요청이 어떤 네트워크를 거쳐 들어오는지 모르기 때문에 매 테스트마다 실패 요청이 다릅니다. 감안하고 봐주세요!!
503 오류
가 자주 발생하는 경우, burst
값이나 rate
를 조정하여 서버 부하를 관리할 수 있습니다.nodelay
대신 delay
를 사용하여 초과 요청이 대기열에 쌓이도록 할 수도 있습니다.Nginx의 limit_req
모듈을 사용하면 특정 API 경로에 대해 요청 횟수를 제한할 수 있습니다. 이 설정을 통해 API 서버의 부하를 관리하고, 비정상적인 트래픽을 제한하여 시스템의 안정성을 확보할 수 있습니다.