카테고리 없음

병목을 해결하는 사이클

tally 2025. 1. 19. 22:40

개요

최근 회사에서 성능 관련된 이슈가 꽤 발생했었습니다. 
 
이슈를 확인하고 대응하면서 '어떻게 미리 방지할 수 있을까'하는 생각에 부하 테스트를 알아보게 되었고, 학습하면서 배운 부하테스트를 통해 병목이 되는 구간을 파악하고 해결해가는 과정을 정리하려고 합니다.
 
 
이 강의를 보고 참고하여 작성한 글입니다.
https://inf.run/sND28

대규모 트래픽 처리를 위한 부하테스트 입문/실전 강의 | JSCODE 박재성 - 인프런

JSCODE 박재성 | 비전공자 입장에서도 쉽게 이해할 수 있고, 실전에서 바로 적용 가능한 '대규모 트래픽 처리를 위한 부하테스트 입문/실전' 강의를 만들어봤습니다!, 🤬 에라이, 못 해먹겠네!비전

www.inflearn.com

 
 

지연시간과 처리량

지연시간은 실제 요청을 보낸 시간부터 응답을 받기까지의 시간을 의미하고, 레이턴시(Latency)라고도 부릅니다.
만약, 특정 API에 요청을 보냈을 때 레이턴시가 2.5라고 한다면 평균적으로 응답을 받는 시간이 2.5초라고 할 수 있습니다.
 
처리량은 이름 자체에도 알 수 있듯이 서비스가 처리할 수 있는 트래픽의 양을 의미합니다.
이를 쓰로우풋(Throughput)이라고도 부르는데요, 단위는 일반적으로 TPS(Transaction Per Seconds)를 활용합니다.
만약, 어떠한 서버에서 1초에 최대 100개의 API 요청을 처리할 수 있다면 이 서버의 스로우풋은 100이라고 할 수 있습니다.
 
참고로, 요즘 서비스들은 외부와 통신하거나 다수의 서비스들과 협력하는 경우가 많은데요, 
이러한 환경의 서비스일때 아래 이미지처럼 서버간의 통신에서 TPS가 1000이 나오지만 데이터베이스와의 통신이 500이 나오고 있는 상황이라면 실질적으로 해당 API가 초당 처리할 수 있는 양은 500이기 때문에 TPS는 500이게 됩니다.

A -- 1000 --> B -- 500 --> DB

 
 

목표 설정

부하 테스트를 진행할 때 가장 선행되어야 하는 것 중 하나는 '우리의 서비스가 얼마만큼 수용하게 할 것인가'입니다.
얼마만큼의 사용자가 와도 수용할 수 있게 만드는 것이 가장 좋겠지만, 이러한 목표값을 설정해야 하는 이유는 비용과 관련되어 있기 때문입니다.
 
극단적인 예시로 부품 변경이 어려운 온프레미스 환경이고, 하나의 서버만 운용하고 있는 상황이라고 가정해보겠습니다.
해당 서버를 운용하는 서비스는 초기 오픈한 상태라 하루 최대 접속자수가 100명밖에 되지 않는 상황입니다. 
그런데 만약, 1000만명의 사용자가 와도 수용하게 한다라는 목표를 가지고 진행한다면 이를 수용하기 위한 과도한 비용이 나오는 문제가 발생할 수 있습니다.
 
또 하나 중요한 것은 '현재 시스템의 상태'를 알아야 합니다.
CPU, 디스크, 메모리 등의 사용률뿐만 아니라 요청량과 같은 서비스 단위 지표를 확인할 수 있어야 어느 부분이 병목이 있고, 어떻게 개선해야 하는지를 알 수 있기 때문입니다.
 
 

현재 상태

실무에서 부하 테스트를 진행한다는건 '서버가 터지면 어쩌지', '기존 트래픽만큼 견딜 수 있나'하는 고민에서 시작되었을 것입니다.
 
그렇다면 현재 구성되어 있는 시스템이 1초당 몇 개의 요청을 처리할 수 있고,
안정적인 레이턴시를 유지하는 구간은 어디까지인가를 알아야 합니다.
 
현재 시스템이 얼마만큼 수용할 수 있는지를 Grafana Labs에서 만든 부하 테스트 도구인 K6로 진행하였습니다.
https://grafana.com/docs/k6/latest/

테스트 환경
- EC2: t3a.small 2대(application server(spring), k6)
- RDS: t4g.micro (free tier)
- 더미 데이터 100만건

부하테스트 스크립트
유저당 1초에 한번씩 호출하고 유저수(VU, Virtual Users)가 6000명에 도달할때까지 10분동안 점진적으로 증가

 
 
테스트 결과
부하 테스트를 진행한 결과 사용자가 늘어나더라도 TPS는 4/s ~ 4.5/s가 나오고 있고, 레이턴시는 초당 4개 요청을 기준으로 평균 6초의 응답 시간을 가지고 있는 것을 확인할 수 있습니다.

TPS: 4/s ~ 4.5/s

 

레이턴시: 초당 4개 요청 기준 6초

 
 
위 결과의 지표는 사용자 경험에 영향을 줄만큼 좋지 않은 수치이지만 병목을 해결하는 사이클을 배우는 것이 목적이기 때문에 논외로 하고,
여기서 중요한 것은 '목표하는 수치를 달성하고 있는가'에 초점을 맞추어 바라보아야 합니다.
 
해당 지표를 기준삼아 목표치를 다음과 같이 설정해보겠습니다.

목표 수치
TPS: 7/s 이상
레이턴시: 3초 미만

 
 

AS-IS

테스트한 결과에 일정 수치에서 유지가 된다라는 것은 서버가 처리할 수 있는 최대 용량(처리량, 요청수 등)에 거의 도달했음을 의미합니다.
 
부하 테스트를 진행한 이후에 서버와 데이터베이스의 대시보드를 확인해보면 다음과 같습니다.

 
EC2 CPU 사용률을 제외한 나머지 수치가 한계점에 도달하지 않은걸로 보았을 때,
병목 현상(일정 수치를 유지하게 만드는)이 발생한 원인으로 EC2 CPU 사용률이었음을 의심할 수 있게 됩니다.
 
 
TO-BE
AS-IS에서 의심되는 병목 현상이 EC2에서 발생한 것임을 알게 되었으니,
확장(수직적 또는 수평적)을 해결 방법으로 둘 수 있습니다.
 
따라서, 하나의 EC2를 추가하여 수평적 확장을 통해 두 대의 EC2 서버가 처리하도록 하여,
성능 테스트를 다시 돌려본 결과는 다음과 같습니다.
 

TPS: 8/s ~ 9/s

 

레이턴시: 초당 4개 요청 기준 1.5초

 
병목이 되었던 EC2를 수평 확장을 통해 TPS는 기존 대비 12.5% 개선되고, 레이턴시는 기존 대비 40% 개선이 된 것을 확인할 수 있고,
목표 수치였던 TPS가 7/s 이상이 나오고, 레이턴시는 3초 미만으로 나오면서 목표로 하는 수치를 달성한 것을 알 수 있습니다.
 
이처럼 목표로 해야 하는 수치가 있더라면 운영 환경과 가장 비슷한 알파 환경(하드웨어 스펙, 데이터, 요청량 등)을 구축하여 지속적인 확인과 점진적인 개선의 사이클을 돌리면 최종적으로 목표치에 달성하여 안정적으로 서비스 오픈을 할 수 있게 됩니다.
 
 

결론

부하 테스트를 곁들여 병목을 찾고, 해결하는 과정을 진행해보면서 배우고 정리되는 것들이 많았던 것 같습니다. 특히나 지난달에 회사 인프라분과 온콜 문화를 같이 공부하면서 완벽하게 얻어가지 못한 것들을 이번 기회에 많이 정리되었습니다. 
 
굉장히 흥미로웠던 것 중 하나는,
단순히 한 곳의 병목을 해결한다고 해서 모든 것이 해결되는 것이 아니라, 새로운 병목 지점이 생겨난다는 것이었습니다.
 
 
이번 포스팅에서는 부하테스트로 병목인 구간을 찾아 해결하는 것에 정리했지만, 한 스텝 더 나아가 운영 측면에서 알람까지도 생각해보고 있다면 다음의 포스팅들을 추천합니다 ♻️
 
https://aws.amazon.com/ko/blogs/tech/how-to-monitor-rds-in-woowabrothers/

우아한형제들에서 Amazon Aurora 데이터베이스를 모니터링 하는 방법 | Amazon Web Services

우아한형제들은 3천만 이상이 선택한 배달앱 ‘배달의민족’으로 음식 문화를 선도하고 있습니다. ‘배민1 한집배달’로 더 빠르게 배달 받을 수 있고, ‘배민 쇼핑라이브’를 보면서 판매자와

aws.amazon.com

https://tech.kakao.com/posts/560

KHP 모니터링과 알림 - 2부 - tech.kakao.com

앞선 1부 에서는 KHP 시스템이 모니터링 체계의 데이터 기반이 되는 메트릭과 로...

tech.kakao.com