웹 서버·WAS 용어 사전
WASproxy_read_timeout · proxy_connect_timeout · connectionTimeout

타임아웃 계층

계층마다 타임아웃이 있고 어긋나면 사고가 난다. 안쪽으로 갈수록 짧아야 한다.

요청 경로의 계층마다 타임아웃이 있고, 값이 어긋나면 사고가 난다.

  • 클라이언트 타임아웃 — 3초
  • CDN / LB 유휴 타임아웃 — 60초
  • nginx proxy_read_timeout 60초
  • WAS connectionTimeout — 20초
  • DB 쿼리 타임아웃 — 없음 ← 여기가 구멍

어긋나면 무슨 일이 생기나

바깥이 안쪽보다 짧으면

  • 클라이언트는 이미 끊었는데 서버는 계속 처리한다
  • 자원 낭비. nginx 로그에 499 가 쌓인다

바깥이 안쪽보다 훨씬 길면

  • 죽은 요청을 오래 붙들고 있다
  • 스레드·커넥션 고갈로 이어진다

원칙 — 안쪽으로 갈수록 타임아웃이 짧아지게 잡는다

  • 그리고 '없는' 타임아웃이 가장 위험하다

nginx 쪽 지시자

location /api/ {
    proxy_pass http://backend;
    proxy_connect_timeout 3s;     # 업스트림에 연결하는 데까지
    proxy_send_timeout   10s;     # 요청을 보내는 중 무응답 허용 시간
    proxy_read_timeout   30s;     # 응답을 읽는 중 무응답 허용 시간
    proxy_next_upstream error timeout http_502 http_503;
}

proxy_connect_timeout 은 짧게 (수 초)

  • 연결조차 안 되는 서버를 오래 기다릴 이유가 없다

proxy_read_timeout 은 '무응답' 기준이지 전체 시간이 아니다

  • 데이터가 계속 오면 갱신된다 → 스트리밍은 이 값에 안 걸린다

재시도를 함부로 켜지 않는다

proxy_next_upstream 에 non_idempotent 를 넣지 않는 한 POST 같은 비멱등 요청은 재시도하지 않는다

재시도가 중복 처리를 만들 수 있기 때문이다

  • 결제가 두 번 되는 사고가 여기서 나온다

이 기본값을 함부로 바꾸지 않는다 재시도가 필요하면 애플리케이션이 멱등 키로 보호한 뒤에 켠다

유휴 타임아웃도 계층마다 있다

  • keepalive_timeout — nginx ↔ 클라이언트

  • keepalive (upstream) — nginx ↔ 업스트림

  • keepAliveTimeout — WAS

  • LB 유휴 타임아웃 — 클라우드 LB (AWS ALB 기본 60초)

  • 앞단의 유휴 타임아웃이 뒤보다 길면

    • 뒤가 먼저 끊은 연결을 앞단이 재사용하려다 502 가 난다
  • 앞단 값을 뒤보다 '짧게' 잡는 것이 안전하다

점검 방법

계층별 타임아웃을 한 표에 적어 두는 것만으로 절반이 해결된다

확인

  • curl -w 'conn=%{time_connect} ttfb=%{time_starttransfer} total=%{time_total}\n' \
  • 어느 구간에서 시간이 가는지 분해해 보여 준다

표로 적어 두는 것이 절반이다

계층                     연결      읽기      유휴
──────────────────────────────────────────────
클라이언트(앱)            3s        10s       -
CDN                       -         30s       -
클라우드 LB               -         -         60s
nginx                     3s        30s       65s
WAS                       -         20s       20s
DB 쿼리                   1s        5s        -

이 표가 없으면 어긋난 것을 발견할 방법이 없다
장애 회고에서 가장 자주 나오는 산출물이기도 하다

타임아웃이 없는 곳을 찾는다

가장 위험한 것은 '설정하지 않은' 타임아웃이다

흔히 빠지는 곳

  • DB 쿼리 타임아웃 (드라이버 기본이 무한인 경우가 있다)

  • 외부 API 호출 (HTTP 클라이언트 기본값 확인)

  • 커넥션 풀 획득 대기

  • 분산 락 획득 대기

  • 하나라도 무한이면 그 지점에서 스레드가 영원히 묶인다

  • 코드 리뷰 체크리스트에 "이 호출의 타임아웃은?" 을 넣는다

면접 함정

  • "타임아웃은 길게 잡는 게 안전하다" → 죽은 요청이 자원을 붙든다.
  • "타임아웃이 걸리면 재시도하면 된다" → 비멱등 요청은 중복 처리가 된다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — WAS 커넥터 튜닝 — 스레드는 몇 개가 맞나