웹 서버·WAS 용어 사전
WASmaxThreads · maxConnections · acceptCount · 커넥터

커넥터 튜닝

acceptCount·maxConnections·maxThreads는 서로 다른 층의 한도다. 연결 수용과 처리가 분리돼 있다.

요청이 WAS 안에서 겪는 세 개의 서로 다른 한도.

  • OS 가 SYN 을 받아 accept 큐에 넣는다 — ← acceptCount
  • WAS 가 accept 해서 연결로 인정한다 — ← maxConnections
  • 처리할 스레드를 할당한다 — ← maxThreads

Tomcat 11.0.24 기본값

  • maxThreads — 200
  • maxConnections — 8192
  • acceptCount — 100
  • connectionTimeout — 60000
  • keepAliveTimeout — connectionTimeout 값을 따름
  • maxKeepAliveRequests — 100

함정connectionTimeout문서 기본값은 60000 이지만 배포되는 server.xml 은 20000 으로 설정한다. 값을 논할 때는 항상 "무엇 기준인지" 를 밝힌다.

maxConnections 가 maxThreads 보다 훨씬 큰 이유

  • 연결을 8천 개 유지하면서 실제 처리는 200개만 동시에 한다
  • keep-alive 로 붙어만 있는 연결이 스레드를 잡지 않는다
  • NIO 커넥터라서 가능하다 (연결과 스레드가 1:1 이 아니다)

예전 BIO 커넥터는 연결 = 스레드였다 그때는 maxConnections 를 따로 둘 이유가 없었다

스레드는 몇 개가 맞나

하한 — 리틀의 법칙 필요한 동시 처리 수 = 처리량(TPS) × 평균 응답시간(초) 1,000 TPS · 평균 50ms → 1000 × 0.05 = 50 여유를 감안해 2~3배로 시작한다 → 100~150

상한 — 뒤에 있는 가장 좁은 자원 스레드 200개 · DB 커넥션 20개라면 180개는 커넥션을 기다린다 스레드를 400개로 늘려도 DB 앞의 줄만 길어진다

  • 앞을 넓히면 병목이 사라지는 게 아니라 줄이 옮겨갈 뿐이다

메모리도 함께 본다

스레드 하나 = 네이티브 스택 (리눅스 기본 1MB 예약)

maxThreads 2000 → 스택만으로 최대 2GB 규모의 주소 공간 컨테이너 limit 을 넘기면 커널이 프로세스를 죽인다 (OOMKilled — 애플리케이션 로그에 아무것도 안 남는다)

큐가 어디에 생기는지가 설계다

  • maxConnections 도달 — → OS accept 큐(acceptCount)에서 대기

  • acceptCount 도 참 — → OS 가 연결을 거부한다

  • 빠른 실패를 원한다 — acceptCount 를 작게

    • 거부가 빨리 나고 앞단이 다른 서버로 보낸다
  • 버티기를 원한다 — 크게 — 대기는 늘지만 끊기지는 않는다

  • 큐를 크게 잡는 것은 대체로 나쁜 선택이다

    • 오래 기다린 요청은 클라이언트가 이미 포기했을 가능성이 높다
    • 처리해 봐야 버려진다 (일은 하고 값은 못 받는다)

keep-alive 설정이 연결 수를 좌우한다

  • maxKeepAliveRequests — 한 연결에서 처리할 최대 요청 수 (기본 100)

    • 초과하면 연결을 닫는다
  • keepAliveTimeout — 다음 요청을 기다리는 시간

  • 값이 작으면 — 연결을 자주 새로 만든다 (핸드셰이크 비용)

  • 값이 크면 — 유휴 연결이 maxConnections 를 잠식한다

앞단 nginx 가 커넥션 풀을 유지한다면 백엔드의 keep-alive 는 넉넉해도 된다 — 연결 수가 예측 가능하기 때문이다 반대로 클라이언트가 직접 붙는 구조라면 보수적으로 잡는다

관측 없이 튜닝하지 않는다

봐야 할 지표
  활성 / 전체 스레드 수     상시 포화면 상한이 낮거나 뒤가 느리다
  큐 대기 수                 0 보다 크게 지속되면 병목 신호
  현재 연결 수 / maxConnections
  accept 큐                  ss -lnt 의 Recv-Q(대기) · Send-Q(백로그 한도)

숫자를 바꾸기 전에 '어디가 포화인지' 를 먼저 확인한다 포화가 아닌 값을 올리면 아무 일도 일어나지 않는다

면접 함정

  • "스레드를 늘리면 처리량이 는다" → 뒤가 좁으면 대기만 늘어난다.
  • "maxConnections와 maxThreads는 같은 말" → 수용과 처리는 다른 층이다.

함께 보면 좋은 용어

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