본문으로 건너뛰기
Advertisement

연결 최적화 — keepalive·버퍼·타임아웃 튜닝

Nginx와 Tomcat 사이의 연결 효율을 높이는 핵심 설정을 다룹니다. keepalive 연결 재사용, 버퍼 크기 조정, 타임아웃 3종(connect·send·read) 튜닝을 실무 기준으로 설명합니다.


연결 흐름 이해

최적화를 위해 먼저 Nginx → Tomcat 연결의 전체 흐름을 파악합니다.

클라이언트 ←→ Nginx ←→ Tomcat

[연결 수립]
1. 클라이언트 → Nginx: TCP 연결 + TLS 핸드셰이크
2. Nginx → Tomcat: TCP 연결 (proxy_connect_timeout 이내)

[요청 전달]
3. Nginx → Tomcat: 요청 헤더 + 바디 전송 (proxy_send_timeout 이내)

[응답 수신]
4. Tomcat → Nginx: 응답 헤더 + 바디 수신 (proxy_read_timeout 이내)
5. Nginx → 클라이언트: 응답 전달

keepalive — 연결 재사용

TCP 연결을 매 요청마다 새로 수립하면 Tomcat에 부하가 걸립니다. keepalive로 연결을 재사용하면 레이턴시와 CPU 사용량이 크게 줄어듭니다.

Nginx upstream keepalive 설정

upstream tomcat_backend {
server 127.0.0.1:8080;

# keepalive: Nginx가 Tomcat과 유지할 유휴 연결 수
# (동시 요청 수의 약 50% 권장)
keepalive 64;

# keepalive 연결 최대 요청 수 (이후 연결 갱신)
keepalive_requests 1000;

# keepalive 연결 유지 시간
keepalive_time 1h;
keepalive_timeout 75s;
}

server {
location / {
proxy_pass http://tomcat_backend;

# keepalive 사용 시 반드시 HTTP/1.1 + Connection "" 설정
proxy_http_version 1.1;
proxy_set_header Connection ""; # "keep-alive" 아닌 "" (빈 문자열)
}
}

중요: proxy_http_version 1.1proxy_set_header Connection ""을 함께 설정해야 keepalive가 동작합니다. Connection: keep-alive 헤더를 Tomcat에 전달하면 오히려 문제가 생길 수 있습니다.

Tomcat HTTP 커넥터 keepalive 설정

Nginx와 Tomcat 양쪽에서 keepalive를 지원해야 합니다.

<!-- server.xml -->
<Connector port="8080" protocol="HTTP/1.1"
keepAliveTimeout="75000" <!-- Nginx keepalive_timeout과 맞춤 -->
maxKeepAliveRequests="1000" <!-- Nginx keepalive_requests와 맞춤 -->
connectionTimeout="20000"
maxThreads="200"/>

타임아웃 3종 완전 이해

location / {
proxy_pass http://tomcat_backend;

# 1. connect_timeout: Nginx → Tomcat TCP 연결 수립 대기 시간
# Tomcat이 응답 없으면 502 반환
proxy_connect_timeout 10s;

# 2. send_timeout: Nginx → Tomcat 요청 전송 중 두 패킷 사이 최대 대기 시간
# 클라이언트가 느린 업로드를 할 때 영향
proxy_send_timeout 60s;

# 3. read_timeout: Tomcat → Nginx 응답 수신 중 두 패킷 사이 최대 대기 시간
# Tomcat 처리 시간보다 길게 설정해야 함
proxy_read_timeout 60s;
}

타임아웃 설정 가이드

상황connectsendread
일반 API5~10s30s30~60s
파일 업로드5~10s300s60s
파일 다운로드5~10s60s300s
장시간 처리 (배치)5~10s60s600s+
WebSocket5~10s3600s3600s

경로별 타임아웃 분리

# 일반 API
location /api/ {
proxy_pass http://tomcat_backend;
proxy_connect_timeout 5s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
}

# 파일 업로드
location /api/upload {
proxy_pass http://tomcat_backend;
proxy_connect_timeout 5s;
proxy_send_timeout 300s;
proxy_read_timeout 60s;
proxy_request_buffering off; # 청크 업로드 지원
client_max_body_size 500m;
}

# 배치 작업 (시간이 오래 걸리는 API)
location /api/batch/ {
proxy_pass http://tomcat_backend;
proxy_connect_timeout 5s;
proxy_send_timeout 60s;
proxy_read_timeout 600s;
}

버퍼 설정

버퍼는 Tomcat의 응답을 Nginx가 임시 저장하는 공간입니다. 올바른 버퍼 설정으로 클라이언트 속도와 무관하게 Tomcat 스레드를 빠르게 해제할 수 있습니다.

location / {
proxy_pass http://tomcat_backend;

# 버퍼링 활성화 (기본값 on)
proxy_buffering on;

# 응답 헤더용 버퍼 크기 (헤더가 크면 늘릴 것)
proxy_buffer_size 16k;

# 응답 본문용 버퍼 (개수 × 크기)
proxy_buffers 8 64k; # 512KB

# 클라이언트에 전달 중인 버퍼 최대 크기
proxy_busy_buffers_size 128k;

# 임시 파일 사용 (버퍼가 꽉 찬 경우)
proxy_temp_path /var/cache/nginx/proxy_temp;
proxy_max_temp_file_size 1024m;
proxy_temp_file_write_size 64k;
}

버퍼 크기 산정 기준

응답 크기권장 설정
소형 API (< 4KB)buffer_size 4k, buffers 4 4k
일반 웹 페이지 (< 64KB)buffer_size 16k, buffers 4 64k (기본값)
대용량 JSON (< 1MB)buffer_size 32k, buffers 8 128k
파일 다운로드proxy_buffering off (스트리밍)

캐시 설정 (선택적 프록시 캐시)

자주 변경되지 않는 API 응답을 Nginx에서 캐시하면 Tomcat 부하를 줄일 수 있습니다.

# nginx.conf http 블록
proxy_cache_path /var/cache/nginx/proxy_cache
levels=1:2
keys_zone=tomcat_cache:10m
max_size=1g
inactive=60m
use_temp_path=off;

# location 블록
location /api/products {
proxy_pass http://tomcat_backend;

proxy_cache tomcat_cache;
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_valid 200 5m; # 200 응답 5분 캐시
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout updating;
proxy_cache_lock on;

# 캐시 상태 헤더 추가 (디버깅용)
add_header X-Cache-Status $upstream_cache_status;

# 특정 쿠키/헤더가 있으면 캐시 우회
proxy_cache_bypass $http_authorization;
proxy_no_cache $http_authorization;
}

종합 최적화 설정 예시

upstream tomcat_backend {
server 127.0.0.1:8080;
keepalive 64;
keepalive_requests 1000;
keepalive_timeout 75s;
}

server {
listen 443 ssl http2;
server_name example.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

# 클라이언트 설정
client_max_body_size 50m;
client_body_buffer_size 128k;
client_header_buffer_size 4k;
large_client_header_buffers 4 16k;

# 기본 API 프록시
location /api/ {
proxy_pass http://tomcat_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
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;

proxy_connect_timeout 10s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;

proxy_buffering on;
proxy_buffer_size 16k;
proxy_buffers 4 64k;
proxy_busy_buffers_size 128k;
}

# 대용량 업로드
location /api/upload {
proxy_pass http://tomcat_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
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;

client_max_body_size 500m;
proxy_request_buffering off;
proxy_connect_timeout 5s;
proxy_send_timeout 300s;
proxy_read_timeout 60s;
}

# 정적 파일
location ~* \.(css|js|png|jpg|webp|woff2)$ {
root /var/www/myapp;
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
}

성능 측정 및 검증

# ab 로드 테스트
ab -n 10000 -c 200 https://example.com/api/users

# 연결 현황 확인 (ESTABLISHED, TIME_WAIT 등)
ss -s
ss -tnp | grep nginx | wc -l

# Nginx 업스트림 상태 확인 (nginx-module-vts 또는 status 페이지 필요)
curl http://localhost/nginx_status

# Tomcat 활성 스레드 확인
curl -u admin:password http://localhost:8080/manager/status

Summary

최적화 항목설정효과
keepalivekeepalive 64 + HTTP/1.1TCP 재연결 오버헤드 제거
connect timeoutproxy_connect_timeout 10s장애 Tomcat 빠른 감지
read timeoutproxy_read_timeout 30~60sTomcat 처리 시간에 맞게
버퍼링proxy_buffers 4 64kTomcat 스레드 빠른 해제
캐시proxy_cache_path반복 요청 Tomcat 부하 감소
HTTP/2listen 443 ssl http2클라이언트 다중화 이점
Advertisement