ngrinder를 이용한 성능 테스트 및 서버 구성하기

2022. 5. 17. 16:48 성능테스트/nGrinder

📝 ngrinder

현재 진행 중인 shoe-auction 프로젝트의 비즈니스 로직 구현이 90% 이상 완료되었습니다. 현재 Naver Cloud Platform으로 프로젝트의 인프라 환경을 구축해놓은 상태에서 성능 테스트 지표를 이용해 Scale-out 방식으로 서버 확장을 진행해보려고 합니다.

 

성능 테스트 툴은 네이버에서 만든 ngrinder 사용해서 진행하였습니다. 심플한 UI를 제공하기 때문에 초보자도 쉽게 사용할 수 있고 테스트 결과도 결과 보고서를 통해 한눈에 알아볼 수 있어서 국내에서 많이 사용되고 있습니다.

설치 방법은 이전 ​글을 참고해주세요.

📝 사용 방법

가장 먼저 성능테스트를 위한 스크립트를 작성해야 합니다. ngrinder 메인 화면에서 스크립트 생성 화면으로 이동합니다.

 

성능 테스트를 원하는 URL 입력하고, 아래 사진처럼 body에 데이터를 넣어서 보낼수도 있습니다.

자동으로 만들어진 groovy 코드를 환경에 맞게 적절히 수정하고 오른쪽 상단에 [검증] 버튼을 눌러 정상적으로 작동하는지 확인하고 저장버튼을 클릭합니다.

 

스크립트문 작성이 완료되었으면 성능 테스트 페이지로 이동해 테스트 생성 버튼을 클릭합니다.

에이전트 수를 입력하고, 몇 명의 가상 사용자로 부하 테스트를 진행할지 선택합니다. 또한 비교적 정확한 평균 수치를 산출해내기 위해 테스트 기간은 10분 이상으로 잡는 걸 추천드립니다.

모든 설정을 완료하고 오른쪽 상단에 [저장 후 시작] 버튼을 클릭하면 테스트가 시작됩니다.

 

주의사항

성능 테스트 시 기본적으로 Agent는 12000~ port를 이용하기 때문에 해당 포트 번호를 사전에 열어놓아야 합니다.

📝 테스트 진행 - 단일 서버 환경

이제 본격적으로 성능테스트를 진행해보겠습니다. 초기 서버 구성은 [Compact] 1vCPU, 2GB Mem, 50GB 급 WAS 서버 1대와 Master/Slave로 구성된 동일한 스펙의 MySQL 서버로 이루어져 있습니다.

1. 로그인 테스트

가장 먼저 로그인 테스트를 진행해보겠습니다.

위 테스트는 가상 사용자 1000명을 기준으로 진행한 테스트입니다. 초당 처리 가능한 요청인 TPS는 평균 632 정도가 나왔고, 지연 시간은 1500ms 정도가 나왔습니다. 또한 해당 서버의 CPU 사용량 조회 결과 약 90% 이상을 점유하고 있었습니다.

하지만 테스트 성공률이 100%였기 때문에 이번에는 가상 사용자를 3000명 투입시켜 테스트를 진행해보았습니다.

 

테스트 결과 TPS는 1000명의 가상유저를 투입했을때와 비슷하지만 지연시간과 에러 발생률이 증가한 것을 확인할 수 있었습니다. 또한 WAS의 CPU 사용률을 조회해본 결과 거의 100%에 육박하는 사용률을 보이고 있었습니다. 따라서 적절한 조치가 필요하다고 생각했습니다.

 

2. 상품 조회 테스트

다음으로 해당 프로젝트에서 가장 많은 트래픽이 발생될 것으로 예상되는 상품 조회 기능을 테스트해보겠습니다. 해당 테스트는 단일 WAS 서버에서 캐시를 저장하기 전과 후의 수치를 비교해볼 예정입니다.

캐시 사용 전의 서버 구성을 간략하게 표현하자면 아래와 같습니다.

먼저 동일한 서버 스펙 기준으로 물품 조회시 캐시를 적용하지 않은 상태에서 3000명의 가상사용자를 투입한 테스트 결과입니다.

평균 TPS는 500정도를 보이고 있으며 약 5200ms의 지연시간과 에러 발생 확률도 1% 이상으로 상당히 불안정한 모습을 보이고 있었습니다.

 

다음으로 동일 환경에 Redis를 이용한 캐시 서버를 추가로 구축하고 물품 조회 로직에 캐싱 기능을 추가한 후 테스트를 진행해보았습니다. 캐시를 저장한 간단한 서버 구조는 아래와 같습니다.

마찬가지로 3000명의 가상사용자를 기준으로 성능테스트를 진행해보았습니다.

캐시를 사용하기 전과 후의 성능 지표 차이를 살펴보면 TPS는 약 5배 정도 증가하였고, 지연 시간 또한 5배 정도 감소하였습니다. 또한 에러 발생률도 0.01% 미만으로 감소한 것을 확인할 수 있었습니다.

 

물론 실제 운영 환경에서는 해당 Product(물품)에 대한 Trade(거래)가 추가될 때마다 캐시 만료(CacheEvict)가 발생하기 때문에 위 성능 지표보다는 조금 낮은 성능을 보일 것으로 예상됩니다.

📝 테스트 진행 - nginx를 통한 로드벨런싱

위에서 단일 서버 환경으로 테스트를 진행해본 결과 비교적 간단한 로직인 로그인 테스트에서 3000명 이상의 동시 사용자가 발생할 경우 상당히 불안정한 모습을 보인 것을 확인할 수 있었습니다.

 

따라서 nginx 웹서버를 띄우고 하나의 WAS를 더 추가시켜 로드밸런싱을 통해 적절하게 부하를 분산시키도록 Scale-out방식으로 서버 확장을 진행하였습니다.

 

해당 프로젝트는 초기 설계 시 Scale-out 방식으로 서버를 확장할 수 있는 환경을 구성했기 때문에 비교적 간단하게 서버를 확장시킬 수 있었습니다.

 

nginx를 이용한 로드밸런싱 방법은 아래 포스팅을 참고해 주세요.

 

[Server] Nginx를 이용해 로드밸런싱(Load Balancing) 구현하고 HTTPS 적용하기

 현재 진행중인 프로젝트 shoe-auction은 지속적인 사용자 증가를 가정하고 진행하였기 때문에 확장성의 한계가 적은 Scale-out 방식의 확장을 채택하였다. 따라서 2개 이상의 WAS를 두고 있고, Session

kerobero.tistory.com

 

로그인 테스트

단일 서버 환경에서 3000명 이상이 접근했을때 서버가 불안정한 상태를 보이는것을 확인할 수 있었습니다. 이번에는 웹서버를 거쳐 2개의 서버로 부하를 분산시켰을 때 성능 지표가 어떻게 변경되었는지 알아보겠습니다.

테스트 결과 단일 서버 환경에서보다 모든 면에서 향상된 지표를 보였습니다. 특히 눈에 띄는 것은 평균 테스트 시간이 4400ms에서 약 300ms로 감소했다는 점과 평균 TPS도 거의 20배 가깝게 증가했다는 점 입니다.

또한 nginx의 CPU 사용률을 조회한 결과 50~60% 정도로, 3000명울 초과하는 환경에서도 비교적 안정적으로 서버 운영이 가능하다는 점을 예상할 수 있었습니다.

 

하지만 해당 지표는 어디까지나 로그인에 대한 성능 테스트 지표입니다. 대부분의 애플리케이션 사용자가 로그인만 하고 아무런 활동도 안하는 경우는 드물기 때문에 정확한 성능 테스트 지표가 될수는 없다고 생각했습니다.

상품 조회 테스트

서버 확장이 진행된 상태에서 위와 동일하게 Redis를 이용한 캐싱 기능을 적용한 상태로 상품 조회 성능 테스트를 진행해보았습니다.

평균 TPS가 12000까지 증가하였고, 평균 테스트 시간 또한 약 240ms로 감소하였습니다. 또한 해당 테스트가 진행되는 동안 nginx의 CPU 사용률을 살펴본 결과 약 60% 정도로 매우 안정적인 성능을 보였습니다.

 

로그인 -> 상품 검색 -> 상품 조회 테스트

마지막으로, 이번 프로젝트에서 가장 빈번하게 사용될 것으로 예상되는 로직을 묶어서 성능 테스트를 진행해보았습니다. 과정은 대략 아래 그림과 비슷할 것으로 예상됩니다. (로그인 -> 상품 검색 -> 상품 조회)

마찬가지로 웹서버를 거쳐 2대의 WAS에 라운드로빈 방식으로 로드밸런싱이 진행되는 방식이며, 캐싱 또한 적용된 상태입니다.

사전에 3000명의 가상 사용자로 테스트를 진행해본 결과 nginx의 CPU사용률이 평균 98%~100%을 기록했습니다. 따라서 2000명을 기준으로 테스트를 진행해보겠습니다.

테스트 결과 평균 TPS는 5600, 평균 테스트 시간은  340ms 정도가 나왔습니다. 하지만 앞에서도 언급했듯이 상품과 연관되어 있는 Trade가 추가될 때마다 캐시가 만료되기 때문에 실제 운영 환경에서는 해당 성능 테스트 결과에서 보인 퍼포먼스보다는 조금 더 낮은 성능을 보이게 될 것입니다.

 

이번 프로젝트의 모티브가 된 애플리케이션을 조사해본 결과, 새로운 한정판 스니커즈 발매일을 제외하고는 Trade가 추가되는 경우가 그렇게 많지는 않은 것을 확인할 수 있었습니다. 또한 비인기 상품의 경우에는 새로운 Trade 생성이 매우 드물게 일어나기 때문에 서비스 오픈 초기 기준으로 이번 성능 테스트 지표와 엄청나게 큰 차이를 보이지는 않을 것으로 예상됩니다.

 

📝 서버 구성

이번 프로젝트에서 서버 구성은 AWS S3와 Lambda를 제외하고 모두 네이버 클라우드 플랫폼을 이용해서 구성하였습니다.

1. Redis Server

성능 테스트 결과 Cache의 적용 여부에 따라 엄청난 성능 차이를 보이는 것을 확인할 수 있었습니다. 따라서 Redis 서버를 각 기능별로 분리시켜 효율적인 메모리 관리를 통해 캐시 저장소의 가용성을 잘 유지해야 합니다. 이번 프로젝트에서는 총3개의 캐시 서버를 용도별로 분리시켰습니다.

 FCM 토큰 저장소 : [Compact] 1vCPU, 2GB Mem, 50GB Disk

 Login Session 저장소 : [Compact] 1vCPU, 2GB Mem, 50GB Disk

 캐시 데이터 저장소 : [Compact] 1vCPU, 2GB Mem, 50GB Disk

2. WAS

로그인 테스트에서 3000명의 사용자 접속 시 불안정한 성능지표를 보였습니다. 따라서 기존에 WAS 1대만 이용하던 방식에서 웹서버 nginx와 WAS1대를 추가로 띄어서 로드밸런싱을 통한 부하 분산이 가능하도록 서버 구성을 변경하였습니다.

 WAS 1 : [Compact] 1vCPU, 2GB Mem, 50GB Disk

 WAS 2 : [Compact] 1vCPU, 2GB Mem, 50GB Disk

 nginx :  [Standard] 2vCPU , 4GB Mem, 50GB Disk

3. MySQL

성능 테스트 이전에 DB에서 발생하는 병목현상을 개선하고자 사전에 Master/Slave 구조의 Replication을 구성했었습니다. 일단 Slave서버는 1개만 구성하였고, Master 서버와 Slave 서버 모두 동일한 스펙의 서버를 사용했습니다. (기본적으로 Master서버는 Slave 서버 스펙과 동일하거나 더 높게 구성해야 합니다.)

 MySQL Master : [Compact] 1vCPU, 2GB Mem, 50GB Disk

 MySQL Slave : [Compact] 1vCPU, 2GB Mem, 50GB Disk

4. Jenkins

처음 Jenkins 서버를 띄었을 때는 NCP에서 1년간 무료로 사용할 수 있는 micro 서버를 사용했었습니다. git push 또는 pull request가 발생 할 때마다 자동 테스트와 빌드가 진행되도록 설정했었는데, 테스트가 진행될 때마다 20분에서 최대 1시간까지 걸리고 심할 경우 Timeout으로 인해 빌드가 실패하는 문제가 생겼습니다. 따라서 Jenkins 서버의 스펙은 다른 서버들보다 조금 더 높은 사양을 선택했습니다.

 Jenkins : [Standard] 2vCPU , 4GB Mem, 50GB Disk

5. AWS S3 & Lambda

프로젝트에 사용되는 이미지를 저장하기 위해 AWS S3와, 이미지 리사이징을 위해 AWS Lambda를 선택했습니다. 해당 프로젝트에서 이미지를 업로드할 수 있는 사용자는 관리자 뿐이기 때문에 사용량이 그리 높지 않을 것이라고 판단했습니다. 추후 커뮤니티성 게시판을 추가 구현한다면 해당 서버 스펙도 Sacle -UP을 진행할 예정입니다.

 AWS S3 & Lambda : AWS 프리 티어 (이미지 저장 기본 50GB, Lambda 월별 무료요청 100만)

6. ngrinder

최대한 정확한 테스트 결과 지표를 얻기 위해 Controller와 Agent, 그리고 테스트 Target이 되는 Server를 모두 각각 띄어서 성능 테스트를 진행하였습니다. Controller의 명령을 받아 Agent에서 실제 부하를 발생시키기 때문에 Agent의 서버 스펙을 가장 높게 구성하였습니다.

 Controller server : [Standard] 2vCPU, 4GB Mem, 50GB Disk

 Agent server : [Standard] 4vCPU, 8GB Mem, 50GB Disk


Shoe-auction 1차 서버 구조도

현재까지 완성된 서버 구조는 위 그림과 같습니다. 아직 docker에 대한 학습이 부족해서 docker를 이용하지 않고 직접 하나하나 서버를 띄우는 방식으로 진행해보았습니다. 추후 도커 관련 학습이 어느 정도 완료되면 도커 이미지를 통한 배포 과정을 추가할 예정입니다.

 

출처 : https://1-7171771.tistory.com/155

'성능테스트 > nGrinder' 카테고리의 다른 글

<HEADER, COOKIES, PARAM> 스크립트  (0) 2022.06.10
리눅스 서버에 nGrinder 설치하기  (0) 2022.05.17