Skip to content

성능 단위 테스트기

gaya edited this page Nov 13, 2023 · 9 revisions

부하 테스트기

개요

성능지표에 대해 알아보았으니, (링크)
이번에는 작성한 프로그램의 성능지표를 확인하기 위해 실제로 부하 테스트를 진행해보겠습니다.
서비스에 부하를 일으키켜서 부하 테스트를 진행해보았습니다.

nGrinder


nGrinder는 네이버에서 제작한 오픈소스 프로젝트로 서버의 부하 테스트를 위한 도구 입니다. Groovy, Jython 스크립트로 테스트 스크립트를 작성할 수 있고, WebUI를 통해 테스트를 실행시킬 수 있습니다.

테스트 도구라고 하면 JMeter, Gatling등 다른 유명한 소프트웨어들도 있지만,
오픈소스라 비용의 문제도 없고, 익숙한 Java와 비슷하다는 Groovy 문법으로 테스트 스크립트를 작성할 수 있는 nGrinder를 테스트 도구로 선정하였습니다.

nGrinderController, Agent로 이루어져 있습니다.

Controller는 테스트 스크립트를 작성하고, Agent에게 부하 발생 명령을 내려주는 웹 어플리케이션 서버 입니다. 또한, 테스트 프로세스 조정과 통계 등도 볼 수 있습니다.

Agent는 Controller에게 명령을 받아 테스트 하고자하는 Target 서버에 부하를 발생시킵니다.

여기서는 Docker를 사용해서 nGrinder를 설치하였습다.

구체적인 설치 방법은 링크로 대체하도록 하겠습니다.

성능 테스트

테스트 환경구성


우선 저희 시스템은 다음과 같은 환경으로 구성되어있습니다.

img
▲ [그림] at_ticket 테스트 환경구성

메인서버와 테스트 서버는 각각 다른 서버로 구성되어 있습니다.
테스트 서버에는 nGrinder가 설치되어 있고, controller와 agent로 구성되어 있습니다.

메인 서버는 테스트를 받을 Target 서버로, Target 서버 앞에는 reverse proxy역할의 ngnix를 두어 요청을 docker 컨테이너로 구성되어 있는 각각의 모듈에 전달해줍니다.

상품조회 단위 테스트


상품의 조회시에 사용되는 상품 조회 API의 단위 테스트를 해보겠습니다.

vUser수(가상 유저수를)를 500명으로 잡고 테스트를 진행하였습니다.

img

충격적인 결과가 나왔습니다.
저희 at_ticket 서비스는 vUser500기준으로 상품 조회에 초당 121건 밖에 처리할 수 없고, 테스트 요청당 4000ms의 지연시간을 가진다는 결과가 나왔습니다. 게다가 에러까지 발생하였습니다.

그런데 생각해보니 이상했습니다. 단순 조회에 4초가 걸린다니...?

원인 파악


단순 조회 기능이었기 때문에 매우 처참한 결과에 의아함을 느꼈습니다.
매우 느린 응답시간이 우리가 만든 프로그램의 문제인지, 환경 구성의 문제인지 판단을 해야 했습니다.

ngnix를 사용하지 않고, 메인 서버에 직접 테스트를 하여 보았습니다. 환경구성을 다음과 같이 변경하였습니다.

img
▲ [그림] ngnix를 사용하지 않는 환경설정

reverse proxy의 역할을 해주고 있는 nginx를 제거하고 다시 vUser를 500명으로 설정하고 테스트를 해보았습니다.

img

TPS는 1294, 테스트 요청당 391ms의 지연시간이라는 결과가 나왔습니다. 성능이 비약적으로 상승하였음을 알 수 있습니다. 에러도 전혀 없습니다.
결과적으로 프로그램 자체의 문제보다는 reverse proxy의 역할을 해주는 ngnix에서 병목 현상이 발생하고 있다고 추측할 수 있었습니다.

개선


정확한 원인 파악을 위해 ngnix를 다시 사용하도록 설정하고, 다시 부하 테스트를 진행하였습니다.

어느 부분에서 에러가 발생하기 시작하는 지 확인하기 위해 점진적으로 부하양을 늘려가며 테스트하였습니다.

img

img

테스트의 상세리포트 입니다.
00:32 분경 vUser수가 400을 넘어 갈 때 오류 수가 급격히 증가하는 것을 알 수 있었습니다. 이때의 TPS는 1057였습니다.

그리고 nGrinder의 에러로그에는 다음과 같은 에러가 출력되어 있었습니다.

org.apache.hc.core5.http.ConnectionClosedException: Connection is closed

혹시, ngnix가 1000개 이상의 커넥션을 맺지 못하는 것이 아닌가하는 추측이 들었습니다.

ngnix의 Max Connection을 2000으로 변경해 주고 다시 테스트를 해보았습니다.

결과


nginix를 다시 사용하도록 설정하고,
이번엔 vUser를 저번 테스트를 2배, 1000으로 올리고 테스트를 해보았습니다.

img TPS는 1370에 지연시간은 375, 테스트 타임 1분동안 에러는 한 건도 발생하지 않았습니다.
심각한 에러와 Lentency는 추측한대로 ngnix 설정 문제였던 것입니다.

테스트 결과를 보자면 vUser가 2배 1000명으로 증가하였음에도 500명 테스트 시 결과 TPS 1294와 별로 차이가 나지 않습니다. 포화지점에 도달했다고 볼 수 있겠습니다.

img 그라파나로 cpu사용량도 확인해보았습니다.
WAS의 CPU사용량이 90% 이상까지 도달하였음으로 현재 WAS의 최대 처리량에 거의 도달하였음을 알 수 있습니다.

우여곡절이 있었지만 저희 프로그램은 1000명의 vUser 기준 초당 약 1300 건을 약 370ms Latency로 처리하는 성능을 보여줌을 알 수 있었습니다.

하지만 이는 단위 테스트임이기에 전체 시스템의 성능이라고는 단정할 수 없고, 통합 시나리오 테스트까지 거쳐야 전체 시스템의 성능을 예상할 수 있을 것입니다.

참고


성능 테스트에 관해
https://velog.io/@sontulip/performance-test#%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B3%84%ED%9A%8D%EC%A7%9C%EA%B8%B0
https://hyuntaeknote.tistory.com/11 https://velog.io/@max9106/nGrinderPinpoint-test1

Connection Pool의 적절한 사이즈
https://colour-my-memories-blue.tistory.com/15
https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing

ngnix 설정 https://minholee93.tistory.com/entry/Nginx-Worker-Process