https://www.youtube.com/watch?v=um4rYmQIeRE 

Why Review?

Java, Tomcat, SpringBoot의 Thread Pool을 WAS 관점에서 궁금증이 생겼다.

 

Program / Process / Thread 

CPU Core가 Thread 단위로 작업을 처리한다. 

Thread를 사용함으로써 하나의 Process에서 두가지 이상의 작업을 동시에 실행가능하다는 것이다.

 

단순히 Thread만 사용해서 동시에 여러 작업을 실행시킬 수 있는 프로그램을 만들 수 있을까?

Thread를 단순하게 사용할때 요청이 올때마다 새로 Thread를 생성하여 작업이 끝나면 삭제하는 방식이다.

문제가 생긴다.

1. Thread 생성 비용이 크기 때문에 요청에 대한 응답시간이 늘어난다.

  1)Java는 One-to-One Threadming Model로 Thread를 생성한다. 

  2) User Thread(Process의  Thread) 생성시 OS Thread( OS Leveld의 Thread) 와 연결해야한다.

  3) 새로운 Thread를 생성할때마다 OS Kernel의 작업이 필요하므로 생성비용이 많이든다.

 

2번쨰 문제. Thread가 너무 많으면 여러가지 문제 발생.

  2-1. Process의 처리속도보다 빠르게 요청이 들어오면, 새로운 Thread가 무제한적으로 계속생성된다.

  2-2. Thread가 많아질수록 메모리를 차지하고 Context-Switching이 더 자주 발생.

  2-3.메모리 문제가 발생하고 CPU 오버헤드가 증가.

 

 

이러한 문제점을 해결하기 위해 Thread Pool 을 사용한다.

Pool of Threads 를 사용하여 Thread를 허용된 개수 안에서 사용하도록 제한하는 시스템입니다.

 

간단하게 Thread Pool은 크게 두가지 요소로 이루어져있습니다.

1. 작업할 쓰레드 최대갯수 n개

2. 작업큐

Thread Pool은 단순 Thread문제점을 해결가능하다.

1. 미리 만들어놓은 Thread를 재사용하기때문에 새로운 Thread를 생성하는 비용을 줄일 수 있다.

2. 사용할 Thread개수를 제한하기 때문에 무제한적으로 스레드가 생성되지 않아서 메모리문제, CPU 오버헤드를 피할 수 있다.

 

여러개의 작업을 동시에 처리하면서도 안정적으로 처리할 수 있다.

 

Java의 Thread Pool 구현방법은,

1. ThreadPoolExecutor Class를 이용해서 Thread Pool을 구현합니다.

1) maxinumPoolSize : 최대 Thread Size

2) KeepAliveTime : 특정 시간동안 작업이 없을경우 Thread 삭제. 

3) CorePoolSize : 최소 Thread 개수

요청이 없을떄는 Thread가 필요없으므로 KeepAliveTime 이후의 시간에도 작업이 없을경우 Thread가 사라집니다.

 

딱 해당하는 경우는 WebServer에 적합하다.

동시적인 요청을 동시에 처리해야하기에, 많은 어플리케이션이 Thread Pool을 사용중이다.

 

Tomcat의 Thread Pool

1) Spring Boot의 내장 Servlet Container 중 하나

- Springboot 최신 버전에서는 Tomcat 9 버전을 사용중이다.

- Java 기반의 WAS

- Java의 Thread Pool 클래스와 매우 유사한 자체 스레드 풀 구현체를 가지고 있다. org.apache.tomcat.util.threads.ThreadPoolExecutor

 

Java의 Thread Pool 클래스와 비교하여 더 알아야할점들 2가지정도 추가적인것이 필요

Max-Connections

- Tomcat이 최대로 동시에 처리할 수 있는 Connection 의 개수

web 요청이 들어오면 Tomcat의 Connector가 Connection을 생성하면서 요청된 작업을 Thread Pool의 Thread에 연결한다.

 

Accept-Count

- Max-Connections 이상의 요청이 들어왔을떄 사용하는 대기열 Queue의 사이즈

- Max-Connections와 Accept-Count 이상의 요청이 들어왔을때 추가적으로 들어오는 요청은 거절될 수 있다.

 

 

Thread Pool의 개념을 가지고서 Java, Tomcat의 Thread Pool 이 구현되어잇다.

동시 요청을 안정적으로 처리해야하는 WebSever에서 Thread Pool을 생성한다.

어떻게 잘설정해야 Thread Pool을 사용할 수 있을까?

 

Spring Boot 설정을 통한 Tomcat Thread Pool 설정

server.tomcat.threads.max

- Thread Pool에서 사용할 최대 스레드 개수, 기본값은 200

- 서버 애플리케이션이 동시에 처리할 수 있는 요청개수와 관련있다.

- 요청수에 비해 너무 많게 설정한다면, 놀고있는 스레드가 많아져서 비효율 발생

- 너무 적게 설정하면 동시처리 요청수가 줄어든다. 평균응답시간과 TPS 가 감소된다.

- 기본적으로 Thread가 많아지면 CPU 오버헤드와 메모리에서 문제가 생길 수 있다는걸 고려해야한다.

 

server.tomcat.threads.min-spare

- Thread Pool에서 최소한으로 유지할 Thread 개수, 기본값은 10

- 너무많이 설정한다면 Thread Pool 이 항상 유지해야할 Thread 수가 너무 많아진다.

- 적절하게 설정한다면, 적은 수의 요청에서 새로운 스레드를 만들 필요없이 요청을 효과적으로 처리할 수 있다.

- 잘못설정했을때 사용하지 않는 Thread가 메모리를 차지하면서 비효율을 발생시킨다는걸 고려해야한다.

 

server.tomcat.max-connections

- 동시에 처리할 수 있는 최대 Connection 의 개수, 기본 값은 8192개를 동시에 처리가능

- 사실상 서버의 실질적인 동시요청 처리개수라고 생각할 수 있습니다..

Tomcat의 Connector Component의 방식에 따라 개수를 설정합니다.

  - Non-Blocking IO에서는 Thread Pool의 최대 스레드 개수보다 많은 양의 Connection을 유지할 수 있다. Tomcat 8 버전부터는 Non-Blocking 방식이기에 이와 같이 설정합니다. N Connection 에 1 Thread. 

  - Blocking IO에서는 최대 Thread 개수보다 적거나 같은 수의 max-connections를 설정하는 것은 비효율적인 설정이 될 수 있다.1 Connection에 1 Thread

 

server.tomcat.accept-count

- max-connections 이상의 요청이 들어왔을때 사용하는 요청 대기열 Queue의 사이즈 기본값은 100

- 너무 크게 설정하면 대기열이 커지면서 메모리 문제를 유발할 수 있다.

- 너무 작게설정하면 요청이 몰렸을떄 들어오는 요청을 거절해버릴 수 있다.

- 이 설정을 하는 이유 중 하나는 부적절하거나 잘못된 요청이 한번에 너무 많이 들어와 서버에 장애를 발생시키는 것을 방지하기 위함도 있다.

 

우리가 Thread Pool 설정을 해야하는 이유

- Thread Pool은 응답시간과 TPS에 영향을 주는 하나의 요소이다.

- 잘 조정된 Thread Pool은 시스템의 성능을 끌어내고 안정적인 어플리케이션 운용을 가능하게한다.

- 부적절하게 설정된 Thread Pool은 병목현상, CPU 오버헤드나 메모리 병목현상을 일으키게 한다.

 

 

 

 

 

 

 

 

+ Recent posts