Java, Tomcat, SpringBoot에서의 Thread Pool을 Web server application 관점에서 살펴보자.
....
먼저 Program / Process / Thread를 살펴보자.
Program
- 어떤 목적을 위해 컴퓨터의 동작을 하나로 모아 둔 것 (코드 덩어리)
Process
- 현재 실행중인 프로그램
Thread
- Cpu core의 실행 단위
- Process의 작업을 Thread 단위로 나눌 수 있음
- 이를 Cpu core가 처리
- 하나의 Process 에서 두가지 이상 작업을 동시에 실행 가능
...
단순히 Thread만 사용해서 동시에 여러 작업을 실행시킬 수 있는 프로그램을 만들 수 있을까?
Thread를 단순하게 사용할 때
- 요청이 올 때마다 새로운 스레드를 생성하여 작업을 처리하고 처리가 끝나면 스레드를 없애는 방식으로 동작하는 프로세스이다.
문제 1)
- 스레드 생성 비용이 크기때문에 요청에 대한 응답시간이 늘어난다.
- 이 말은 User Thread(프로세스 스레드) 생성 시 OS Thread 와 연결해야하고,
- 새로운 스레드를 생성할 때마다 OS 커널 작업이 필요하다.
- 이는 스레드 생성 비용이 많이 든다고 판단할 수 있다.
문제2)
- 프로세스의 처리 속도보다 빠르게 요청이 들어오면 새로운 스레드가 무제한 적으로 생긴다.
- 스레드가 많아질수록 메모리를 차지하고, 컨텍스트 스위칭이 더 자주 발생한다.
- 메모리 문제가 발생할 수 있고 CPU 오버헤드가 증가한다.
...
단순히 Thread만 사용해서는 문제가 많다. 이를 위해 스레드 풀을 사용한다. 스레드 풀이란, 스레드를 허용된 개수 안에서 사용하도록 제한하는 시스템을 말한다.
스레드 풀은 두 가지 요소로 구성되어 있다.
1) 스레드 풀에서 작업하는 스레드
2) 작업 큐
- 스레드 풀에 작업 요청이 들어오면 작업 큐에 작업이 쌓인다.
- 그리고 스레드 풀 안에 스레드들이 작업 큐의 작업을 빼서 처리한다.
스레드 풀의 특징
- 정해진 양만큼의 스레드를 사용
- 사용된 스레드는 없어지지 않고 재사용 가능
...
스레드 풀을 이용하면 위 '문제 1), 문제 2)'를 처리할 수 있다.
- 미리 만들어 놓은 스레드를 재사용할 수 있기 때문에 새로운 스레드를 생성하는 비용을 줄일 수 있음.
- 스레드 개수를 제한하기 때문에 무제한적 스레드가 생성되는 것을 방지할 수 있음.
결론, 여러개의 작업을 동시에 처리하면서도 안정적으로 처리하고 싶을 때 스레드 풀은 효과적이다.
...
자바에서는 스레드 풀을 어떻게 구현하고 있을까?
- 스레드 풀 executor라는 클래스를 이용하여 스레드 풀 구현
- maximumPoolSize, KeepAliveTime, corePoolSize 특징을 가지고 있다.
- KeepAliveTime 시간동안 요청이 없으면 스레드는 corePoolSize 만큼만 사라진다.
- 최대 maximumPoolSize, 최소 corePoolSize 만큼 가지고 있다.
여러개의 작업을 동시에 처리하면서도 안정적으로 처리하고 싶을 땐 스레드 풀은 효과적이다.
...
웹 서버의 특성은 동시 요청을 동시에 처리 해야한다. 그래서 웹 서버들은 스레드 풀 시스템을 사용하고 있다.
...
톰켓의 스레드 풀
톰켓은 스프링 부트 내장 서블릿 컨테이너 중 하나이다.
Java 기반의 WAS이다.
Java 의 스레드 풀 클래스와 매우 유사한 자체 스레드 풀 구현체를 가지고 있다.
'org.apache.tomcat.util.threads.ThreadPoolExecutor'
톰켓 스레드 풀 자체는 자바의 스레드 풀과 비교했을 때 두 가지 알아야 하는 것이 있다.
1) MaxConnections
- 톰켓이 최대로 동시에 처리할 수 있는 커넥션의 개수
- 웹 요청이 들어오면 톰켓의 커넥터 가 커넥션을 생성하면서 스레드 풀의 스레드에 연결한다.
- 이 때 동시에 연결해서 처리할 수 있는 커넥션의 개수가 MaxConnections
2) Accept-Count
- MaxConnections 이상의 요청이 들어왔을 때 사용하는 대기열 Queue의 사이즈
- MaxConnections 와 AcceptCount 이상의 요청이 들어왔을 때 추가적으로 들어오는 요청은 거절될 수 있다.
...
여기까지, 아래 개념을 학습했다.
1) 스레드 풀의 개념
2) 자바와 톰켓의 스레드 풀 비교
3) 동시 요청을 안정적으로 처리해야하는 웹 서버에서 스레드 풀을 사용
어떻게 하면 스레드 풀을 잘 설정해서 서버 어플리케이션을 효과적으로 구현할 수 있을까?
-> SpringBoot 설정으로 Tomcat 스레드 풀 설정이 가능
- 'server.tomcat.thread.max'
- Thread Pool에서 사용할 최대 스레드 개수, 기본 200
- 서버 어플리케이션이 동시에 처리할 수 있는 요청 개수와 관련있다.
만약,
1) 요청 수에 비해 너무 많게 설정 -> 놀고 있는 스레드가 많아져서 비효율 발생
2) 너무 적게 설정 -> 동시 처리 요청수가 줄어든다. (평균응답시간, TPS 감소)
스레드가 많아지면 CPU 오버헤드와 메모리에서 문제가 생길 수 있다는 걸 고려해야 함
- 'server.tomcat.thread.min-spare'
- 스레드 풀에서 최소한으로 유지할 스레드 개수, 기본 10
1) 너무 많이 설정 -> 스레드 풀이 항상 유지해야 할 스레드 수가 너무 많아진다.
2) 적절하게 설정 -> 적은 수의 요청에서 새로운 스레드를 만들 필요없이 요청을 효과적으로 처리할 수 있다.
잘못 설정했을 때 사용하지 않는 스레드가 메모리를 차지하면서 비효율을 발생시킨다는 것을 고려해야한다.
- 'server.tomcat.thread.max-connections'
- 동시에 처리할 수 있는 최대 커넥션 개수, 기본 8192
- 사실상 서버의 실질적은 동시 요청 처리 개수라 생각할 수 있음.
- 논블록킹 IO에서는 스레드 풀의 최대 스레드 개수보다 많은 양의 커넥션을 유지할 수 있음.
- 논블록킹 IO에서는 최대 스레드 개수보다 적거나 같은 수의 max-connections를 설정하는 것은 비효율적인 설정이 될 수 있다.
1) 블록킹 IO
- 1 connections : 1 Thread
2) 논블록킹 IO (톰켓 8이상)
- N connections : 1 Thread
'Web' 카테고리의 다른 글
XML & JSON & YAML (0) | 2021.10.30 |
---|---|
[DB] Connection Pool 정리 (1) | 2021.09.11 |
쿠키(Cookie)와 세션(Session) 정리 (0) | 2021.09.04 |
HTTP 프로토콜 정리 (0) | 2021.08.28 |