Print
카테고리: [ Amazon Web Services ]
조회수: 6136

AWS 공식 홈페이지를 통해 공개된 기술 문서로 웹 및 어플리케이션 서버의 부하 테스트를 

AWS 환경에서 수행했을 때의 모든 것(?)에 대해 기술한 내용입니다.

제 입장에서 가장 유익했던 부분은 부하 테스트 툴이 이리도 많이 있었다는 것에 놀랐고

기회가되면 한 번 테스를 해봐야겠다는 생각이 드네요. 

 

AWS 기반 웹 및 애플리케이션 서버 부하 테스트: A to Z

 

사용자가 이용하고 있는 온라인 서비스로부터 예상치 못한 느려짐을 겪거나, 접속 불가로 인해 서비스 이용 조차 할 수 없다면, 서비스에 중요한 재방문율(Retention Rate)과 유료 전환율(Conversation Rate)을 하락 시켜 비지니스에 큰 손실을 야기 할 수 있습니다. 이런 성능 관련 문제를 예방하기 위해 성능 테스트, 특히 부하 테스트에 대한 중요성이 크게 증가하고 있으며, 더불어 관련  도구 및 서비스의 다양성 또한 증가하고 있습니다.

이번 글은 AWS 클라우드에서 어떻게 웹/애플리케이션 서버의 부하 테스트를 하는지 모범 사례를 알려드리기 위한 것으로, 부하테스트 목적과 고려 사항 그리고 단계 및 도구 등을 대해 다루고자 합니다.

부하 테스트의 목적
일반적으로 부하 테스트는 서비스 개발 이후, 운영을 하기 직전 수행하는 테스트 중 하나로서, 실제 요구되는 부하를 서비스가 수용할 수 있는지를 확인하기 위한 작업 입니다. 사용자 활동을 시뮬레이션 하고 인프라 및 서버의 동작을 모니터링 함으로써, 전부는 아닐지라도, 많은 부분의 병목 현상(Bottleneck)을 제거할 수 있습니다.

부하 테스트의 목적으로는 보통 다음 세가지가 있습니다.

부하 테스트 전 고려되어야 할 점
실제 성능 테스트 시, 부하 테스트를 비중 있게 여기지 않는 경우가 많으며, ApacheBench 나 JMeter 와 같은 도구를 다운로드 한 뒤, 특정 시나리오를 기반으로 하여 도구를 실행하는 것만으로 충분하다고 생각하는 경우가 있습니다. 하지만, 실제 워크로드는 다양한 변수와 시나리오를 가지고 있기 때문에, 부하 테스트를 진행할 때 충분히 이점을 반영 하여 야지만 실제 서비스에서 예상 가능한 결과를 가져올 수 있다는 것은 분명한 사실 입니다.

그럼 실용적인 부하 테스트를 위해 어떤 부분들을 고려해야 할까요?

AWS 클라우드 기반 부하 테스트의 장점
AWS 클라우드는 부하 테스트를 진행하기 위해 고려할 사항에 대한 적절한 해답을 가지고 있습니다.  AWS 클라우드에서 부하 테스트 하게 된다면 어떤 특징을 가지고 있을까요?

부하 테스트의 단계
부하 테스트는 서비스 전체 스택을 대상으로 진행할 수도 있지만, 최근에는 마이크로서비스(Microservices) 나 서비스 지향 구조(Service-Oriented Architecture) 등의 형태로 서비스를 디자인하는 경우가 많아, 전체 스택을 구성하고 있는 작은 컴포넌트들부터 진행되는 경우가 많아지고 있습니다.

또, 빠른 병목 현상 발견과 수정을 위해, 애플리케이션 로직이 적용되기 전 순수한 인프라 수준에서 시작하여 작은 컴포넌트들, 솔루션, 그리고 애플리케이션 순으로 부하 테스트를 확대해 나갈 수도 있습니다.

아래는 일반적으로 수행할 수 있는 부하 테스트 단계 입니다.

단계별 부하 테스트 수행 방법
앞서 언급한 것처럼, 부하 테스트는 전체 스택에 대해서도 수행 가능하지만, 작은 비결합된 컴포넌트나 기능 단위로도 수행 가능합니다. 그리고 작은 단위로 수행될 수록 더 분명하게 병목 지점을 파악하기에 수월 합니다. 그렇기에, 가능한 작은 단위부터 단계별로 진행하는게 원하는 결과를 얻어내는데 효율적입니다.

다음은 전형적인 3단계(3-tier) 웹 서비스에 대해 단계별로 부하 테스트를 진행하는 것을 설명하고 있습니다.

 

  1. 최초 ‘WEB’ 을 출력하는 웹 페이지를 대상으로 동시 연결성에 대한 테스트 수행 → 결과 평가→최적화 진행 (Client →Web Server)
  2. 웹 서버를 통해 애플리케이션 서버에서 넘겨 받은 ‘APPLICATION’ 을 출력하는 웹 페이지를 대상으로 동시 연결성에 대한 테스트 수행→ 결과 평가 → 최적화 진행 (Client →Web Server → App Server – w/o Logic)
  3. 데이터베이스에서 최소한의 쿼리 결과를 전달 받아 출력하는 웹 페이지를 대상으로 동시 연결성에 대한 테스트 수행 →결과 평가 → 최적화 진행
    (Client →Web Server → App Server – w/o Logic → Database)
  4. 3-tier 스택 전체를 대상으로 애플리케이션 로직이 적용된 페이지에 동시 연결성에 대한 테스트 수행 → 결과 평가 → 최적화 진행
    (Client → Web Server → App Server – with Logic →Database)
  5. 4번을 기반으로 다양한 시나리오를 지정하여 테스트 수행 → (얻고자 하는 지표 기준에 대해서) 결과 평과 → 최적화 진행

부하 테스트 시, 각 레이어별 고려하여야 할 사항
부하 테스트를 수행한 뒤 각 레이어별로 발생할 수 있는 상황과 고려하여야 할 부분에 대해서 알아보도록 하겠습니다.

  1. 네트워크 용량 확인: 테스트 환경이 구성된 인프라와 관련하여 여러가지 지표를 확인할 수 있지만, 대표적으로 아웃바운드 연결이 예상되는 최대의 부하를 처리할 수 있는지 확인할 필요가 있습니다. Amazon EC2 의 경우 인스턴스 타입 마다 서로 다른 네트워킹 성능을 제공하고 있기에, 부하에 따른 적절한 인스턴스 타입 선택이 중요 합니다. 또 사내 인프라와 프라이핏하게 연결되어 있다면, VPN 관련 네트워킹 성능에 대해서도 확인을 하여야 합니다.
  2. 부하 생성 클라이언트: 앞서 설명하였듯이 부하 테스트의 요구사항 중 하나로, 필요한 만큼의 부하를 생성할 수 있는 충분한 인스턴스의 확보가 요구됩니다. 하지만, 설정 및 구현 방식에 의해 하나의 부하 생성 클라이언트가 처리할 수 있는 동시성에 큰 제한이 있다면, 필요 이상으로 복수개의 인스턴스가 요구되어 비용이 증가할 수 있습니다. 이럴 땐 Thread 기반의 툴 보다는 높은 동시성을 제공하는 Async IO 기반의 툴을 사용하여 테스트를 진행하는게 좋습니다.
  3. 로드 밸런싱: ELB(Elastic Load Balancing)는 서비스 전체 부하를 백엔드에 등록된 복수개의 인스턴스로 분산하는 기능을 제공합니다. 부하 테스트를 수행할 때 다양한 이유로 기대치 보다 낮은 결과나 5xx 에러가 발생하는 것을 볼 수 있습니다. 이 때, ELB 가 제공하는 다양한 모니터링 지표들을 확인하면, 어느 곳에서 병목 현상이나 에러가 발생되는지 확인하는데 도움이 됩니다. 가장 자주 발생하는 문제는, 503 Server Unavailable 이나 504 Gateway Timeout 에러 발생과 동시에, ELB 의 모니터링 지표에 SurgeQueueLength 가 1024 로 기록되고 SpilloverCount 가 0 보다 높을 경우 입니다. SurgeQueueLength 는 ELB 에 등록된 백엔드 인스턴스가 요청을 처리하지 못하여 쌓이게 되는 ELB 의 큐 이며, 앞서 언급한 것처럼 1024가 큐의 최대 크기 입니다. 이 최대 크기를 넘어서면 요청을 한 클라이언트에 5xx 에러를 보내게 되고, 동시에 SpilloverCount 가 기록 됩니다. 이 문제를 해결하기 위해서는 적시에 Auto Scaling 이 일어날 수 있도록 적절한 지표를 기준으로 알람을 발생 시킬 수 있도록 해야 합니다. 백엔드 인스턴스에서 동작하는 시스템이 어떤 자원을 더 많이 사용하는지 확인을 하고, 그 자원의 지표를 기준으로 Auto Scaling 을 설정하는 것이 좋습니다. SurgeQueueLength 를 기준으로 알람이 발생하게 하는 것도 한 가지 방법 입니다. ELB 가 제공하는 지표들은 여기에서 확인할 수 있습니다.
    추가로 ELB 도 발생하는 부하에 따라 Auto Scaling 을 통해 규모가 변화되도록 설계 되어 있습니다. 만약, 매우 급격한 트래픽 증가가 일어날 때 ELB 가 확장되는 속도가 증가하는 트래픽을 수용하지 못한다면 5xx 에러가 발생할 수 있습니다. 이를 방지 하기 위해, 미리 점차적으로 증가하는 부하 테스트를 통해 어느정도 ELB 를 확장 시켜 둘 수 있습니다. 또한, ELB 에 등록된 백엔드 인스턴스에서 Keep-Alive 기능을 활성화 시켜, ELB 와 백엔드 인스턴스간에 불필요한 연결 수립이 일어나는 것을 방지한다면 더 높은 성능을 기대할 수 있습니다.
  4. 서버 인스턴스: 서버 인스턴스의 설정 값에 따라 웹/애플리케이션 서버의 자원 사용 효율성이 달라 집니다. 대표적으로 Linux 서버의 open files 숫자를 늘려 두지 않으면, 동시 접속이 기본값인 1024 개로 제한되어 서버 인스턴스를 효과적으로 사용할 수 없습니다.
  5. 애플리케이션 서버: 애플리케이션 서버의 종류마다 다르지만, 일반적으로 Tomcat 등의 Thread 기반의 애플리케이션 서버일 경우, Thread Pool 의 크기가 너무 작다면 처리 되어야할 요청들이 기다리는(waiting) 상태가 길어져 전체 부하 테스트의 효율성을 떨어뜨릴 수 있습니다. 최근에는 Thread 기반의 애플리케이션 서버가 가지고 있는 제약으로 인해, Event 기반의 비동기 형태의 애플리케이션 서버가 자주 사용되어 집니다.
  6. 애플리케이션: 애플리케이션 코드와 프레임워크 둘로 나누어 생각해 볼 수 있습니다. 애플리케이션 코드 내에서 잘못된 방식으로 프레임워크나 API 를 사용할 수 있으며, blocking 코드가 포함되어 있다거나, 불필요한 연산을 진행, 또 테스트 코드를 삭제하지 않았다는 등의 문제가 있을 수 있습니다. 이 때에는 적절한 Unit Test 와 Lint 등을 통해 문제를 조기에 발견할 수 있어야 합니다.  사용하는 웹 프레임워크나 ORM(Object-relational mapping)과 같은 라이브러리가 가지고 있는 버그로 인하여 문제가 발생할 수도 있습니다. 애플리케이션 관련 다양한 문제를 해결하기 위해 APM(Application Performance Monitoring) 을 활용하여 성능을 모니터링 하는 것도 한가지 방법 입니다.
  7. 데이터베이스: CPU 사용률과 응답 시간(response time) 등을 확인할 필요가 있습니다. 특히 데이터베이스를 설정한 방법에 따라 더 요구되는 자원을 눈 여겨 볼 필요가 있습니다. 최근에는 성능을 향상 시키기 위해 메모리를 적극 활용하게끔 설정을 하는 경우가 많으며, 이때에는 메모리 사용률이 특정 수치 이상으로 넘어갈 경우, 알람을 발생 하도록 설정하여 병목 지점 확인이 가능 하겠습니다.

부하 테스트 관련 도구 및 서비스
부하 테스트를 위해 사용할 수 있는 다양한 툴과 서비스들이 존재 합니다. 간단한 소개와 함께 특징들을 살펴보겠습니다.

 

그밖에도 다양한 AWS Marketplace에서도 다양한 파트너들의 부하 테스트 솔루션을제공하고있습니다.

부하테스트 시 유용한 팁 모음
AWS 클라우드 기반으로 부하 테스트를 진행하는데 있어서 알아두면 도움이 되는 팁들을 간단하게 소개해 드리고자 합니다.

부하 테스트에는 보통의 시나리오 기반의 가상의 워크로드에 대한 부하 테스트 뿐만 아니라, 실제 워크로드에 대한 부하 테스트를 위해 프로덕션에서 발생하는 트래픽을 활용하는 방법도 있습니다. 프로덕션 환경의 실제 트래픽을 활용하기 위해서는, 트래픽을 재사용 하기 위해 기록하거나 곧바로 테스트 환경으로 리플레이 해 주는 gor (https://goreplay.org/) 와 같은 툴을 사용할 수 있습니다. 프로덕션 환경의 실제 트래픽을 반복하여 활용할 수 있다는 이점 이외에도, 서비스 및 애플리케이션 업데이트 예정 버전에 실제 트래픽을 흘려 보내 사용성에 대한 테스트도 진행할 수 있는 장점도 있습니다.

추가로, 많은 경우 부하 테스트는 개발 주기 마지막에 진행되는 경우가 많습니다. 애자일 방법론과 지속적인 통합(CI/CD)을 활용하는 경우 조금 더 일찍, 자주 부하 테스트를 진행할 수 있으며, 이를 통해 추후 발생할 수 있는, 비용이 많이 드는 성능 문제를 미리 방지할 수 있습니다. 따라서, 가능한 개발 주기에 부하 테스트를 포함하여 자주 진행하는 것이 바람직하다고 볼 수 있습니다.

AWS 에서 제공하는 방대한 인프라와 이미 부하에 대해 고려되어 설계된 관리형 서비스, 그리고 다양한 규모 관련 기능들을 적극 활용하여 서비스를 구축한다면 가변적인 부하에도 유연한 서비스를 제공할 수 있을 것 입니다.