배경
우아한테크의 테코톡을 보고 배운 내용들을 간단하게 정리해 볼까 합니다.
내용
Program / Process / Thread
스레드를 사용하면서 하나의 프로세스 안에 두 가지 이상의 작업을 병렬 처리 가능(CPU Core가 여러개일 경우)
그러면 단순히 thread를 무한히 늘리면서 작업을 할 수 있을까요?
하나의 요청에 대해서 하나의 thread를 생성하게 된다면 어떻게 될까요? thread는 생성 비용이 크기 때문에 점차 늘어날 수록 메모리를 많이 사용하게 되면서 서버 응답시간이 늘어나게 됩니다.
특히 Java의 경우 One-to-One Threading-Model로 thread를 생성하게 됩니다.
process의 처리속도보다 빠르게 요청이 들어오게 된다면 thread가 무한히 생성되게 될 겁니다. 이는 CPU오버헤드로 이어지겠죠.
이에 해결책으로 나온 것이 Thread Pool이라는 개념입니다. Thread Pool이라는 개념은 허용된 thread 개수 안에서 사용하도록 제한하는 시스템입니다.
그림을 보시게 되면 요청이 들어 오게 되면 작업큐에 작업을 하나씩 쌓아두고 스레드가 하나씩 처리하는 방법이 보이죠? 여기서 특징은, 작업이 끝난 스레드는 사라지는게 아니라 재사용이 가능하다는 것입니다.
Java에서의 Thread Pool을 알아보겠습니다.
Java에서 thread pool은 ThreadPoolExecutor로 관리가 됩니다. ThreadPoolExecutor의 특징은 항상 maximumPoolSize로 thread를 최대로 만들어 놓는게 아니라, 일정시간동안 요청이 없을 경우(keepAliveTime) corePoolSize까지 thread개수를 줄여서 관리를 하게 됩니다.
Java에서 web하면 뺴놓을 수 없는 것이 바로 Tomcat입니다. Tomcat의 경우도 Java와 매우 비슷한 thread pool 구현체를 가지고 있습니다.
한가지 추가된 점은 acceptCount라는 큐인데 이것은 maxConnections이상의 요청이 들어왔을 경우 사용하게 됩니다. acceptCount까지 꽉차게 되면 추가 요청이 거절될 수도 있습니다.
그럼 thread pool에서 관리하는 thread의 개수는 관리할 수는 없을까요? Spring Boot에서는 thread pool을 설정해서 custom하게 사용이 가능합니다.
- server.tomcat.threads.max : thread pool에서 사용할 최대 스레드 개수. 기본값 200.
- server.tomcat.threads.min-spare : thread pool에서 최소한으로 유지할 thread 개수. 기본값 10.
- server.tomcat.max-connections : 동시에 처리할 수 있는 최대 Connection의 개수. 기본 8192.
- server.tomcat.accept-count : max-connections 이상의 요청이 들어왔을 때 사용하는 대기열 Queue 사이즈. 기본 100.
thread pool 크게만 하면 좋을까요? 놀고 있는 스레드가 많아져 비효율이 발생하게 됩니다. 프로젝트에 들어올 요청 예상에 따라 적절하게 설정하는 것이 매우 중요하다고 생각합니다.
여기서 connections는 Blocking 방식과 Non-Blocking 방식으로 나뉘게 됩니다. Blocking 방식의 경우 1 connection = 1 thread로 connection과 thread가 1:1 대응됩니다. Non-Blocking 방식의 경우 1 connection = N thread 즉, 하나의 connection 다수의 thread가 처리 가능합니다. Tomcat8 이상의 경우 Non-Blocking 방식이 기본 적용되기 때문에 max-connection의 수가 max thread 수보다 같거나 작으면 비효율적인 설정이 되게 됩니다.
적절하게 thread pool을 설정하는 것은 응답시간을 줄이고 안정적인 app 운용을 가능하게 할것이라 생각됩니다. 하지만 항상 고민되는 것들이 있죠.. 과연 적절한 값이라는게 뭘지 ㅎㅎ.. 이 부분은 차차 알아봐야 할 것 같습니다.
'개발 > Java' 카테고리의 다른 글
Fetch Join (0) | 2024.11.24 |
---|---|
Block vs Non-Block & Sync vs Async (0) | 2024.11.23 |
static method(정적 메서드) (1) | 2024.11.21 |
Request, Response Logging (1) | 2024.11.20 |
Swagger 적용해보기 (1) | 2024.11.19 |