개요
Spring에서 사용자의 요청을 처리하기 위해서 HTTP Connection이 수립되어야 합니다.
이러한 사용자와의 Connection을 Process로 관리하는 것은 불가능합니다.
자원소모가 너무 클 뿐더러, 이미 Tomcat자체가 Process로 동작하기 때문입니다.
만약 사용자의 Connection을 Process로 관리한다면, Connection마다 Process생성, 제거 등을 해야 하고, Tomcat과의 Process간 통신 방식을 따로 수립해 사용해야 합니다.
Tomcat에서는 이러한 Connection을 Thread로 처리합니다.
HTTP Connection
Tomcat 9.0미만 버전에서는 IO(Input Output) Connector를 사용했습니다.
IO Connector에서는 1 Connection : 1 Thread를 할당합니다.
즉, 하나의 Connection을 관리하기 위해서는 하나의 Thread가 필요하다는 것입니다.
Tomcat 9.0이상 버전에서는 NIO(New Input Output) Connector를 사용합니다.
NIO Connector에서는 N Connection : 1 Thread방식을 사용합니다.
하나의 Thread가 여러 개의 Connection을 커버합니다.
HTTP 1.0의 keep-alive, HTTP 1.1의 지속 커넥션(마찬가지로 keep-alive긴 합니다.) 방식을 생각해봅시다.
하나의 Connection이 이뤄지고, 하나의 Request를 처리한 뒤 Connection이 끊어진다면?
HTTP Connection 설립을 위한 과정, TCP Connection 설립을 위한 과정이 모두 Overhead로 나타날 것입니다.
그래서 이러한 Overhead를 줄이기 위해 keep-alive기술을 이용해 Connection을 끊지 않고 계속 사용할 수 있습니다.
Keep-alive는 위와 같이 연결을 재설립하지 않아 Overhead를 줄이고 반응성을 향상시켜줍니다.
이것을 서버 입장에서 생각해볼 수 있습니다.
Client입장에서는 Server가 자신과의 연결을 지속시키기 때문에 장점이 클 것이지만, Server입장에서는 최대한 많은 Client를 받아야 하는데 하나의 Connection을 계속 갖고 있으니, Thread에 낭비가 발생할 수 있을 것입니다.
그래서, NIO Connector는 Nonblocking방식 통신을 지원합니다.
여러 Connection이 하나의 Thread에 의해 유지됩니다.
단, 어찌되었든 작업은 하나의 Thread를 통해 이뤄져야 하기 때문에 Selector라는 기능이 추가되었습니다.
각 Connection은 Channel로 Thread의 자원으로 유지되고, Selector가 각 Channel의 유휴 상태를 판단해 Thread자원을 할당하는 것입니다.
NIO Connector는 이러한 방식으로 Thread라는 자원을 효율적으로 사용할 수 있습니다.
Tomcat ThreadPool
이렇게 Thread를 효율적으로 사용하지만, Thread를 단순하게 관리하는 경우에도 문제가 발생할 것입니다.
따라서 Tomcat은 Connection Thread를 ThreadPool로 관리합니다.
(참고, ThreadPool : https://nangmandeveloper.tistory.com/7)
Tomcat에서 ThreadPool(Worker)에 들어가기 전 Maxconnection으로 Tomcat에 연결되는 Client의 수를 정할 수 있습니다.
또, 이 Maxconnection이 꽉 차는 경우를 대비해 Acceptcount(대기열)을 추가로 할당할 수 있습니다.
Maxconnection + Acceptcount보다 많은 수의 요청이 들어오고, ThreadPool이 가득 찼다면 다음 Request는 Reject될 것입니다.
SpringBoot에서는 Tomcat이 내장되어 있고, Tomcat ThreadPool을 튜닝할 수 있습니다.
application.yml에서 아래의 옵션을 수정하면 됩니다.
1. server.tomcat.threads.max : ThreadPool의 최대 스레드 개수입니다. Default : 200
2. server.tomcat.threads.min-spare : ThreadPool이 유지하는 최소 스레드입니다. Default : 10
3. server.tomcat.max-connections : 동시 처리 가능한 connection의 개수입니다. Default : 8192
4. server.tomcat.accept-count : acceptcount의 최대값입니다. Default : 100
max값이 너무 적으면 서버의 자원에 비해 처리하는 요청이 적을 것입니다.
min-spare값이 너무 크면 유휴 상태에도 많은 Thread를 유지해야 합니다.
두 경우 뿐 아니라, max값이 너무 큰 경우, min-spare값이 너무 적은 경우에도 문제가 발생할 것입니다.
따라서, Tomcat ThreadPool을 튜닝하는 경우 여러 테스트를 통해 최적값을 찾아야 합니다.
'WEB > Spring' 카테고리의 다른 글
[Spring] Virtual Thread, DB IO테스트시 발생했던 문제 - 1 (1) | 2024.01.21 |
---|---|
[Spring] HikariCP 알아보기 (0) | 2024.01.14 |
[Spring] Actuator (1) | 2024.01.04 |
[Spring] SpringBoot에서의 Virtual Thread (2) | 2023.12.31 |
[Spring] Jmeter로 HTTP Stress Test 진행해보기 (1) | 2023.12.27 |