이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.
CPU Core와 실행 단위에서 붙잡아야 할 핵심 판단 기준은 무엇인가?core는 실행 자원이고 thread는 실행 후보이다라는 기준은 어떤 JVM/OS 신호로 확인되는가?- Java/Spring 코드에서
CPU Core와 실행 단위판단 기준은 어떤 장애 신호로 드러나는가?
개요
이 문서의 주제는 CPU Core와 실행 단위이다. CPU core, hardware thread, process, Java thread가 실제 실행에서 어떤 관계를 갖는지 다룬다.
먼저 붙잡을 기준은 다음 문장이다. core는 실행 자원이고 thread는 실행 후보이다. 이 문서는 이 기준을 Java/Spring 실행 흐름, JVM/OS 관찰 지표, 장애 판단 순서로 연결한다.
핵심 모델
- 판단 기준: core는 실행 자원이고 thread는 실행 후보이다.
- CPU core는 동시에 실행할 수 있는 작업 수의 물리적 상한에 가깝다. thread 수가 이 상한을 넘으면 runnable 대기와 context switch가 생긴다.
- Java thread가 많다는 사실은 곧 처리량이 높다는 뜻이 아니다. CPU bound 작업에서는 runnable thread가 늘수록 경합이 커질 수 있다.
- Container 환경에서는 host core 수가 아니라 CPU quota와 throttling을 함께 봐야 한다.
- Per-thread CPU와 Java thread dump의
nid를 연결해야 어떤 Java 코드가 core를 쓰는지 확인할 수 있다.
문서별 핵심 구분
- core는 실제 실행 자원이고 thread는 실행 후보이다.
- CPU 사용률은 전체 평균보다 per-thread 사용량과 runnable 개수가 중요할 때가 많다.
- 동시성이 늘어도 CPU bound 작업은 core 수가 처리량 상한을 만든다.
원리
CPU core는 실제 실행 자원이고 thread는 실행 후보이다. runnable thread가 core보다 많으면 scheduler 대기와 context switch가 생긴다.
Process는 주소 공간과 file descriptor table을 갖고, thread는 같은 process 안에서 heap과 열린 자원을 공유한다.
Java platform thread는 운영체제 thread와 연결되므로 thread 수 증가는 stack memory, scheduling 비용, dump 분석 비용을 함께 늘린다.
CPU Core와 실행 단위 관점에서 중요한 점은 thread 수와 CPU 실행 수를 같은 말로 보지 않는 것이다. Java thread는 실행 후보이고 CPU core는 실제 실행 자원이므로, runnable thread가 많을 때는 per-thread CPU, run queue, container CPU quota를 함께 확인해야 한다.
Java/Spring 연결
- Spring MVC 요청 하나는 보통 Tomcat worker thread 하나를 점유한다. CPU bound handler가 길어지면 같은 worker pool의 다른 요청도 대기한다.
- JSON 직렬화, 암호화, 압축, 대량 mapping은 외부 I/O가 없어도 CPU core를 점유한다.
@Async로 CPU 작업을 별도 executor에 넘겨도 실제 core 수가 늘어나지는 않는다.- Tomcat
threads.max와 executor size는 CPU quota, DB pool, downstream capacity와 함께 조정한다. top -H의 TID와 thread dump의nid를 맞추면 CPU를 쓰는 Spring 코드 경로를 좁힐 수 있다.
코드와 설정 예시
ExecutorService pool = Executors.newFixedThreadPool(20);
CompletableFuture<Order> future = CompletableFuture.supplyAsync(() -> {
return orderClient.fetch(orderId);
}, pool);예시는 CompletableFuture 문법보다 실행 자원 질문을 보기 위한 것이다. pool size 20은 동시에 CPU를 20개 쓰겠다는 뜻이 아니며, core 수, blocking 비율, downstream capacity, queue 정책과 함께 판단해야 한다.
관찰 명령
nproc
lscpu | head
top -H -p <pid>
ps -L -p <pid> -o pid,tid,stat,pcpu,commCPU Core와 실행 단위 관찰 명령은 결론이 아니라 가설 확인 도구다. 운영 중에는 반복 간격, 대상 PID, 수집 시각을 함께 남기고 출력이 큰 명령은 범위를 제한한다.
지표 해석
| 신호 | 먼저 의심할 것 | 다음 확인 |
|---|---|---|
| RUNNABLE thread가 core보다 많음 | CPU 경합 또는 native I/O 대기 | top -H, stack trace, load average |
| BLOCKED가 특정 lock에 몰림 | synchronized/monitor 경합 | lock owner와 기다리는 thread |
| WAITING/TIMED_WAITING이 pool에 몰림 | queue 대기, connection 대기, sleep/retry | executor, Hikari, timeout 지표 |
| thread 수가 계속 증가 | unbounded executor 또는 thread leak | thread name 분포와 생성 위치 |
CPU Core와 실행 단위에서는 핵심 신호와 보조 지표를 같은 시간축에서 맞춘다. 먼저 변한 신호와 뒤따라 포화된 신호를 분리해야 원인과 결과를 구분할 수 있다.
장애 상황에서 보는 순서
top -H -p <pid>로 CPU를 많이 쓰는 native thread를 찾는다.- 같은 시각의 thread dump에서
nid를 맞춰 Java stack을 확인한다. - container CPU quota와 throttling 지표를 확인해 host 평균과 분리한다.
- CPU bound 코드인지 GC/compiler thread인지, native library인지 나눈다.
- thread 수 증가가 처리량 증가가 아니라 runnable 대기 증가인지 확인한다.
이 순서는 CPU 실행 자원 부족과 Java 코드 경로를 연결하기 위한 루틴이다.
실전 팁
top -H로 CPU를 많이 쓰는 thread를 먼저 찾는다.- native thread id를 thread dump의
nid와 맞춘다. - CPU bound 작업은 thread를 늘리기보다 작업량과 알고리즘을 줄인다.
- core 수와 container CPU quota를 함께 확인한다.
- 암호화, 압축, JSON 직렬화처럼 CPU를 쓰는 경로를 따로 본다.
주니어 팁
CPU Core와 실행 단위주제는 용어 암기보다 정상 상태와 장애 상태에서 어떤 증거가 달라지는지 연결해 익힌다.- 처음에는
CPU Core와 실행 단위를 재현 가능한 기본 명령과 Actuator 지표로 확인하는 습관부터 만든다. CPU Core와 실행 단위숫자는 크기 자체보다 평소 기준선에서 얼마나 벗어났는지로 판단한다.
시니어 팁
CPU Core와 실행 단위주제의 영향이 pool, queue, retry, timeout으로 번지는 경로를 설계 리뷰에 포함한다.CPU Core와 실행 단위runbook에는 실행 명령, 정상 범위, 해석 기준, 금지할 대응을 같이 둔다.CPU Core와 실행 단위판단이 container, LB, 다중 인스턴스 환경에서도 같은 의미인지 확인한다.
Guru급 팁
CPU Core와 실행 단위주제는 단일 snapshot보다 변화 방향이 중요하다. 같은 명령을 간격을 두고 실행해 상태가 증가, 유지, 회복 중 어디인지 본다.- 고급 도구는
CPU Core와 실행 단위가설을 좁힐 때만 사용하고 기본 지표와 모순되는지 먼저 확인한다. CPU Core와 실행 단위조치 후에는 CPU, memory, socket, disk, pool 중 다음 포화 지점이 어디로 이동했는지 확인한다.
위험 신호!
- thread 수를 늘리면 CPU 작업 처리량도 선형 증가한다고 믿는다.
- container CPU quota를 모르고 host core 수만 본다.
- CPU 평균만 보고 특정 hot thread를 놓친다.
- RUNNABLE을 모두 CPU 사용 중으로 단정한다.
- GC thread와 application thread CPU를 구분하지 않는다.
확인 질문
확인 질문
CPU Core와 실행 단위주제를 장애 중 확인할 때 Application 로그만으로 부족한 이유는 무엇인가?
- 로그는 코드 경로를 보여 주지만
CPU Core와 실행 단위의 JVM/OS 자원 상태, 대기 위치, 포화 방향은 별도 지표로 확인해야 하기 때문이다.CPU Core와 실행 단위관련 설정이나 pool 크기를 바꾸기 전에 확인할 것은 무엇인가?
- 먼저 변한 신호, 하위 자원 capacity, 변경이 완화인지 증폭인지 판단할 기준을
CPU Core와 실행 단위지표로 확인해야 한다.CPU Core와 실행 단위재발을 막기 위해 장애 기록에 무엇을 남겨야 하는가?
- 발생 시간, 영향 범위, 사용한 명령,
CPU Core와 실행 단위핵심 지표, 원인 판단, 완화 조치, 근본 수정, 남은 리스크를 남긴다.