NGINX Plus 를 사용하여 reload 줄이기
[참고 – 이 포스트는 원래 포스트에서 언급된 별도의 동적 구성 및 status 모듈을 NGINX Plus API로 업데이트하였습니다.]
NGINX 오픈소스는 다양한 호스팅 제공 업체, CDN 및 기타 대용량 플랫폼 제공 업체의 프론트엔드 서버로 널리 사용됩니다. 캐싱, 리버스 프록시 및 정적 파일 제공은 가장 널리 사용되는 기능 중 일부입니다. 그러나 NGINX 오픈소스 빌드를 사용하는 것이 복잡할 수 있는 특별한 사용 사례가 있습니다. 바로 대용량 호스팅입니다.
이 포스트에서는 NGINX Plus 기능을 사용하여 대용량 호스팅을 더 쉽고 신뢰성 있게 할 수 있는 방법을 설명하겠습니다. 이를 통해 엔지니어링 및 운영 리소스를 확보하는 방법을 설명합니다.
고객을 위해 많은 수의 호스트명을 처리하기 위해 리버스 프록시를 사용하는 상황을 상상해 보십시오. 매일 새로운 고객이 등록되고 기존 고객이 떠나기 때문에 NGINX 구성을 자주 업데이트해야 합니다. 또한 컨테이너와 클라우드 인프라를 사용하려면 DevOps팀은 계속해서 서로 다른 물리적 호스트와 가상 호스트 간에 지속적으로 리소스를 이동해야 합니다.
NGINX 오픈소스를 사용하면 upstream(backend) server 그룹의 구성을 재구성하려면 구성을 reload 해야 합니다. 구성을 reload 하면 다운타임은 없지만, NGINX가 과부하 상태일 때 이 작업을 수행하면 문제가 발생할 수 있습니다. 그 이유 중 하나는 구성을 reload 하는 동안 worker process가 종료되기 전에 설정된 연결을 완료해야 한다는 것입니다. 이를 드레이닝(draining)이라고 하는 과정이라고 합니다. 만약 다음과 같은 경우에는 지연이 길어질 수 있습니다.
- 대용량 파일 다운로드 진행 중
- WebSocket 프로토콜을 사용하는 클라이언트
- 연결 속도가 느린 클라이언트(3G, 모바일)
- Slowloris 공격

이전 구성을 실행 중인 worker process를 종료하는 충분한 시간을 남기지 않고 여러 번 reload 하는 것은 메모리 사용량을 증가시킬 수 있으며, 결국 시스템을 과부하로 만들 수 있습니다.
종료 상태에 있는 많은 수의 worker process는 이 문제를 나타낼 수 있습니다.
[user@frontend]$ ps afx | grep nginx
652 ? Ss 0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
1300 ? S 0:00 _ nginx: worker process is shutting down
1303 ? S 0:00 _ nginx: worker process is shutting down
1304 ? S 0:00 _ nginx: worker process is shutting down
1323 ? S 0:00 _ nginx: worker process is shutting down
1324 ? S 0:00 _ nginx: worker process is shutting down
1325 ? S 0:00 _ nginx: worker process is shutting down
1326 ? S 0:00 _ nginx: worker process is shutting down
1327 ? S 0:00 _ nginx: worker process is shutting down
1329 ? S 0:00 _ nginx: worker process is shutting down
1330 ? S 0:00 _ nginx: worker process is shutting down
1334 ? S 0:00 _ nginx: worker process
1335 ? S 0:00 _ nginx: worker process
1336 ? S 0:00 _ nginx: worker process
1337 ? S 0:00 _ nginx: worker process
다음 구성을 사용하여 구성을 자주 reload 하는 결과를 복제할 수 있습니다. 파일 상단의 주석에 구성 사용 방법이 설명되어 있습니다.
user nginx;
worker_processes 8;
events {
worker_connections 2014;
}
http {
default_type text/plain;
tcp_nodelay on;
server {
listen 8081;
return 200 "Server $server_addr:$server_port\n\nTime: $time_local\n\n
Syntax: proxy_limit_rate rate;
Default: proxy_limit_rate 0;
Context: http, server, location
프록시 서버의 응답을 읽는 속도를 초당 바이트 수로 제한합니다.
제한은 각 요청에 적용되므로 worker process가 프록시 서버에 대한
두 개의 연결을 동시에 여는 경우 전체 속도는 지정된 제한의 두 배입니다.
기본값 0(zero)은 속도 제한을 비활성화합니다.
지시문은 프록시 서버의 응답 버퍼링이 활성화된 경우에만 유효합니다,
기본적으로('proxy_buffering on' 지시문에 의해 제어됨.)
";
}
upstream backend {
zone backend 64k;
server 127.0.0.1:8081;
}
server {
listen 80 reuseport; # Hint:reuseport 매개변수를 사용하거나 사용하지 않고 테스트합니다.
proxy_limit_rate 20; # 수명이 긴 연결을 에뮬레이트하기 위해 속도를 20bps로 제한
location / {
proxy_pass http://backend;
}
}
}
목차
1. Solution: 동적 구성
1-1. NGINX Plus API를 사용한 동적 구성
1-2. Live Activity 모니터링 대시보드를 사용한 동적 구성
2. 결론
1. Solution: 동적 구성
과도한 메모리 사용 및 시스템 과부하를 방지하기 위해, 상용 제품인 NGINX Plus는 NGINX Plus API를 사용하여 업스트림 서버 그룹(Upstream 블록)의 동적 구성을 지원합니다.
동적 구성과 함께 사용할 수 있는 NGINX Plus의 또 다른 기능은 세션 지속성(session persistence)인데, 이를 통해 특정 서버가 특정 클라이언트의 요청을 처리하도록 지정할 수 있습니다. route-based 세션 지속성을 사용하면, 요청에서 발견된 모든 변수를 기반으로 어떤 서버가 요청을 처리할지를 결정하는 key를 지정할 수 있습니다. 일반적으로 사용되는 변수로는 $cookie_jsessionid 와 같은 쿠키 관련 변수와 $remote_addr 과 같은 IP 주소 변수 등이 있습니다. 다음 예시에서는 Host 헤더에 해당하는 $http_host 변수를 사용합니다.
다음은 주석이 추가된 예시로, route-based 세션 지속성을 동적 구성과 결합한 예시입니다.
user nginx;
worker_processes auto;
events {
worker_connections 1024;
}
http {
upstream vhosts {
# 서버에 대한 상태 정보를 위한 공유 메모리 영역
# 업스트림 그룹
zone vhosts 128k;
# 'Host' 헤더를 기반으로 하는 경로 기반 세션 지속성
sticky route $http_host;
# 업스트림 때문에 여기에는 '서버' 지시문이 없습니다.
# 서버는 NGINX Plus API를 사용하여 동적으로 구성됩니다.
}
server {
# 표준 HTTP 포트에서 청취하는 프로덕션 프런트엔드
listen 80;
# 'vhosts' 업스트림 그룹에 대한 메트릭 수집을 활성화합니다.
status_zone vhosts;
location / {
proxy_pass http://vhosts;
proxy_set_header Host $http_host;
}
}
server {
# 별도의 포트가 있는 업스트림 관리 전용 서버
# 방화벽으로 보호할 수 있는 것
listen 8080;
# 관리 서버에 대한 추가 보안
allow 10.0.0.0/24;
allow 127.0.0.1/32;
deny all;
# NGINX Plus 정적 파일 위치
root /usr/share/nginx/html;
# NGINX Plus API를 활성화합니다.
location /api {
api write=on;
}
# NGINX Plus 대시보드용 HTML 페이지
location = /dashboard.html { }
# 요청을 대시보드로 라우팅
location = / {
return 301 /dashboard.html;
}
}
}
1-1. NGINX Plus API를 사용한 동적 구성
이 구성의 upstream 블록에 백엔드 서버의 호스트명을 정의하기 위한 어떠한 server 지시문도 포함되어 있지 않습니다. 우리는 NGINX Plus API를 사용하여 이를 동적으로 정의할 것입니다. API에 액세스하는 가장 쉬운 방법은 curl 명령을 사용하는 것입니다.
호스팅 환경에 다음 고객을 추가한다고 가정하겠습니다.
고객 hostname | 백엔드 서버 IP, Port |
---|---|
http://www.company1.com | 127.0.0.1:8080 |
http://www.company2.com | 10.0.0.10:8000 |
http://www.homepage1.com | 10.0.0.10:8001 |
고객을 추가하기 위해 다음과 같은 명령을 실행하여 NGINX Plus API에 접근합니다. 우리는 NGINX Plus 호스트 쉘에 로그인했지만, 이러한 명령은 안전한 위치에서 다음 명령을 실행할 수 있습니다.
[user@frontend]$ curl -X POST -d '{"server":"127.0.0.1:8080", "route":"www.company1.com"}' http://127.0.0.1:8080/api/version/http/upstreams/vhosts/servers
[user@frontend]$ curl -X POST -d '{"server":"10.0.0.10:8000", "route":"www.company2.com"}' http://127.0.0.1:8080/api/version/http/upstreams/vhosts/servers
[user@frontend]$ curl -X POST -d '{"server":"10.0.0.10:8001", "route":"www.homepage1.com"}' http://127.0.0.1:8080/api/version/http/upstreams/vhosts/servers
업스트림 서버를 나열하고 해당 내부 ID 번호를 알아보려면 다음 명령을 실행하면 됩니다. 출력을 jq 유틸리티로 파이핑(piping)하여 각 서버의 이름 또는 주소, ID 및 route만 필터링하여 출력합니다.
[user@frontend]$ curl -s http://127.0.0.1:8080/api/version/http/upstreams/vhosts | jq -c '.peers[] | {server, id, route}'
{"server":"127.0.0.1:8080","id":0,"route":"www.company1.com"}
{"server":"10.0.0.10:8000","id":1,"route":"www.company2.com"}
{"server":"10.0.0.10:8001","id":2,"route":"www.homepage1.com"}
업스트림에서 서버를 제거하려면 이전 명령으로 보고된 ID로 식별하면 됩니다. 위에서 추가한 세 번째 서버를 예시로 들면 다음과 같습니다.
[user@frontend]$ curl -X DELETE http://127.0.0.1:8080/api/version/http/upstreams/vhosts/servers/2
기본적으로 NGINX Plus API를 사용하여 수행한 변경 사항은 기본적으로 구성을 reload 해도 유지되지만. NGINX 프로세스를 다시 시작할 때는 유지되지 않습니다. NGINX Plus R8 이상에서는 변경 사항을 완전히 유지하기 위해 upstream 블록에 state 지시문을 포함할 수 있습니다. state 지시문은 NGINX Plus가 업스트림 그룹의 서버에 대한 상태 정보를 저장하는 파일의 이름을 지정합니다. 이를 구성에 포함하면 서버를 정적으로 정의하는 server 지시문도 포함할 수 없습니다.
1-2. NGINX Plus 의 Live Activity 모니터링 대시보드를 사용한 동적 구성
NGINX Plus의 Live Activity 모니터링 대시보드를 사용하면 현재 서버 구성을 확인하고 동적으로 변경할 수도 있습니다. dynamic-upstream-configuration.conf 파일에 있는 지시문들은 Live Activity 모니터링을 구성하는 데 필요한 모든 내용입니다. 이러한 지시문을 사용하면 NGINX Plus 호스트의 웹 브라우저에서 http://your-nginx-server:8080/dashboard.html을 열어 대시보드에 접근할 수 있습니다.
또한, NGINX Plus API 참조 문서에 설명된 URL endpoints를 통해 NGINX Plus API에서 모니터링 매트릭에 접근할 수 있습니다.
작동 중인 대시보드의 live demo는 https://demo.nginx.com/을 확인하십시오.
2. 결론
호스트명과 해당하는 백엔드 서비스를 자주 추가하고 제거하는 것은 과부하 배포 환경에서 불필요한 메모리 사용 증가와 이로 인한 성능 문제가 발생할 수 있습니다. NGINX Plus로 스택을 업그레이드하면 NGINX Plus API와 세션 지속성의 도움을 받아 이러한 문제를 해결할 수 있고 메모리 사용을 효율적으로 관리할 수 있습니다.
NGINX Plus의 고급 기능을 사용하면 필요한 프로세스 reload 횟수가 줄어들고, 고객 요청에 대한 응답성을 향상하며, 인프라의 확장성을 향상하고, 기술팀이 다른 중요한 작업에 시간을 투자할 수 있습니다. 이러한 고급 기능은 기술적인 측면에서도 팀의 업무를 효율적으로 처리하고, 다른 비즈니스적으로 중요한 작업에 집중할 수 있게 됩니다.
NGINX Plus를 직접 사용해 보시려면 30일 무료 평가판을 신청하거나 NGINX STORE에 연락하여 문의하십시오.
사용 사례에 대해 최신 소식을 빠르게 전달받고 싶으시면 아래 뉴스레터를 구독하세요.
댓글을 달려면 로그인해야 합니다.