프로젝트/Ticketing

[Ticketing] nGrinder를 통한 부하 테스트

이덩우 2024. 6. 20. 00:50

완성된 백엔드 배포 환경에 대해서 서버가 얼마나 버텨줄 수 있을지 테스트 해보기로했습니다.

DB Connection을 한 번 가지는 테스트로 진행했습니다.

ECS Fargate 컨테이너 스펙 : 1vCPU, 3GB Memory

 

1. API Gateway로 요청

ECS 클러스터 내 컨테이너를 1개 띄웠을 경우와 2개 띄웠을 경우를 테스트하며 결과를 비교해봤습니다.

가상 유저 수는 10, 50, 100, 200, 400, 800, 2000 순으로 차례대로 늘려가며 테스트 했습니다.

컨테이너 수 = 1
컨테이너 수 = 2

 

                               1대의 컨테이너                                   2대의 컨테이너
Vusers TPS MTT Err Rate TPS MTT Err Rate
10 83.4 119.5 0.0% 89.1 111.3 0.0%
50 324.1 153.4 0.0% 343.6 144.7 0.0%
100 436.6 224.1 0.0% 430.8 227.2 0.0%
200 520.7 369.9 0.0% 525.7 365.4 0.0%
400 539.1 712.3 0.0% 538.5 706.8 0.0%
800 545.3 1,380.3 0.0% 542.5 1,392.5 0.0%
2000 507.9 3,577.0 0.0% 503.6 3,563.7 0.0%

 

1 container VS 2 container

 

서버의 수는 늘었지만 이상하게 *TPS 및 MTT는 거의 동일했습니다.*

TPS의 상한선인 Saturation Point는 가상 유저 수 200명을 기점으로 대략 500~600 수준을 보이는 모습입니다.

 

스케일 아웃의 효과를 보지 못한 것이데요, 로드 밸런싱이 동작하지 않은 것일까요?

한 대의 컨테이너를 시작으로 최대 5대의 컨테이너까지 동작시키며 실제로 모든 컨테이너에 DB 통신 로그가 남는지와 평균 CPU 사용량을 확인해봤으나 모두 정상적으로 부하 분산이 발생하고 있었습니다.

컨테이너 수를 늘릴 수록 평균 CPU 사용률이 떨어지는 모습

 

API Gateway의 문제일까요? API Gateway를 건너뛰고 ALB로 직접 요청을 보내보겠습니다.

2. Application Load Balancer로 요청

컨테이너 수 = 1
컨테이너 수 = 2

 

                               1대의 컨테이너                                   2대의 컨테이너
Vusers TPS MTT Err Rate TPS MTT Err Rate
10 140.7 70.5 0.0% 150.0 66.3 0.0%
50 610.3 82.2 0.0% 697.3 70.8 0.0%
100 801.6 122.4 0.0% 1066.4 91.1 0.0%
200 765.3 252.1 0.0% 1213.9 158.4 0.0%
400 774.0 494.7 0.0% 1245.5 306.6 0.0%
800 717.0 1,070.4 0.0% 1247.2 599.7 0.0%
2000 752.2 2554.9 0.0% 1279.7 1,318.8 0.0%

 

1 container VS 2 container

 

ALB 요청 수 2배 증가



이제서야 스케일 아웃의 효과를 확인할 수 있습니다.

서버 수를 두 배로 늘렸을 때, MAX 유저 수로 다가갈수록 MTT(응답 속도)가 두 배에 가까워짐을 확인할 수 있고 TPS 또한 증가했습니다.

 

또한 동일한 컨테이너 수에서의 TPS도 증가했습니다. API Gateway를 사용하는 경우, 스케일 아웃과 상관없이 포화 지점에서 500~600 대의 TPS를 보여줬지만, ALB로 요청을 바로 보내는 경우 1대의 컨테이너로 운영하더라도 포화 지점에서 700대의 TPS를 보여주고 있습니다.

TPS가 증가한 원인은 API Gateway를 거치는 네트워크 비용이 사라졌기 때문이지 아닐까 생각합니다.

 

 

API Gateway를 통해 통신하면 스케일 아웃의 효과를 볼 수 없는 이유가 뭘까요? 다양한 환경에서 실험해봤습니다.

 

 

3. API Gateway 문제 원인 분석

- 트래픽 제한?

AWS API Gateway 측의 트래픽 제한이 있나 찾아봤습니다.

제가 사용하는 HTTP API 유형의 경우 초당 10,000개의 트래픽을 허용한다는 공식 문서의 자료가 있었지만, 테스트 결과로 보이는 500 ~ 600 TPS 와는 다소 거리감이 있었습니다.

 

그래도 직접 수동으로 설정을 변경해 다시 테스트해봤지만 소용이 없었습니다..

Throttling 설정

 

 

다음으로는 직접 Usage Plan을 생성해 사용량을 제한해봤습니다.

동일한 클라이언트에게서 오는 트래픽을 제한하나 싶어 할당량을 대폭 늘렸습니다.

Usage Plan 설정

이 역시도 소용이 없었습니다..

 

- HTTP API 유형의 문제?

현제 사용하는 HTTP API 유형의 게이트웨이는 REST API 유형에 비해 간단하게 생성하고 사용할 수 있습니다.

공식 문서 어디에서도 HTTP API 유형의 트래픽 제한 내용은 없었지만,, REST API 유형을 새로 생성하고 테스트해봤습니다.

테스트 결과

 

문제가 해결되지 않았습니다.

 

 

- 문제는 어디에?

로드 밸런서로 직접 요청을 보낸 경우에는 스케일 아웃의 효과가 나타납니다.

하지만 API Gateway로 요청을 보낸 경우 최대 TPS가 500 수준으로 제한이 있는 것으로 보아,

저는 API Gateway측의 문제, 혹은 API Gateway와 로드 밸런서간 통신 문제라고 생각해 문제점을 찾아봤지만..

글을 작성하는 현재 시점까지는 문제를 해결하지 못했습니다. (약 2주간 문제를 해결하지 못하고 있네요..)

꼭 해결해서 포스팅을 수정하도록 하겠습니다!

 

4. 결론

로드 밸런서로 직접 요청을 보낸 결과를 다시 가져오겠습니다.

                               1대의 컨테이너                                   2대의 컨테이너
Vusers TPS MTT Err Rate TPS MTT Err Rate
10 140.7 70.5 0.0% 150.0 66.3 0.0%
50 610.3 82.2 0.0% 697.3 70.8 0.0%
100 801.6 122.4 0.0% 1066.4 91.1 0.0%
200 765.3 252.1 0.0% 1213.9 158.4 0.0%
400 774.0 494.7 0.0% 1245.5 306.6 0.0%
800 717.0 1,070.4 0.0% 1247.2 599.7 0.0%
2000 752.2 2554.9 0.0% 1279.7 1,318.8 0.0%

 

가상 유저 수 2000명인 경우를 살펴보면 유저가 느끼는 응답 속도는 컨테이너를 1대, 2대 운영했을 때 각각 2.5초, 1.3초 수준입니다.

한 번의 API 요청에 수 초가 걸린다는 것은 굉장히 불편한 경험일 것입니다.

 

따라서 현재 서비스 아키텍처에서 대처 가능한 방법으로 떠올린 것은 다음과 같습니다. 

 

- 컨테이너 평균 CPU 사용량 기반의 오토 스케일링 구성

컨테이너 수를 늘릴 수록 평균 CPU 사용률이 떨어지는 모습

 

가상 유저 수 2000명을 기준으로 했을 때 결과입니다. 

평균 CPU 사용률을 보아할 때 두 대의 컨테이너를 띄워도 약간 버거워 하는 모습을 보입니다. 하지만 5대는 과한 모습이네요.

 

저는 평균 CPU 사용률 50%를 기준으로 잡고 자유로운 스케일이 가능하도록 해보았습니다.

 

1. 대상 추적 조정 정책

ECS 오토 스케일링 설정 - 대상 추적

 

위 설정을 통해 순간적인 트래픽으로 테스트 한 결과, 실제로 서버 수가 늘어날 때 까지 5분 정도 소요되었습니다.

5분이라는 다운타임은 실제로 큰 영향을 미칠텐데요, 이유가 무엇일까요? CloudWatch를 살펴봤습니다.

자동으로 생성된 CloudWatch 경보

 

이전 ECS 오토 스케일링 설정으로 자동으로 생성된 Cloudwatch 경보입니다. 

경보 조건을 보면 *3분 내 3개의 데이터 포인트에 대한 평균 CPU 사용률이 50%* 가 넘어야 발생한다고 나와있습니다.

거기에 ECS -> CloudWatch로 지표를 1분마다 전송해주는게 원칙이 존재했습니다.

컨테이너가 띄워지는 시간까지 고려해 총 5분정도의 시간이 소요된 것입니다. 

 

ECS -> CloudWatch로 지표를 1분마다 전송하는 것은 엔지니어가 줄일 수 있는 영역이 아니니, 저는 대신 기존의 3분이라는 시간을 줄이기로 했습니다. 

 

2. 단계 조정 정책

자동으로 생성된 경보에 대해서 3분이라는 시간을 편집할 수 없었는데요, 

그래서 직접 더 짧은 시간 단위의 경보를 직접 생성하고 단계별로 적용할 수 있는 단계 조정 정책을 통해 오토 스케일링을 적용해보기로 했습니다.

 

먼저 경보를 생성해보겠습니다.

경보 생성

이전과 달리 직접 시간을 제어할 수 있습니다.

 

단계 조정 정책 생성

 

평균 CPU 사용률이 50 ~ 70%인 경우 하나의 컨테이너를 추가 실행하고 그 이상인 경우 두개의 컨테이너를 즉시 추가 실행하도록 설정했습니다.

이를 통해 대상 추적 정책을 사용할 때 보다 빠른 속도로 스케일링되는 환경을 구축할 수 있었습니다.