본문 바로가기
make-delivery 프로젝트

[#10] Ngrinder를 이용해 성능테스트 : WAS, DB, Nginx등 서버에 병목이 있는지 확인하는 과정

by sunggook lee 2020. 12. 21.

3000명 동시 사용자 성능테스트

Ngrinder 사용이유

제가 진행했던 make-delivery라는 프로젝트는 배달앱 서버를 구축해보는 것을 목표로 진행했습니다. 제가 만든 프로젝트 서버가 성능이 어느정도 되는지 , 동시에 몇명의 사용자가 요청해도 서버가 견뎌 낼 수 있는지가 궁금했고 객관적인 지표를 얻는 테스트를 해보고 싶었습니다.

 

최종 테스트 환경

- 위 스크린샷은 최종 서버 구성에서 총 3000명의 동시 사용자 성능테스트 결과입니다.

- 네이버 클라우드 플랫폼에서 8vCPU RAM 8GB 서버를 한대 띄워 Ngrinder를 설치하였습니다.

- 배달음식점 조회 기능을 성능테스트했고 이 조회 기능은 음식 카테고리 별로 단순한 조회 쿼리 기능입니다.

- Row는 100개 정도로 테스트했고 Redis 캐시를 이용해 음식점 조회 기능을 빠르게 가능하도록 구현했습니다.

- 자바+스프링 WAS 서버 사양은 2vCPU RAM 4GB 서버 두대이고 Redis 서버 사양은 1vCPU RAM 2GB 서버 한대입니다.

 

tjdrnr05571.tistory.com/16

 

백엔드 취업준비 프로젝트를 위해 무료로 여러 대의 서버 구축하기

제가 진행했던 make-delivery라는 프로젝트는 배달앱 서버를 구축해보는 것을 목표로 진행했습니다. 사용한 서버 목록 - WAS 서버 (자바+스프링) 3대 - Mysql 서버 2대 (Master, Slave) - Redis 서버 1대 (세션,

tjdrnr05571.tistory.com

 

Ngrinder 설명 

Ngrinder는 Naver에서 만든 오픈소스이며 서버를 한대 띄워 Ngrinder를 설치하면 이 서버에서 테스트해볼 서버에 최대한의 요청을 넣어 어느 정도의 부하까지 견뎌낼 수 있는지 테스트해볼 수 있는 툴입니다. 또한 Groovy Script를 기반으로 다양한 시나리오를 작성해 성능테스트를 해볼 수 있습니다. 스크립트 생성 버튼을 누르면 예시 코드가 있으며 Groovy기반이고 Junit과 비슷한 형식이어서 젠킨스를 사용해봤거나 단위테스트를 해본 사용자라면 쉽게 구현볼 수 있습니다.

예시코드에서 자신의 코드 시나리오에 맞게 변경하여 스크립트를 작성합니다.

 

몇명의 동시사용자등 테스트 환경 설정

테스트 설정 화면에서 성능 테스트를 어느정도 규모로 할 것인지 설정합니다. 에이전트별 가상사용자에서 동시 사용자를 선택하고 성능테스트를 시작합니다. 생각보다 사용법은 간단합니다.

 

Scale Out: WAS 서버 대수를 늘려가며 성능테스트

처음 성능테스트는 2vCPU 4GB RAM 급 서버 한대에서 시작했습니다. 레디스를 이용해 캐싱을 했기 때문에 한대의 서버만으로도 1000명의 동시 사용자에서 TPS는 1800대가 나왔습니다. (캐싱을 하지 않고 Mysql에 쿼리를 날릴 경우의 TPS는 1000대가 나왔습니다)

 

 

하지만 1000명 이상으로 사용자를 늘릴수록 에러가 급증하고 서버에서 Read Time Out이 나는등 트래픽을 견뎌낼 수 없었습니다. 프로젝트 초기에 서버 설계를 할 때사용자가 늘어날 것을 대비해 서버의 대수를 늘리는 Scale Out방식을 적용하기로 결정했었습니다. 따라서 Nginx 웹서버 한대 띄워 이 웹서버를 거쳐 2vCPU 4GB RAM 서버 두대에 로드밸런싱을 하는 방식으로 서버 구조를 변경하고 성능테스트를 진행해봤습니다. 

 

서버를 두대로 Scale Out 후 동시사용자 1000명 성능 테스트

서버를 두대로 Scale Out후 동시사용자 1000명 성능테스트를 했을 시 TPS는 4152로 급증했습니다. 

 

 

Nginx서버, WAS서버 두대, Redis, Mysql서버의 CPU사용률을 성능테스트 중 리눅스 top명령어로 간단하게 체크해봤습니다. 위 그림에서 보다시피 Nginx의 CPU 사용량은 63%이고 WAS서버의 CPU는 110~120%에 그쳐있고 200%를 다 채워서 사용하지 못하고 있었습니다. 이 때 Ngrinder 서버의 사양은 4vCPU RAM 4GB였고 Ngrinder의 CPU사용률은 95%대인 것으로 미루어보아 현재 Ngrinder의 서버 사양이 낮아 WAS서버에 최대한 트래픽을 집어넣지 못하고 있는 것으로 보였습니다.

 

따라서 제 WAS서버의 성능의 최대치를 테스트해보려면 Ngrinder의 성능을 올려야겠다고 판단했습니다. 따라서 Ngrinder의 서버 사양을 8vCPU RAM 8GB로 늘려서 성능테스트를 진행했습니다.

 

 

제가 예상했던 부분이 맞았는지 Ngrinder 서버의 사양을 올리니 WAS서버의 1000명의 동시 사용자에도 TPS는 6500으로 급증가했고 평균 테스트시간도 155MS로 감소했습니다. 

 

WAS서버 두대 모두 CPU 사용량이 160%정도로 증가했고 Nginx의 CPU 사용량 또한 98%정도로 Nginx의 최대 사양을 사용하고 있는 것으로 보였습니다. 이 때 Ngrinder 서버의 CPU 사용량은 70%정도로 최대한의 부하를 서버에 주고 있지 못하는 것으로 보아 Nginx 웹 서버에서 병목이 있는 것으로 보였습니다. 따라서 최대한으로 이 프로젝트의 서버 성능을 이끌어내기 위해 Nginx 웹 서버의 사양 또한 증가시켜야 했습니다. Nginx의 원래 서버 사양은 1vCPU 2GB RAM을 사용하고 있었으나 2vCPU 2GB RAM으로 향상시켰습니다.

 

 

Nginx의 CPU를 높이고 성능테스트를 해보니 WAS 서버 두대는 여전히 CPU 사용량이 160%였고 Nginx의 CPU사용량은 59%, 57%였고 TPS는 6700으로 소폭 증가하였습니다. 이로 미루어보아 Nginx에서 큰 병목이 있었던 것은 아니고 이전엔 98%의 CPU 사용량을 가지며 최대한의 성능을 사용하고 있었던 것이었습니다. Nginx의 CPU 사용량은 98%에서 115%정도로 증가했지만 Nginx에서 병목이 있었던 것이 아니었기 때문에 WAS의 CPU사용량은 그대로였고 TPS는 소폭 증가했습니다.

 

VisualVM을 이용해 WAS서버 CPU사용 추이와 스레드, 힙 정보 모니터링

자바 WAS 서버 모니터링툴 VisualVM

VisualVM을 이용하면 자바+스프링으로 만든 WAS서버의 CPU 사용량, 힙덤프, 스레드덤프등 메모리정보, CPU정보등을 모니터링을 실시간으로 할 수 있습니다. 위 스샷에서 제가 1번, 2번 표시를 해둔 시간은 5시 12분정도로 동일한 시간입니다. 1번 그래프는 CPU사용량이고 2번 그래프는 활성화된 스레드 개수를 나타내는 그래프입니다.

 

5시 12분은 제가 Ngrinder의 성능을 향상시켜 트래픽을 최대한 서버로 넣은 시간입니다. 이에 따라 CPU사용량도 급증하였고 스레드 활성화 개수도 최대화 되었습니다. (스프링 내장 톰캣의 기본 스레드 풀 최대 개수는 200개입니다) 힙 사이즈 또한 트래픽증가 시마다 증가 되었다 줄어듭니다. Heap Size 또한 넉넉하기 때문에 GC activity는 크게 높지 않습니다.

 

위 스샷은 WAS서버에서 스레드 할당이 높은 순서를 보여줍니다. lettuce-nioEvenLoop가 가장 높은 것을 볼 수 있는데 lettuce는 스프링에서 Redis에 연결하는 클라이언트입니다. 위 성능테스트 시 레디스에서 응답을 받아오기 때문에 lettuce에 연결하는 스레드들이 가장 많은 것을 확인할 수 있습니다. (CPU 사용량도 가장 높습니다)

 

마지막으로 동시 사용자 3000명에서의 성능 테스트 결과입니다. 

 

 

동시 사용자를 3000명으로 증가시켜도 TPS는 여전히 6600대를 유지하고 있으며 WAS서버의 CPU사용량도 각각 188%,160%로 최대한의 성능을 발휘하며 트래픽을 처리하고 있는 것으로 보입니다.

 

결론

이로써 동시 사용자 몇명정도 까지 서버가 견뎌낼 수 있는지를 파악해보고 트래픽을 견디지 못하면 서버의 대수를 늘려보며 성능 테스트를 진행해봤습니다. 이 과정에서 어떠한 점들을 모니터링 해보고 주목해야하는지를 정리해봤습니다.

 

부록 - 같은 서버 구성에도 Nginx를 거치기만 해도 성능이 좋아지는 이유?

최종 서버 구성은 Nginx웹서버 한대가 WAS서버 두대에 트래픽을 나눠주는 구조이지만 성능테스트 도중 Nginx 웹서버 한대에 WAS서버 한대의 구성이 단일 WAS서버의 구성보다 훨씬 성능이 좋았습니다. 이유를 알아보기 위해 많은 검색과 질문이 있었는데 Nginx의 gzip 설정 때문에 성능이 훨씬 좋아진 것이었습니다.

 

Nginx에서 gzip설정을 할 시 json파일을 응답으로 보내줄 때 압축을 해서 보내줍니다. 이는 json의 크기가 클수록 성능이 좋아집니다. 성능 테스트시 json 응답은 row 100개정도로 적은양이 아니었기 때문에 Nginx만 추가해도 성능이 좋아지는 결과가 있었습니다. 단순 API response이기 때문에 Nginx의 정적파일 캐싱이 원인은 아니었습니다. 또한 Nginx에서 response에 micro caching을 몇초동안 지정해서 해줄 수 있지만 이 설정은 지정해주지 않았기 때문에 성능이 좋아진 원인은 아니었습니다.

 

프로젝트 url

github.com/f-lab-edu/make-delivery

 

f-lab-edu/make-delivery

구매자에게 음식 배달을 제공하는 서비스입니다. Contribute to f-lab-edu/make-delivery development by creating an account on GitHub.

github.com

 

댓글