-
Spring MVC Stack - Tomcat Thread Pool 성능 테스트Spring 2023. 6. 9. 16:20
Spring MVC Stack을 사용하는 경우의 기본 WAS 인 TOMCAT 9의 설정 변경을 통해
WAS의 성능 검증 및 EKS POD Spec에 따른 적절한 설정 값을 찾기 위해 진행한 테스트 입니다.Spring Embedded Tomcat 9 - Default Config Info's
- max-thread: 생성할 수 있는 thread의 총 개수.default 200
- min-spare: 항상 활성화 되어있는(idle) thread의 개수. default 10
- max-connections : 수립가능한 connection의 총 개수. default 8192
- accept-count: 작업큐의 사이즈(max-connections 이후에 추가로 받을 연결 수). default 100
- connection-timeout: connection-timeout: 20000 # timeout 판단 기준 시간, 20초
참고 : https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html
TEST Target API’s
- EVENT-API : 이벤트 다운로드 가능 여부 API
TEST CASE's
TEST 1 - Default Tomcat 설정 적용
- 테스트 환경
- 개발 Ngrinder
- agent(core 2, mem 2gb): 10 대
- 총 Vuser : 100 (process 2, thread 5)
- ramp-up : true
- test duration : 3분
- event-api : 4대 고정 (core 2, mem 4gb, heap 2gb)
- Tomcat
- threads.max : 200
- threads.min-spare : 10
- accept-count : 100
- max-connections : 8192
- 개발 Ngrinder
- 결과
- TPS : 1831
- 실행 테스트 : 322,499 건
- 평균 테스트 시간 : 48.44 ms
TEST 2 - Default Tomcat 설정 적용 + 부하 증가(VUser 300)
- 테스트 환경
- 개발 Ngrinder
- agent(core 2, mem 2gb): 10 대
- vuser : 300 (process 2, thread 15)
- ramp-up : true
- test duration : 3분
- event-api : 4대 고정 (core 2, mem 4gb, heap 2gb)
- Tomcat
- threads.max : 200
- threads.min-spare : 10
- accept-count : 100
- max-connections : 8192
- 개발 Ngrinder
- 결과
- TPS : 2730
- 실행 테스트 : 480,759 건
- 평균 테스트 시간 : 108.59 ms
TEST 3 - Max Thread 400, IDLE 100
- 테스트 환경
- 개발 Ngrinder
- agent(core 2, mem 2gb): 10 대
- vuser : 100 (process 2, thread 5)
- ramp-up : true
- test duration : 3분
- event-api : 4대 고정 (core 2, mem 4gb, heap 2gb)
- Tomcat
- threads.max : 400
- threads.min-spare : 100
- accept-count : 100
- max-connections : 8192
- 개발 Ngrinder
- 결과
- TPS : 2612
- 실행 테스트 : 459,878 건
- 평균 테스트 시간 : 37.90 ms
TEST 4 - Max Thread 400, IDLE 100 + 부하 증가(VUser 300)
- 테스트 환경
- 개발 Ngrinder
- agent(core 2, mem 2gb): 10 대
- vuser : 300 (process 2, thread 15)
- ramp-up : true
- test duration : 3분
- event-api : 4대 고정 (core 2, mem 4gb, heap 2gb)
- Tomcat
- threads.max : 400
- threads.min-spare : 100
- accept-count : 100
- max-connections : 8192
- 개발 Ngrinder
- 결과
- TPS : 2532
- 실행 테스트 : 445,729 건
- 평균 테스트 시간 : 106.89 ms
TEST 5 - Max Thread 400, IDLE 200
- 테스트 환경
- 개발 Ngrinder
- agent(core 2, mem 2gb): 10 대
- vuser : 300 (process 2, thread 15)
- ramp-up : true
- test duration : 3분
- event-api : 4대 고정 (core 2, mem 4gb, heap 2gb)
- Tomcat
- threads.max : 400
- threads.min-spare : 200
- accept-count : 100
- max-connections : 8192
- 개발 Ngrinder
- 결과
- TPS : 2506
- 실행 테스트 : 441,286 건
- 평균 테스트 시간 : 118.82 ms
TEST 6 - Max Thread 400, IDLE 200 + POD 스케일업
- 테스트 환경
- 개발 Ngrinder
- agent(core 2, mem 2gb): 10 대
- vuser : 300 (process 2, thread 15)
- ramp-up : true
- test duration : 3분
- event-api : 4대 고정 (core 4, mem 8gb, heap 4gb)
- Tomcat
- threads.max : 400
- threads.min-spare : 200
- accept-count : 100
- max-connections : 8192
- 개발 Ngrinder
- 결과
- TPS : 3356
- 실행 테스트 : 590,987 건
- 평균 테스트 시간 : 88.70 ms
TEST 7 - Max Thread 400, IDLE 200 + POD 스케일업 + 부하 증가(VUser 500)
- 테스트 환경
- 개발 Ngrinder
- agent(core 2, mem 2gb): 10 대
- vuser : 500 (process 2, thread 25)
- ramp-up : true
- test duration : 3분
- event-api : 4대 고정 (core 4, mem 8gb, heap 4gb)
- Tomcat
- threads.max : 400
- threads.min-spare : 200
- accept-count : 100
- max-connections : 8192
- 개발 Ngrinder
- 결과
- TPS : 3358
- 실행 테스트 : 591,245 건
- 평균 테스트 시간 : 147.69 ms
TEST 8 - Max Thread 800, IDLE 400
- 테스트 환경
- 개발 Ngrinder
- agent(core 2, mem 2gb): 10 대
- vuser : 500 (process 2, thread 25)
- ramp-up : true
- test duration : 3분
- event-api : 4대 고정 (core 4, mem 8gb, heap 4gb)
- Tomcat
- threads.max : 800
- threads.min-spare : 400
- accept-count : 100
- max-connections : 8192
- 개발 Ngrinder
- 결과
- TPS : 3132
- 실행 테스트 : 591,407 건
- 평균 테스트 시간 : 158.42 ms
-
JVM 최대 쓰레드 개수 561개
- 최대 쓰레드 개수인 800개까지 생성되지는 않는 부하라고 판단됨
TEST 9 - Max Thread 800, IDLE 400 + 부하 증가(VUser 800)
- 테스트 환경
- 개발 Ngrinder
- agent(core 2, mem 2gb): 10 대
- vuser : 800 (process 2, thread 40)
- ramp-up : true
- test duration : 3분
- event-api : 4대 고정 (core 4, mem 8gb, heap 4gb)
- Tomcat
- threads.max : 800
- threads.min-spare : 400
- accept-count : 100
- max-connections : 8192
- 개발 Ngrinder
- 결과
- TPS : 3190
- 실행 테스트 : 561,591 건
- 평균 테스트 시간 : 249.23 ms
-
JVM 최대 쓰레드 개수 860개
- 최대 쓰레드 개수인 800 + 기본 쓰레드를 포함한 860개 달성
POD 4대 중에 1대만 쓰레드 최대 개수를 달성하여, 부하를 증가시켜 나머지 POD 의 쓰레드 개수도 증가시켜 해당 POD 개수 및 Spec 기준 가능 트래픽 확인을 추가로 진행 했습니다.
TEST 10 - Max Thread 800, IDLE 400 + 부하 증가(VUser 1200)
- 테스트 환경
- 개발 Ngrinder
- agent(core 2, mem 2gb): 10 대
- vuser : 1200 (process 2, thread 40)
- ramp-up : true
- test duration : 3분
- event-api : 4대 고정 (core 4, mem 8gb, heap 4gb)
- Tomcat
- threads.max : 800
- threads.min-spare : 400
- accept-count : 100
- max-connections : 8192
- 개발 Ngrinder
- 결과
- TPS : 2968
- 실행 테스트 : 522,577 건
- 평균 테스트 시간 : 334.45 ms
-
JVM 최대 쓰레드 개수 864개
- 최대 쓰레드 개수인 800 + 기본 쓰레드를 포함한 864개 달성
TEST 11 - Max Thread 800, IDLE 400 + 부하 증가(VUser 2800)
- 테스트 환경
- 개발 Ngrinder
- agent(core 2, mem 2gb): 10 대
- vuser : 1200 (process 2, thread 40)
- ramp-up : true
- test duration : 3분
- event-api : 4대 고정 (core 4, mem 8gb, heap 4gb)
- Tomcat
- threads.max : 800
- threads.min-spare : 400
- accept-count : 100
- max-connections : 8192
- 개발 Ngrinder
- 결과
- TPS : 2678
- 실행 테스트 : 466,148 건
- 평균 테스트 시간 : 337.75 ms
-
JVM 최대 쓰레드 개수 831개
-
POD CPU 최대 평균 53.7
- 최대 쓰레드 개수인 800 + 기본 쓰레드를 포함한 831개에 도달 하였고, POD CPU/MEMORY 또한 증가는 하였지만 HPA 를 발동하는 CPU 평균 60%이상이 아님을 확인 하였습니다.
테스트 요약
- POD 4대 고정 (core 4, mem 8gb, heap 4gb) + Tomcat 최대/최소 쓰레드 개수 : 800/400 으로 설정시에 VUser 1,200명 기준 5분간 46만건의 요청을 300ms 이내에 처리가 가능함을 확인 하였습니다.
NO 테스트 명 VUser TPS 처리 수 평균 테스트 시간(ms) Thread Max 개수 Thread Idle 개수 POD Spec 1 Default Tomcat 설정 적용 100 1831 322,499 48.44 200 10 4대 고정 (core 2, mem 4gb, heap 2gb) 2 Default Tomcat 설정 적용 + 부하 증가(VUser 300) 300 2730 480,759 108.59 200 10 4대 고정 (core 2, mem 4gb, heap 2gb) 3 Max Thread 400, IDLE 100 100 2612 459,878 37.90 400 100 4대 고정 (core 2, mem 4gb, heap 2gb) 4 Max Thread 400, IDLE 100 + 부하 증가(VUser 300) 300 2532 445,729 106.89 400 100 4대 고정 (core 2, mem 4gb, heap 2gb) 5 Max Thread 400, IDLE 200 300 2506 441,286 118.82 400 200 4대 고정 (core 2, mem 4gb, heap 2gb) 6 Max Thread 400, IDLE 200 + POD 스케일업 300 3356 590,987 88.70 400 200 4대 고정 (core 4, mem 8gb, heap 4gb) 7 Max Thread 400, IDLE 200 + POD 스케일업 + 부하 증가(VUser 500) 500 3358 591,245 147.69 400 200 4대 고정 (core 4, mem 8gb, heap 4gb) 8 Max Thread 800, IDLE 400 500 3132 591,407 158.42 800 400 4대 고정 (core 4, mem 8gb, heap 4gb) 9 Max Thread 800, IDLE 400 + 부하 증가(VUser 800) 800 3190 561,591 249.23 800 400 4대 고정 (core 4, mem 8gb, heap 4gb) 10 Max Thread 800, IDLE 400 + 부하 증가(VUser 1200) 1200 2968 522,577 334.45 800 400 4대 고정 (core 4, mem 8gb, heap 4gb) 11 Max Thread 800, IDLE 400 + 부하 증가(VUser 2800) 2800 2678 466,148 337.75 800 400 4대 고정 (core 4, mem 8gb, heap 4gb) 마치며
위의 테스트를 통해 WAS 쓰레드 Max/Idle 개수 조정 및 부하 증가를 통해 요청 트래픽이 증가함에도 3000대의 TPS를 유지하며
요청 처리수의 증가를 확인하여 WAS 설정 변경시에 성능 향상을 확인하였습니다.다만 평균 응답 시간은 100ms 단위로 증가되었지만, 이는 순간 트래픽이 몰리는 API 성격 상, 보다 많은 요청을 처리하는 것을 목표를 했을때에는 크게 무리 없는 응답 시간의 증가로 판단됩니다.
WAS 설정 중 쓰레드 풀의 IDLE 개수 server.tomcat.threads.min-spare 의 개수를 증가 시킴으로서 미리 유휴한 쓰레드 개수를 확보하여, 순간 들어오는 트래픽에 대응하는 방법을 권장하며, 최고 트래픽 순간 이후에는 다시 IDLE 개수를 조정하여 유휴 쓰레드 개수를 조정하여 배포바랍니다.
그리고 MAX 쓰레드 개수 server.tomcat.threads.max 의 개수를 증가시켜 순간 들어오는 트래픽 뿐만 아니라 지속적으로 유지되는 트래픽에 대응이 가능 할 것으로 보이며, POD 및 JVM 리소스를 모니터링 하여 최대 쓰레드 개수를 지정하시기 바랍니다.
만약 WAS 기본 값으로 운영하게 되면 실제 POD의 CPU/MEMORY 자원을 100% 효율 적으로 사용하지 못하며, 순간 트래픽에 따른 응답 시간 지연 및 5xx 대의 응답이 예상됩니다.
사전에 TPS 목표/임계치, 적절한 POD 개수/Spec(CPU/MEM)을 설정하고 부하 테스트를 통해 적절한 WAS 설정값을 찾고 실제 상용 트래픽에 대응할 수 있기를 바랍니다.
'Spring' 카테고리의 다른 글
Spring MVC Stack - WebFlux/WebClient Logging with Reactor Context + MDC (3) 2021.05.21 Spring MVC Stack - Logging With AOP + MDC (0) 2021.04.14 Spring MVC Controller - Header(@RequestHeader) Validation 처리 (0) 2020.05.22 Spring/Java - ModelMapper 사용시 Source Object null 케이스 처리 방법 (0) 2020.02.13