NGINX 및 NGINX Plus Load Balancer, 2부

NGINX 및 NGINX Plus Load Balancer, 1부에서는 여러 웹 서버에서 트래픽을 로드 밸런싱하는 간단한 HTTP 프록시를 설정했습니다 이 포스트에서는 NGINX Plus에서 사용할 수 있는 추가 기능인 keepalive를 통한 성능 최적화, 상태 확인, 세션 지속성, 리디렉션 및 콘텐츠 재작성을 살펴보겠습니다.

NGINX 및 NGINX Plus 의 로드 밸런싱 기능에 대한 자세한 내용은 NGINX Plus 관리자 가이드를 확인하세요.

목차

1. 빠른 검토(A Quick Review)
2. HTTP 킵얼라이브(Keepalives)
3. 상태 점검(Health Checks)
4. 세션 지속성(Session Persistence)
5. HTTP 리디렉션(Redirect
) 재작성
6. HTTP 응답 재작성
7. A Complete Example

1. 빠른 검토(A Quick Review)

빠른 검토(A Quick Review)하기 위해 이전 포스트에서 구축한 구성은 다음과 같습니다.

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를 구성하는 몇 가지 간단한 방법을 살펴보겠습니다.

2. HTTP Keepalive

NGINX 또는 NGINX Plus와 업스트림 서버 간에 HTTP Keepalive를 활성화하면 성능이 향상되고(대기 시간 감소) NGINX에서 임시 포트가 부족해질 가능성이 줄어듭니다.

HTTP 프로토콜은 기본 TCP 연결을 사용하여 HTTP 요청을 전송하고 HTTP 응답을 수신합니다. HTTP keepalive 연결은 이러한 TCP 연결을 재사용할 수 있게 하여 각 요청에 대한 연결을 만들고 파괴하는 Overhead 방지합니다.

TCP Connection

NGINX는 전체 프록시이며 클라이언트로부터의 연결(Frontend keepalive 연결)과 서버 연결(업스트림 keepalive 연결)을 독립적으로 관리합니다.

NTINX는 업스트림 서버에 대한 유휴 Keepalive 연결 세트인 Keepalive 연결의 “Cache”를 유지하며, 요청을 업스트림에 전달해야 할 때 새로운 TCP 연결을 만드는 대신 Cache에서 이미 설정된 Keepalive 연결을 사용한다. 이는 NGINX와 업스트림 서버 간의 트랜잭션 대기 시간을 줄이고 임시 포트가 사용되는 속도를 줄여 NGINX가 대량의 트래픽을 흡수하고 로드 밸런싱을 수행할 수 있습니다. 트래픽이 급증하면 캐시를 비울 수 있으며 이 경우 NGINX는 업스트림 서버에 대한 새로운 HTTP 연결을 설정합니다.

다른 로드 밸런싱 도구의 경우 이 기술을 멀티플렉싱, 연결 풀링, 연결 재사용 또는 OneConnect라고 하는 경우가 있습니다.

구성에 proxy_http_version, proxy_set_header 및 keepalive 지시문을 포함하여 keepalive 연결 캐시를 구성합니다.

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

3. 상태 점검(Health Checks)

상태 점검(health checks)을 활성화하면 로드 밸런싱된 서비스의 안정성이 향상되고, 최종 사용자가 오류 메시지를 볼 가능성이 감소하며, 일반적인 유지 관리 작업도 용이해질 수 있습니다.

NGINX Plus의 상태 점검 기능을 사용하여 업스트림 서버의 장애를 감지할 수 있습니다.  NGINX Plus는 “합성 트랜잭션”을 사용하여 각 서버를 검사하고, health_check 지시어에서 구성한 매개 변수(일치 매개 변수를 포함하면 관련 일치 구성 블록)에 대해 응답을 확인합니다.

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

상태 검사는 상위 위치 블록에서 일부 매개변수를 상속합니다. 구성에서 런타임 변수를 사용하는 경우 문제가 발생할 수 있습니다. 예를 들어, 다음 구성은 클라이언트 요청에서 Host 헤더 값을 추출하기 때문에 실제 HTTP 트래픽에 대해 작동합니다. 호스트 헤더가 해당 트랜잭션에 대해 설정되지 않았기 때문에 상태 점검에서 사용하는 가상 트랜잭션에는 작동하지 않을 수 있습니다. 즉, 가상 트랜잭션에 호스트 헤더가 사용되지 않습니다.

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 관리자 가이드를 참조하십시오.

4. 세션 지속성(Session Persistence)

세션 지속성(session persistence)을 통해 클러스터에 배포할 수 없는 애플리케이션을 안정적으로 로드 밸런싱하고 확장할 수 있습니다. 세션 상태를 저장하고 복제하는 애플리케이션이 더 효율적으로 작동하고 최종 사용자 성능이 향상됩니다.

사용자가 가상 쇼핑 카트에 항목을 넣거나 업로드한 이미지를 편집할 때 특정 애플리케이션이 상태 정보를 업스트림 서버에 저장하는 경우가 있습니다. 이러한 경우 해당 사용자의 모든 후속 요청을 동일한 서버로 전송할 수 있습니다.

세션 지속성은 요청을 라우팅할 위치를 지정하는 반면, 로드 밸런싱은 NGINX가 최적의 업스트림 서버를 선택할 수 있는 자유를 제공합니다. 두 프로세스는 NGINX Plus의 세션 지속성 기능을 사용하여 공존할 수 있습니다.

요청이 세션 지속성 규칙과 일치하면 대상 업스트림 서버를 사용하고 그렇지 않으면 로드 밸런싱 알고리즘을 적용하여 업스트림 서버를 선택합니다.

대상 서버를 사용할 수 없기 때문에 세션 지속성 결정이 실패하면 NGINX Plus는 로드 밸런싱 결정을 내립니다.

가장 간단한 세션 지속 방법은 NGINX Plus가 sticky 업스트림 서버를 식별하는 첫 번째 응답에 쿠키를 삽입하는 “sticky cookie” 접근 방식이다.

sticky cookie srv_id expires=1h domain=.example.com path=/;

대체 “sticky route” 방법에서 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 관리자 가이드를 참조하십시오.

5. HTTP 리디렉션(Redirect) 재작성

일부 리디렉션이 손상된 경우, 특히 프록시에서 실제 업스트림 서버로 리디렉션되는 경우 HTTP 리디렉션을 다시 작성합니다.

업스트림 서버에 프록시할 때 서버는 로컬 주소에 애플리케이션을 게시하지만 사용자는 다른 주소(프록시의 주소)를 통해 애플리케이션에 액세스합니다. 이러한 주소는 일반적으로 도메인 이름으로 resolve되며, 서버와 프록시의 도메인이 다를 경우 문제가 발생할 수 있습니다.

예를 들어, 테스트 환경에서는 프록시를 IP 주소로 직접 주소 지정하거나 localhost로 주소 지정할 수 있습니다. 그러나 업스트림 서버는 실제 도메인 이름(예: nginxstore.com)을 수신할 수 있습니다. 업스트림 서버가 리디렉션 메시지(3xx 상태 및 위치 헤더 사용 또는 새로 고침 헤더 사용)를 발행할 때, 메시지는 서버의 실제 도메인을 포함할 수 있습니다.

NGINX는 이 문제의 가장 일반적인 인스턴스를 가로채고 수정하려고 합니다. 특정 재작성을 강제하기 위해 전체 제어가 필요한 경우 다음과 같이 proxy_redirect 명령을 사용하십시오.

proxy_redirect http://staging.mysite.com/ http://$host/;

6. HTTP 응답 재작성

HTTP 응답의 내용을 다시 작성해야 하는 경우가 있습니다. 위의 예시와 같이 응답에 프록시가 아닌 다른 서버를 참조하는 절대 링크가 포함되어 있을 수 있습니다.

sub_filter 지시어를 사용하여 적용할 재작성을 정의할 수 있습니다

sub_filter /blog/ /blog-staging/;
sub_filter_once off;

가장 일반적인 문제 중 하나는 HTTP 압축을 사용할 때 입니다. 클라이언트가 압축된 데이터를 수락할 수 있다는 신호를 보내고 서버가 응답을 압축하면 NGINX는 응답을 검사하고 수정할 수 없습니다. 가장 간단한 해결 방법은 클라이언트 요청에서 Accept-Encoding 헤더를 빈 문자열(“”)로 설정하여 제거하는 것입니다.

proxy_set_header Accept-Encoding "";

7. A Complete Example

다음은 이 포스트에서 설명하는 모든 기술을 사용하는 로드 밸런싱 구성용 템플릿입니다. 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
    }
}