이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.
Tomcat Connector와 OS Socket 연결에서 붙잡아야 할 핵심 판단 기준은 무엇인가?connector는 socket과 Java thread 사이의 경계다라는 기준은 어떤 JVM/OS 신호로 확인되는가?- Java/Spring 코드에서
Tomcat Connector와 OS Socket 연결판단 기준은 어떤 장애 신호로 드러나는가?
개요
이 문서의 주제는 Tomcat Connector와 OS Socket 연결이다. Tomcat connector의 thread, accept count, timeout이 OS socket과 연결되는 방식을 다룬다.
먼저 붙잡을 기준은 다음 문장이다. connector는 socket과 Java thread 사이의 경계다. OS가 연결을 받아도 Tomcat worker thread가 없으면 요청은 application 처리로 넘어가지 못한다. 따라서 connector 장애는 ss의 socket 상태와 Actuator의 Tomcat thread/connection metric을 같은 시간축으로 놓고 판단해야 한다.
핵심 모델
- 판단 기준: connector는 socket과 Java thread 사이의 경계다.
- Tomcat connector는 OS listen socket에서 accepted connection을 받아 Java worker thread로 넘긴다.
maxThreads는 동시에 request를 처리할 수 있는 worker thread 상한이다.acceptCount는 worker가 모두 바쁠 때 추가 connection을 얼마나 대기시킬지와 연결된다.connectionTimeout과 keep-alive 설정은 느린 client가 connector 자원을 얼마나 오래 잡을지 결정한다.- Connector 지표는 CPU, downstream latency, thread dump와 함께 봐야 실제 병목 위치가 드러난다.
문서별 핵심 구분
- Tomcat connector는 OS socket과 Java worker thread 사이의 경계다.
- maxThreads, acceptCount, connectionTimeout은 함께 봐야 한다.
- thread가 바쁘면 accept 이후 요청 처리도 밀린다.
원리
Tomcat은 OS socket을 직접 대신하는 것이 아니라 OS가 accept 가능한 연결을 Java request 처리 흐름으로 넘기는 connector 계층이다. 이 경계에서 연결 수, worker thread 수, timeout 정책이 맞물린다.
maxThreads가 꽉 차면 OS가 받은 연결이 있어도 request 처리가 밀린다. 이때 busy thread가 100%에 가깝고 thread dump가 DB call, 외부 HTTP call, lock wait에 몰려 있으면 socket 자체보다 application 처리 지연이 원인이다.
반대로 busy thread는 낮은데 connection timeout이나 accept queue 문제가 보이면 client/LB, TLS, backlog, connection 설정을 먼저 봐야 한다. 같은 “응답 지연”이라도 connector 앞과 뒤의 조치가 다르다.
Connector 설정은 단독 숫자가 아니라 timeout 예산이다. Client timeout, LB timeout, Tomcat connection timeout, downstream timeout이 서로 충돌하면 정상 부하에서도 재시도 폭증과 connection churn이 생긴다.
Java/Spring 연결
- Spring Boot의 embedded Tomcat은 connector worker thread를 통해 Controller 호출을 실행한다.
server.tomcat.threads.max,server.tomcat.accept-count,server.connection-timeout은 Controller 처리 전후의 대기와 실패 방식을 바꾼다.- Actuator
tomcat.threads.busy,tomcat.threads.current,tomcat.connections.current는 connector 상태를 Java metric으로 보여 준다. - Busy thread가 높을 때 thread dump의
http-nio-*worker stack을 보면 DB, 외부 HTTP, lock 중 어디서 막혔는지 알 수 있다. - Connector 값을 키우면 application 동시성도 늘어나므로 DB pool, HTTP client pool, CPU quota를 함께 검토해야 한다.
- Spring 코드 리뷰에서는
Tomcat Connector와 OS Socket 연결판단 기준이 어떤 thread, pool, timeout, resource 설정으로 드러나는지 확인한다.
코드와 설정 예시
server.tomcat.threads.max=200
server.tomcat.accept-count=100
server.connection-timeout=5s이 설정은 “200개 thread면 충분한가”가 아니라 “200개 thread가 어떤 작업에서 얼마나 오래 묶이는가”로 읽어야 한다. accept-count는 짧은 피크를 흡수할 수 있지만, downstream이 느려 worker가 계속 묶이는 상황에서는 대기열만 길어진다.
관찰 명령
curl -s localhost:8080/actuator/metrics/tomcat.threads.busy
curl -s localhost:8080/actuator/metrics/tomcat.connections.current
ss -ltnp | grep javaTomcat Connector와 OS Socket 연결 관찰 명령은 결론이 아니라 가설 확인 도구다. 운영 중에는 반복 간격, 대상 PID, 수집 시각을 함께 남기고 출력이 큰 명령은 범위를 제한한다.
지표 해석
| 신호 | 먼저 의심할 것 | 다음 확인 |
|---|---|---|
tomcat.threads.busy 상한 근접 | worker thread 포화 | thread dump, slow endpoint |
| current connection 증가와 busy 낮음 | keep-alive, 느린 client, LB 문제 | ss, LB access log |
| accept/drop counter 증가 | connector가 제때 받지 못함 | backlog, busy thread, CPU |
| timeout/retry 동시 증가 | timeout 예산 불일치 | client/LB/Tomcat/downstream timeout |
Tomcat Connector와 OS Socket 연결에서는 핵심 신호와 보조 지표를 같은 시간축에서 맞춘다. 먼저 변한 신호와 뒤따라 포화된 신호를 분리해야 원인과 결과를 구분할 수 있다.
장애 상황에서 보는 순서
- Actuator에서 Tomcat busy thread와 current connection을 같은 시각에 확인한다.
ss -ltnp와ss -tanp로 OS listen socket과 연결 state를 본다.- Busy thread가 높으면 thread dump로 worker가 어디에서 막혔는지 확인한다.
- Busy thread가 낮고 connection만 많으면 keep-alive, 느린 client, LB timeout을 본다.
maxThreads,acceptCount, timeout 변경 전 downstream capacity와 retry 정책을 확인한다.
이 순서는 Tomcat Connector와 OS Socket 연결 후보를 빠르게 좁히기 위한 기본 루틴이다. 결론을 내리기 전에는 애플리케이션 증거와 JVM/OS 증거를 최소 한 번 이상 맞춘다.
실전 팁
maxThreads를 키우면 CPU와 downstream 동시성도 같이 늘어난다는 점을 확인한다.acceptCount는 장애를 숨기는 대기열이 될 수 있으므로 client timeout과 같이 조정한다.- Connector metric은
sssnapshot과 같은 시각에 남겨야 앞단/뒷단 병목을 나눌 수 있다. - Busy thread가 높으면 socket보다 thread dump의 blocking 위치가 다음 판단 근거다.
- 장애 회고에는 connector 설정값, 실제 metric, timeout 예산을 함께 남긴다.
주니어 팁
- Tomcat connector는 Spring Controller 앞에서 요청을 worker thread에 배정하는 경계라고 이해한다.
maxThreads는 “성능을 올리는 값”이 아니라 동시에 막힐 수 있는 작업 수의 상한이다.- Connector 지표를 볼 때는 반드시 같은 시각의
ss와 thread dump를 붙여 본다.
시니어 팁
- Connector thread 상한은 CPU core, DB pool, HTTP client pool, endpoint latency를 기준으로 정한다.
- Timeout 예산은 client → LB → Tomcat → downstream 순서로 실패가 예측 가능하게 설계한다.
- Connector 포화 알림은 busy thread 비율, queue/drop 신호, latency를 묶어서 잡는다.
Guru급 팁
Tomcat Connector와 OS Socket 연결주제는 단일 snapshot보다 변화 방향이 중요하다. 같은 명령을 간격을 두고 실행해 상태가 증가, 유지, 회복 중 어디인지 본다.- 고급 도구는
Tomcat Connector와 OS Socket 연결가설을 좁힐 때만 사용하고 기본 지표와 모순되는지 먼저 확인한다. Tomcat Connector와 OS Socket 연결조치 후에는 CPU, memory, socket, disk, pool 중 다음 포화 지점이 어디로 이동했는지 확인한다.
위험 신호!
- Busy thread 100%를 보고
maxThreads만 키운다. acceptCount를 크게 잡아 client가 더 오래 기다리게 만든다.- Connection metric만 보고 worker thread가 실제 어디에서 막혔는지 thread dump를 남기지 않는다.
- Timeout 설정을 각 계층별로 보지 않고 Tomcat 값 하나만 바꾼다.
- Connector 설정 변경 후 downstream pool 포화나 retry 증가를 확인하지 않는다.
확인 질문
확인 질문
- Tomcat busy thread가 높을 때 다음으로 확인할 증거는 무엇인가?
- Thread dump에서 worker thread가 DB, 외부 HTTP, lock, CPU 작업 중 어디에 묶였는지 확인해야 한다.
acceptCount를 늘리는 조치가 위험할 수 있는 이유는 무엇인가?
- 처리 능력이 늘지 않은 상태에서 대기열만 길어져 client timeout과 지연을 키울 수 있기 때문이다.
- Connector 문제를 OS socket 문제와 구분하려면 어떤 지표를 같은 시간에 봐야 하는가?
ss의 listen/connection state, Tomcat busy/current connection metric, thread dump, LB timeout 로그를 같은 시간축으로 봐야 한다.