In NGINX 및 NGINX Plus를 사용한 로드 밸런싱, 1부에서는 여러 웹 서버에 트래픽을 분산하기 위해 간단한 HTTP 프록시를 설정했습니다. 이 글에서는 다음과 같은 추가 기능을 살펴봅니다. 이 중 일부는 NGINX Plus에서 사용할 수 있습니다. keepalive를 통한 성능 최적화, 상태 확인, 세션 지속성, 리디렉션, 콘텐츠 재작성입니다.
NGINX 및 NGINX Plus의 부하 분산 기능에 대한 자세한 내용은 NGINX Plus 관리자 가이드를 참조하세요.
편집자 주 – NGINX Plus 릴리스 5 이상에서는 TCP 기반 애플리케이션의 부하 분산도 지원합니다. TCP 부하 분산 기능은 릴리스 6에서 상태 확인, 동적 재구성, SSL 종료 등의 기능이 추가되면서 크게 확장되었습니다. NGINX Plus 릴리스 7 이상에서는 TCP 부하 분산기가 HTTP 부하 분산기와 완전히 동일한 기능을 제공합니다. UDP 부하 분산 지원은 릴리스 9에서 도입되었습니다.
TCP 및 UDP 부하 분산은 stream 컨텍스트에서 구성하며, http 컨텍스트에서는 구성하지 않습니다. HTTP와 TCP/UDP의 본질적인 차이로 인해 사용할 수 있는 지시문과 매개변수가 다소 다릅니다. 자세한 내용은 HTTP 및 TCP/UDP 업스트림 모듈 설명서를 참조하세요.
간단히 살펴보기
다시 살펴보면, 다음은 이전 글에서 구성한 설정입니다:
server { listen 80;
location / {
proxy_pass http://backend;
# Rewrite the 'Host' header to the value in the client request,
# or primary server name
proxy_set_header Host $host;
# Alternatively, put the value in the config:
# proxy_set_header Host www.example.com;
}
}
upstream backend {
zone backend 64k; # Use NGINX Plus' shared memory
least_conn;
server webserver1 weight=1;
server webserver2 weight=4;
}이 글에서는 로드 밸런싱의 효율성을 높일 수 있는 몇 가지 간단한 NGINX 및 NGINX Plus 구성 방법을 살펴보겠습니다.
HTTP 연결 유지
NGINX 또는 NGINX Plus와 업스트림 서버 간에 HTTP 연결 유지를 활성화하면 지연 시간이 줄어 성능이 향상되고, NGINX의 임시 포트가 고갈될 가능성도 낮아집니다.
HTTP 프로토콜은 기반 TCP 연결을 사용하여 HTTP 요청을 전송하고 HTTP 응답을 수신합니다. HTTP 연결 유지 연결을 사용하면 이러한 TCP 연결을 재사용할 수 있으므로 요청마다 연결을 생성하고 종료하는 데 드는 오버헤드를 방지할 수 있습니다:
NGINX는 완전한 프록시로서 클라이언트의 연결(프런트엔드 연결 유지 연결)과 서버의 연결(업스트림 연결 유지 연결)을 각각 독립적으로 관리합니다:

NGINX는 업스트림 서버에 대한 유휴 keepalive 연결 모음인 keepalive 연결 “캐시”를 유지합니다. 업스트림으로 요청을 전달해야 할 때는 새 TCP 연결을 생성하는 대신 캐시에 있는 기존 keepalive 연결을 사용합니다. 이를 통해 NGINX와 업스트림 서버 간 트랜잭션 지연 시간이 줄어들고 임시 포트 사용 속도도 낮아지므로, NGINX는 대량의 트래픽을 수용하고 부하를 분산할 수 있습니다. 트래픽이 급증하면 캐시가 소진될 수 있으며, 이 경우 NGINX는 업스트림 서버에 대한 새 HTTP 연결을 설정합니다.
다른 부하 분산 도구에서는 이 기법을 멀티플렉싱, 연결 풀링, 연결 재사용, 또는 OneConnect라고도 합니다.
구성에 다음 지시어를 포함하여 keepalive 연결 캐시를 설정합니다: proxy_http_version, proxy_set_header, keepalive directives in the configuration:
server { listen 80;
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
upstream backend {
server webserver1;
server webserver2;
# maintain up to 20 idle connections to the group of upstream servers
keepalive 20;
}상태 확인
상태 확인을 활성화하면 부하 분산 서비스의 안정성이 향상되고, 최종 사용자에게 오류 메시지가 표시될 가능성이 줄어들며, 일반적인 유지 관리 작업도 더 수월하게 수행할 수 있습니다.
NGINX Plus의 상태 확인 기능을 사용하면 업스트림 서버의 장애를 감지할 수 있습니다. NGINX Plus는 “합성 트랜잭션”을 사용하여 각 서버를 검사하고, 응답이 health_check 지시문에 설정한 매개변수와 일치하는지 확인합니다. 또한 match 매개변수를 포함한 경우에는 연결된 match 구성 블록의 설정과도 비교합니다:
server { listen 80;
location / {
proxy_pass http://backend;
health_check interval=2s fails=1 passes=5 uri=/test.php match=statusok;
# The health checks inherit other proxy settings
proxy_set_header Host www.foo.com;
}
}
match statusok {
# Used for /test.php health check
status 200;
header Content-Type = text/html;
body ~ "Server[0-9]+ is alive";
}상태 확인은 상위 location 블록에서 일부 매개변수를 상속합니다. 구성에서 런타임 변수를 사용하는 경우 이로 인해 문제가 발생할 수 있습니다. 예를 들어 다음 구성은 클라이언트 요청에서 Host 헤더 값을 추출하므로 실제 HTTP 트래픽에서는 작동합니다. 하지만 상태 확인에서 사용하는 합성 트랜잭션에는 Host 헤더가 설정되지 않으므로 제대로 작동하지 않을 가능성이 높습니다. 즉, 합성 트랜잭션에서는 Host 헤더가 사용되지 않습니다.
location / { proxy_pass http://backend;
# This health check might not work...
health_check interval=2s fails=1 passes=5 uri=/test.php match=statusok;
# Extract the 'Host' header from the request
proxy_set_header Host $host;
}좋은 해결 방법 중 하나는 상태 확인 트랜잭션에서 사용하는 모든 매개변수를 정적으로 정의하는 더미 location 블록을 만드는 것입니다:
location /internal-health-check1 { internal; # Prevent external requests from matching this location block
proxy_pass http://backend;
health_check interval=2s fails=1 passes=5 uri=/test.php match=statusok;
# Explicitly set request parameters; don't use run-time variables
proxy_set_header Host www.example.com;
}자세한 내용은 NGINX Plus 관리자 가이드를 참조하세요.
세션 지속성
세션 지속성을 사용하면 클러스터에 배포할 수 없는 애플리케이션도 안정적으로 부하를 분산하고 확장할 수 있습니다. 세션 상태를 저장하고 복제하는 애플리케이션은 더욱 효율적으로 작동하며 최종 사용자 성능도 향상됩니다.
일부 애플리케이션은 사용자가 가상 장바구니에 상품을 담거나 업로드한 이미지를 편집하는 경우와 같이 업스트림 서버에 상태 정보를 저장하기도 합니다. 이러한 경우 해당 사용자의 이후 모든 요청을 동일한 서버로 전달할 수 있습니다.
세션 지속성은 요청을 라우팅해야 하는 위치를 지정하는 반면, 로드 밸런싱은 NGINX가 최적의 업스트림 서버를 자유롭게 선택할 수 있도록 합니다. 이 두 프로세스는 NGINX Plus의 세션 지속성 기능을 사용하여 함께 적용할 수 있습니다.
요청이 세션 지속성 규칙과 일치하면
해당 대상 업스트림 서버를 사용하고
그렇지 않으면 부하 분산 알고리즘을 적용하여 업스트림 서버를 선택합니다
대상 서버를 사용할 수 없어 세션 지속성 결정에 실패하면 NGINX Plus가 부하 분산 결정을 내립니다.
가장 간단한 세션 지속성 방식은 “고정 쿠키” 방식으로, NGINX Plus가 첫 번째 응답에 고정 업스트림 서버를 식별하는 쿠키를 삽입합니다:
sticky cookie srv_id expires=1h domain=.example.com path=/;또 다른 “스티키 라우트” 방식에서는 NGINX가 JSESSIONID 쿠키와 같은 요청 매개변수를 기반으로 업스트림 서버를 선택합니다:
upstream backend {
server backend1.example.com route=a;
server backend2.example.com route=b;
# select first non-empty variable; it should contain either 'a' or 'b'
sticky route $route_cookie $route_uri;
}자세한 내용은 NGINX Plus 관리자 가이드를 참조하세요.
HTTP 리디렉션 재작성
일부 리디렉션이 제대로 작동하지 않는 경우, 특히 프록시에서 실제 업스트림 서버로 리디렉션되는 경우에는 HTTP 리디렉션을 다시 작성하세요.
업스트림 서버로 프록시할 때 서버는 로컬 주소에 애플리케이션을 게시하지만, 사용자는 이와 다른 주소인 프록시 주소를 통해 애플리케이션에 액세스합니다. 이러한 주소는 일반적으로 도메인 이름으로 확인되며, 서버와 프록시의 도메인이 서로 다르면 문제가 발생할 수 있습니다.
예를 들어 테스트 환경에서는 프록시에 직접(IP 주소로) 접근하거나 localhost로 접근할 수 있습니다. 하지만 업스트림 서버는 실제 도메인 이름(예: www.nginx.com)으로 수신 대기할 수 있습니다. 업스트림 서버가 리디렉션 메시지(3xx 상태 및 Location 헤더를 사용하거나 Refresh 헤더를 사용)를 보내면 메시지에 서버의 실제 도메인이 포함될 수 있습니다.
NGINX는 이 문제의 가장 일반적인 사례를 감지하여 수정하려고 합니다. 특정 재작성을 강제로 적용하기 위해 완전한 제어가 필요한 경우 다음과 같이 proxy_redirect 지시어를 사용합니다:
proxy_redirect http://staging.mysite.com/ http://$host/;HTTP 응답 재작성
경우에 따라 HTTP 응답의 콘텐츠를 다시 작성해야 할 수 있습니다. 예를 들어 위의 예시처럼 응답에 프록시가 아닌 다른 서버를 가리키는 절대 링크가 포함되어 있을 수 있습니다.
적용할 재작성 규칙을 정의하려면 sub_filter 지시어를 사용할 수 있습니다:
sub_filter /blog/ /blog-staging/;
sub_filter_once off;매우 흔히 놓치는 부분 중 하나는 HTTP 압축을 사용하는 경우입니다. 클라이언트가 압축된 데이터를 수신할 수 있다고 알리고 서버가 응답을 압축하면, NGINX는 해당 응답을 검사하거나 수정할 수 없습니다. 가장 간단한 해결 방법은 클라이언트 요청의 Accept-Encoding 헤더를 빈 문자열("")로 설정하여 제거하는 것입니다:
proxy_set_header Accept-Encoding "";전체 예시
다음은 이 문서에서 설명한 모든 기법을 적용한 부하 분산 구성 템플릿입니다. NGINX Plus에서 제공되는 고급 기능은 주황색으로 강조되어 있습니다.
[편집자 주 – 다음 구성은 실시간 활동 모니터링 및 업스트림 그룹의 동적 구성에 NGINX Plus API를 사용하도록 업데이트되었으며, 기존에 사용되던 별도의 모듈을 대체합니다.]
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Accept-Encoding "";
proxy_redirect http://staging.example.com/ http://$host/;
# Rewrite the Host header to the value in the client request
proxy_set_header Host $host;
# Replace any references inline to staging.example.com
sub_filter http://staging.example.com/ /;
sub_filter_once off;
}
location /internal-health-check1 {
internal; # Prevent external requests from matching this location block
proxy_pass http://backend;
health_check interval=2s fails=1 passes=5 uri=/test.php match=statusok;
# Explicitly set request parameters; don't use runtime variables
proxy_set_header Host www.example.com;
}
upstream backend {
zone backend 64k; # Use NGINX Plus' shared memory
least_conn;
keepalive 20;
# Apply session persistence for this upstream group
sticky cookie srv_id expires=1h domain=.example.com path=/servlet;
server webserver1 weight=1;
server webserver2 weight=4;
}
match statusok {
# Used for /test.php health check
status 200;
header Content-Type = text/html;
body ~ "Server[0-9]+ is alive";
}
server {
listen 8080;
root /usr/share/nginx/html;
location = /api {
api write=on; # Live activity monitoring and
# dynamic configuration of upstream groups
allow 127.0.0.1; # permit access from localhost
deny all; # deny access from everywhere else
}
}NGINX Plus의 뛰어난 모든 부하 분산 기능을 직접 사용해 보세요. 지금 30일 무료 체험을 시작하거나 사용 사례에 대해 논의하려면 문의해 주세요.
작성자 소개

관련 블로그 게시물
시청하기: KubeCon North America 2023에서의 NGINX Gateway Fabric
이 영상에서는 KubeCon의 NGINX 부스를 찾아가, 저희가 공개한 Kubernetes Gateway API 구현을 살펴봅니다.
F5 NGINX로 대규모 WAF 플릿을 확인하고 관리하는 2가지 방법
앱 보안을 강화하는 두 가지 방법을 소개합니다. NGINX Management Suite를 통해 WAF 운영에 대한 가시성을 높이고, NGINX App Protect WAF를 활용해 코드형 보안을 구현하는 것입니다.
Ingress 컨트롤러 선택 가이드, 4부: NGINX Ingress Controller 옵션
개발 주체, 개발 철학, 프로덕션 환경 준비도, 보안 및 지원을 기준으로 어떤 NGINX Ingress 컨트롤러가 가장 적합한지 알아보세요.
진화하는 공격 환경에 NGINX App Protect Denial of Service가 적응하는 방법
NGINX App Protect Denial of Service(DoS)가 계층 7 DoS 공격을 방어하기 위해 완화 방법을 실시간으로 조정하는 방식을 설명합니다. 정상적인 사용자 행동과 서버 상태에 대한 모델을 생성하여 공격을 나타내는 이상 징후를 감지하고 맞춤형 완화 시그니처를 적용할 수 있습니다.
NGINX Instance Manager를 활용한 대규모 구성 업데이트 및 인증서 관리
NGINX Instance Manager 버전 1.0에는 두 가지 새로운 기능이 도입되었습니다. NGINX 인스턴스에 태그와 사용자 역할을 지정하면 전체 그룹에 구성을 한 번에 적용할 수 있습니다. 인증서 검사는 만료 예정인 인증서를 감지하여 서비스 중단을 방지할 수 있도록 인증서를 교체할 수 있게 해줍니다.
Netflix가 자사 CDN의 핵심으로 NGINX를 선택한 이유
Netflix가 글로벌 콘텐츠 전송 네트워크인 Open Connect의 스트리밍 미디어 기술로 NGINX를 선택한 이유를 NGINX 개발자 Gleb Smirnoff에게서 알아보세요.