이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.
Blocking이 Thread를 점유하는 방식에서 붙잡아야 할 핵심 판단 기준은 무엇인가?대기 시간은 thread 점유 시간이다라는 기준은 어떤 JVM/OS 신호로 확인되는가?- Java/Spring 코드에서
Blocking이 Thread를 점유하는 방식판단 기준은 어떤 장애 신호로 드러나는가?
개요
이 문서의 주제는 Blocking이 Thread를 점유하는 방식이다. DB, 외부 API, 파일 I/O 같은 blocking 호출이 요청 thread를 어떻게 붙잡는지 설명한다.
먼저 붙잡을 기준은 다음 문장이다. 대기 시간은 thread 점유 시간이다. 이 문서는 이 기준을 Java/Spring 실행 흐름, JVM/OS 관찰 지표, 장애 판단 순서로 연결한다.
핵심 모델
- 판단 기준: blocking은 기다리는 동안 thread를 점유한다.
- DB, HTTP client, file I/O 호출이 결과를 기다리면 worker thread는 다른 요청을 처리하지 못한다.
- Blocking 자체가 나쁜 것은 아니지만 timeout과 pool 경계가 없으면 장애가 thread 고갈로 번진다.
- Thread dump의 WAITING/TIMED_WAITING은 stack 위치와 함께 봐야 실제 대기 대상을 알 수 있다.
- Blocking 구간의 길이와 동시 요청 수가 worker pool capacity를 결정한다.
문서별 핵심 구분
- blocking 호출은 결과가 올 때까지 요청 thread를 붙잡는다.
- DB, 외부 API, 파일 I/O는 모두 blocking 지점이 될 수 있다.
- busy thread가 많으면 새 요청은 코드 실행 전부터 대기한다.
원리
Blocking은 현재 thread가 결과를 기다리는 동안 다른 작업을 처리하지 못하는 실행 방식이다.
Non-blocking은 대기 중인 I/O를 OS나 event loop에 맡기고 thread 점유를 줄이는 방식이지만 CPU 작업 자체가 사라지지는 않는다.
Async는 호출자와 실행자를 분리한다. 실행자가 부족하거나 queue가 무제한이면 병목 위치만 바뀐다.
Blocking이 Thread를 점유하는 방식 관점에서 중요한 점은 대기 중인 thread도 서버 capacity를 소비한다는 것이다. CPU를 거의 쓰지 않아도 Tomcat worker, executor worker, DB connection 같은 제한된 자원을 붙잡을 수 있으므로 busy thread와 pool 대기 지표를 함께 봐야 한다.
Java/Spring 연결
- Spring MVC handler가 JDBC나 외부 HTTP 호출을 기다리면 Tomcat worker가 그대로 묶인다.
RestTemplate, blockingWebClient.block(), JDBC driver는 thread 점유 시간을 늘릴 수 있다.- Timeout이 길면 실패가 늦게 드러나고 worker pool 고갈이 먼저 나타난다.
- Hikari connection 대기는 DB 문제가 아니라도 요청 thread를 막는다.
- Circuit breaker와 bulkhead는 blocking 대기가 전체 worker pool로 번지는 것을 제한한다.
코드와 설정 예시
@GetMapping("/reports")
public Report download() {
return reportService.createLargeReport(); // 요청 thread를 오래 점유할 수 있다.
}예시는 blocking 호출이 요청 thread를 얼마나 오래 붙잡는지 보기 위한 것이다. createLargeReport() 안에서 DB 조회, 파일 쓰기, 외부 API 호출이 길어지면 해당 Tomcat worker는 응답을 반환할 때까지 다른 요청을 처리하지 못한다.
관찰 명령
jcmd <pid> Thread.print
top -H -p <pid>
curl -s localhost:8080/actuator/metrics/tomcat.threads.busyBlocking이 Thread를 점유하는 방식 관찰 명령은 결론이 아니라 가설 확인 도구다. 운영 중에는 반복 간격, 대상 PID, 수집 시각을 함께 남기고 출력이 큰 명령은 범위를 제한한다.
지표 해석
| 신호 | 먼저 의심할 것 | 다음 확인 |
|---|---|---|
| Tomcat busy thread가 max 근처 | blocking I/O 또는 긴 요청 처리 | thread dump와 endpoint별 latency |
| executor queue가 계속 증가 | worker 부족 또는 downstream 지연 | active/queued/rejected 지표 |
| event loop thread CPU가 높음 | loop 안 CPU 작업 또는 blocking 호출 | JFR, thread name, stack trace |
| timeout 후 retry 급증 | backpressure 실패 | retry 로그와 downstream error rate |
Blocking이 Thread를 점유하는 방식에서는 핵심 신호와 보조 지표를 같은 시간축에서 맞춘다. 먼저 변한 신호와 뒤따라 포화된 신호를 분리해야 원인과 결과를 구분할 수 있다.
장애 상황에서 보는 순서
- thread dump에서 worker thread가 기다리는 stack 위치를 찾는다.
- DB, 외부 API, file I/O, lock 대기 중 어디에 몰렸는지 분리한다.
- 해당 dependency의 timeout과 connection pool 상태를 확인한다.
- 요청량 증가인지 dependency 지연인지 시작 시각을 맞춘다.
- worker pool을 키우기 전에 timeout, bulkhead, fallback을 먼저 검토한다.
이 순서는 blocking이 thread 점유로 번지는 지점을 찾기 위한 루틴이다.
실전 팁
- blocking 구간은 “실행 시간”이 아니라 “thread 점유 시간”으로 기록한다.
- DB, 외부 API, 파일 I/O에는 connection timeout, read timeout, 전체 요청 timeout을 함께 둔다.
- 오래 걸리는 리포트, 대량 다운로드, batch성 작업은 웹 요청 thread에서 끝까지 처리할지 먼저 의심한다.
- Tomcat busy thread가 max에 가까운데 CPU가 낮으면 blocking 대기를 우선 후보로 본다.
- timeout 후 즉시 retry가 붙어 있으면 blocking 대기가 더 빠르게 thread 고갈로 번질 수 있다.
주니어 팁
Blocking이 Thread를 점유하는 방식주제는 용어 정의보다 장애 때 어떤 증거로 확인할지까지 연결해 익힌다.- 정상 상태에서 이 문서의 관찰 명령을 실행해
Blocking이 Thread를 점유하는 방식기준선을 남긴다. - 장애 시에는
Blocking이 Thread를 점유하는 방식신호가 평소 기준선에서 벗어난 시각과 방향을 먼저 본다.
시니어 팁
Blocking이 Thread를 점유하는 방식주제의 영향이 pool, queue, retry, timeout으로 번지는 경로를 설계 리뷰에 포함한다.Blocking이 Thread를 점유하는 방식runbook에는 실행 명령, 정상 범위, 해석 기준, 금지할 대응을 같이 둔다.Blocking이 Thread를 점유하는 방식판단이 container, LB, 다중 인스턴스 환경에서도 같은 의미인지 확인한다.
Guru급 팁
Blocking이 Thread를 점유하는 방식주제는 단일 snapshot보다 변화 방향이 중요하다. 같은 명령을 간격을 두고 실행해 상태가 증가, 유지, 회복 중 어디인지 본다.- 고급 도구는
Blocking이 Thread를 점유하는 방식가설을 좁힐 때만 사용하고 기본 지표와 모순되는지 먼저 확인한다. Blocking이 Thread를 점유하는 방식조치 후에는 CPU, memory, socket, disk, pool 중 다음 포화 지점이 어디로 이동했는지 확인한다.
위험 신호!
- Controller 로그에는 빠르게 들어오지만 응답이 늦는 요청이 늘어난다.
- CPU는 낮은데 Tomcat busy thread와 queue가 계속 찬다.
- 외부 API timeout이 없거나 너무 길어 thread가 오래 묶인다.
- DB connection pool 대기와 요청 thread 대기를 같은 문제로 뭉뚱그린다.
- pool size만 늘려 downstream 장애를 더 세게 압박한다.
확인 질문
확인 질문
Blocking이 Thread를 점유하는 방식주제를 장애 중 확인할 때 Application 로그만으로 부족한 이유는 무엇인가?
- 로그는 코드 경로를 보여 주지만
Blocking이 Thread를 점유하는 방식의 JVM/OS 자원 상태, 대기 위치, 포화 방향은 별도 지표로 확인해야 하기 때문이다.Blocking이 Thread를 점유하는 방식관련 설정이나 pool 크기를 바꾸기 전에 확인할 것은 무엇인가?
- 먼저 변한 신호, 하위 자원 capacity, 변경이 완화인지 증폭인지 판단할 기준을
Blocking이 Thread를 점유하는 방식지표로 확인해야 한다.Blocking이 Thread를 점유하는 방식재발을 막기 위해 장애 기록에 무엇을 남겨야 하는가?
- 발생 시간, 영향 범위, 사용한 명령,
Blocking이 Thread를 점유하는 방식핵심 지표, 원인 판단, 완화 조치, 근본 수정, 남은 리스크를 남긴다.