NGINX 및 NGINX Plus를 활용한 애플리케이션 추적

NGINX | 2016년 9월 27일

사진: WordPress.org

애플리케이션 성능 관리를 위한 변수 사용

변수는 NGINX 구성에서 중요하지만 때로는 간과되는 요소입니다. 약 150개의 변수를 사용할 수 있어 구성의 모든 부분을 개선할 수 있습니다. 이 블로그 게시물에서는 애플리케이션의 성능 병목 현상을 파악하는 데 중점을 두고, 애플리케이션 추적 및 애플리케이션 성능 관리(APM)에 NGINX 변수를 사용하는 방법을 설명합니다. 이 게시물은 NGINX Open Source와 NGINX Plus 모두에 적용됩니다. 간결한 설명을 위해 두 버전 간에 차이가 있는 경우를 제외하고는 본문 전체에서 NGINX Plus로 지칭하겠습니다.

애플리케이션 제공 환경

샘플 애플리케이션 제공 환경에서 NGINX Plus는 애플리케이션의 리버스 프록시로 작동합니다. 애플리케이션 자체는 웹 프런트엔드와 그 뒤에 위치한 여러 마이크로서비스로 구성됩니다.

일반적인 배포 시나리오에서 NGINX 또는 NGINX Plus는 클라이언트의 요청을 웹 프런트엔드와 이를 지원하는 마이크로서비스로 구성된 애플리케이션 또는 애플리케이션 서버로 프록시합니다.
샘플 애플리케이션 제공 환경

요청을 엔드투엔드로 추적하기

NGINX Plus R10(및 NGINX 1.11.0)에는 $request_id 변수가 도입되었습니다. 이 변수는 각 HTTP 요청이 도착할 때 자동으로 할당되는, 무작위로 생성된 32자리 16진수 문자열입니다(예: 444535f9378a3dfa1b8604bc9e05a303). 단순해 보이는 이 메커니즘은 추적 및 문제 해결을 위한 강력한 도구로 활용할 수 있습니다. NGINX Plus와 모든 백엔드 서비스가 $request_id 값을 전달하도록 구성하면 모든 요청을 처음부터 끝까지 추적할 수 있습니다. 다음은 프런트엔드 NGINX Plus 서버의 구성 예시입니다.

upstream app_server {    server 10.0.0.1:80;
}

server {
    listen 80;
    add_header X-Request-ID $request_id; # Return to client
    location / {
        proxy_pass http://app_server;
        proxy_set_header X-Request-ID $request_id; # Pass to app server
    }
}

요청 추적을 위해 NGINX Plus를 구성하려면 먼저 upstream 블록에서 애플리케이션 서버의 네트워크 위치를 정의합니다. 여기서는 간단히 하나의 애플리케이션 server만 표시하지만, 일반적으로 고가용성과 부하 분산을 위해 여러 서버를 사용합니다.

애플리케이션 server 블록은 NGINX Plus가 수신 HTTP 요청을 처리하는 방식을 정의합니다. listen 지시문은 NGINX Plus가 HTTP 트래픽의 기본 포트인 80번 포트에서 수신 대기하도록 지정하지만, 프로덕션 구성에서는 일반적으로 전송 중인 데이터를 보호하기 위해 SSL/TLS를 사용합니다.

The add_header 지시어는 응답의 사용자 지정 헤더를 통해 $request_id 값을 클라이언트에 다시 전송합니다. 이는 테스트뿐만 아니라 모바일 앱처럼 자체 로그를 생성하는 클라이언트 애플리케이션에도 유용하며, 클라이언트 측 오류를 서버 로그와 정확하게 대조할 수 있게 해 줍니다.

마지막으로 location 블록은 전체 애플리케이션 공간(/)에 적용되며, proxy_pass 지시어는 모든 요청을 애플리케이션 서버로 프록시합니다. proxy_set_header 지시어는 애플리케이션에 전달되는 HTTP 헤더를 추가하여 프록시된 요청을 수정합니다. 이 경우 X-Request-ID라는 새 헤더를 만들고 여기에 $request_id 변수의 값을 할당합니다. 따라서 애플리케이션은 NGINX Plus에서 생성된 요청 ID를 수신합니다.

로깅 $request_id 엔드 투 엔드

애플리케이션 추적의 목표는 애플리케이션 성능 관리의 일환으로 요청 처리 수명 주기에서 성능 병목 지점을 식별하는 것입니다. 이를 위해 처리 중 발생하는 주요 이벤트를 기록하여 나중에 예기치 않거나 비정상적인 지연이 있는지 분석할 수 있도록 합니다.

NGINX Plus 구성

먼저 프런트엔드 NGINX Plus 서버가 사용자 지정 로깅 형식인 $request_id에 trace를 포함하도록 구성합니다. 이 형식은 access_trace.log 파일에 사용됩니다.

log_format trace '$remote_addr - $remote_user [$time_local] "$request" '                 '$status $body_bytes_sent "$http_referer" "$http_user_agent" '
                 '"$http_x_forwarded_for" $request_id';

upstream app_server {
    server 10.0.0.1;
}

server {
    listen 80;
    add_header X-Request-ID $request_id; # Return to client
    location / {
        proxy_pass http://app_server;
        proxy_set_header X-Request-ID $request_id;        # Pass to app server
        access_log /var/log/nginx/access_trace.log trace; # Log $request_id
    }
}

백엔드 애플리케이션 구성

요청 ID를 애플리케이션에 전달하는 것도 좋지만, 애플리케이션에서 이를 활용하지 않으면 실제로 애플리케이션 추적에 도움이 되지 않습니다. 이 예제에서는 uWSGI로 관리되는 Python 애플리케이션을 사용합니다. 요청 ID를 로깅 변수로 가져오도록 애플리케이션 진입점을 수정해 보겠습니다.

from uwsgi import set_logvar
def main(environ, start_response):
    set_logvar('requestid', environ['X_REQUEST_ID'])

그런 다음 표준 로그 파일에 요청 ID가 포함되도록 uWSGI 구성을 수정할 수 있습니다.

log-format = %(addr) - %(user) [%(ltime)] "%(method) %(uri) %(proto)" %(status) %(size) "%(referer)" "%(uagent)" %(requestid)

이 구성을 적용하면 이제 여러 시스템에 걸친 단일 요청을 서로 연계할 수 있는 로그 파일이 생성됩니다.

NGINX 로그 항목:

172.17.0.1 - - [02/Aug/2016:14:26:50 +0000] "GET / HTTP/1.1" 200 90 "-" "-" "-" 5f222ae5938482c32a822dbf15e19f0f

애플리케이션의 로그 항목:

192.168.91.1 - - [02/Aug/2016:14:26:50 +0000] "GET / HTTP/1.0" 200 123 "-" "-" 5f222ae5938482c32a822dbf15e19f0f

요청 ID 필드를 기준으로 트랜잭션을 대조하면 Splunk 및 Kibana 같은 도구를 사용하여 애플리케이션 서버의 성능 병목 현상을 파악할 수 있습니다. 예를 들어 완료하는 데 2초 이상 걸린 요청을 검색할 수 있습니다. 하지만 일반 타임스탬프의 기본 시간 해상도인 1초는 대부분의 실제 분석에 충분하지 않습니다.

고정밀 타이밍

요청의 전체 처리 시간을 정확하게 측정하려면 밀리초 수준의 정밀도를 갖춘 타임스탬프가 필요합니다. 로그 항목에 $msec 변수를 포함하면 각 항목의 타임스탬프를 밀리초 단위로 확인할 수 있습니다. 애플리케이션 로그에 밀리초 단위의 타임스탬프를 추가하면 완료하는 데 2초가 아닌 200밀리초 이상 걸린 요청을 찾을 수 있습니다.

하지만 그렇다 해도 전체 상황을 파악할 수 있는 것은 아닙니다. NGINX Plus는 각 요청의 처리가 끝날 때만 $msec 타임스탬프를 기록하기 때문입니다. 다행히도 NGINX Plus에는 밀리초 단위의 정밀도를 제공하여 처리 과정 자체를 더 자세히 파악할 수 있게 해 주는 몇 가지 다른 시간 측정 변수가 있습니다:

  • $request_time – NGINX Plus가 클라이언트에서 첫 번째 바이트를 읽기 시작한 시점부터 응답 본문의 마지막 바이트를 전송한 시점까지의 전체 요청 시간
  • $upstream_connect_time – 업스트림 서버와의 연결을 설정하는 데 걸린 시간
  • $upstream_header_time – 업스트림 서버와의 연결을 설정한 시점부터 응답 헤더의 첫 번째 바이트를 수신할 때까지 걸린 시간
  • $upstream_response_time – 업스트림 서버에 연결한 시점부터 응답 본문의 마지막 바이트를 수신할 때까지 걸린 시간

이러한 시간 측정 변수에 대한 자세한 내용은 애플리케이션 성능 모니터링을 위한 NGINX 로깅 사용을 참조하세요.

이제 log_format 지시문을 확장하여 이러한 고정밀 타이밍 변수를 모두 trace 로그 형식에 포함해 보겠습니다.

log_format trace '$remote_addr - $remote_user [$time_local] "$request" $status '                 '$body_bytes_sent "$http_referer" "$http_user_agent" '
                 '"$http_x_forwarded_for" $request_id $msec $request_time '
                 '$upstream_connect_time $upstream_header_time $upstream_response_time';

선호하는 로그 분석 도구를 사용하면 변수 값을 추출하고 다음 계산을 수행하여 NGINX Plus가 애플리케이션 서버에 연결하기 전에 요청을 처리하는 데 걸린 시간을 확인할 수 있습니다:

NGINX Plus processing time = $request_time - $upstream_connect_time - $upstream_response_time

또한 $upstream_response_time의 최댓값을 검색하여 특정 URI 또는 업스트림 서버와 관련이 있는지 확인할 수 있습니다. 그런 다음 동일한 요청 ID가 있는 애플리케이션 로그 항목과 대조하여 추가로 확인할 수 있습니다.

결론

새로운 $request_id 변수와 밀리초 단위 정밀도를 제공하는 변수 중 일부 또는 전부를 활용하면 애플리케이션의 성능 병목 현상을 심층적으로 파악할 수 있어, 무거운 에이전트나 플러그인에 의존하지 않고도 애플리케이션 성능 관리를 개선할 수 있습니다.

NGINX Plus로 애플리케이션 추적을 직접 사용해 보세요. 지금 30일 무료 체험을 시작하거나 사용 사례에 대해 논의하려면 문의해 주세요.


공유

작성자 소개

관련 블로그 게시물

시청하기: KubeCon North America 2023에서의 NGINX Gateway Fabric
NGINX | 2023. 11. 30.

시청하기: KubeCon North America 2023에서의 NGINX Gateway Fabric

이 영상에서는 KubeCon의 NGINX 부스를 찾아가, 저희가 공개한 Kubernetes Gateway API 구현을 살펴봅니다.

F5 NGINX로 대규모 WAF 플릿을 확인하고 관리하는 2가지 방법
NGINX | 2023. 03. 23.

F5 NGINX로 대규모 WAF 플릿을 확인하고 관리하는 2가지 방법

앱 보안을 강화하는 두 가지 방법을 소개합니다. NGINX Management Suite를 통해 WAF 운영에 대한 가시성을 높이고, NGINX App Protect WAF를 활용해 코드형 보안을 구현하는 것입니다.

Ingress 컨트롤러 선택 가이드, 4부: NGINX Ingress Controller 옵션
NGINX | 2021. 09. 27.

Ingress 컨트롤러 선택 가이드, 4부: NGINX Ingress Controller 옵션

개발 주체, 개발 철학, 프로덕션 환경 준비도, 보안 및 지원을 기준으로 어떤 NGINX Ingress 컨트롤러가 가장 적합한지 알아보세요.

진화하는 공격 환경에 NGINX App Protect Denial of Service가 적응하는 방법
NGINX | 2021. 07. 06.

진화하는 공격 환경에 NGINX App Protect Denial of Service가 적응하는 방법

NGINX App Protect Denial of Service(DoS)가 계층 7 DoS 공격을 방어하기 위해 완화 방법을 실시간으로 조정하는 방식을 설명합니다. 정상적인 사용자 행동과 서버 상태에 대한 모델을 생성하여 공격을 나타내는 이상 징후를 감지하고 맞춤형 완화 시그니처를 적용할 수 있습니다.

NGINX Instance Manager를 활용한 대규모 구성 업데이트 및 인증서 관리
NGINX | 2021. 06. 30.

NGINX Instance Manager를 활용한 대규모 구성 업데이트 및 인증서 관리

NGINX Instance Manager 버전 1.0에는 두 가지 새로운 기능이 도입되었습니다. NGINX 인스턴스에 태그와 사용자 역할을 지정하면 전체 그룹에 구성을 한 번에 적용할 수 있습니다. 인증서 검사는 만료 예정인 인증서를 감지하여 서비스 중단을 방지할 수 있도록 인증서를 교체할 수 있게 해줍니다.

Netflix가 자사 CDN의 핵심으로 NGINX를 선택한 이유
NGINX | 2015. 03. 25.

Netflix가 자사 CDN의 핵심으로 NGINX를 선택한 이유

Netflix가 글로벌 콘텐츠 전송 네트워크인 Open Connect의 스트리밍 미디어 기술로 NGINX를 선택한 이유를 NGINX 개발자 Gleb Smirnoff에게서 알아보세요.