Frontend

Artillery 서버 부하테스트 오픈소스 알아보기(1)

devdubby 2024. 3. 30. 22:00

회사에서 프로모션성 페이지를 Nextjs를 활용하여 개발했는데 릴리즈 하자마자 메모리 부족으로 서버가 죽게 되버린 사건이 있었다. 이제는 프론트엔드 개발자도 서버를 관리 해야하는 임무를 받은 시대가 됨으로써, 어떻게 하면 안전하게 서버를 운영해볼 수 있을까 조사해보다 알게된 Artillery이라는 서버 부하 테스트 오픈소스에 대해 작성해보려 한다.

특징 및 설치방법

artillery는 다음과 같은 특징을 갖고 있다.

  • 클라우드 네이티브 분산 부하 테스트를 대규모로 바로 사용할 수 있는 무료 서비스이다.
  • AWS Lambda 또는 AWS Fargate에서 서버리스 부하 테스트도 가능하다.
  • [HTTP], [WebSocket], Socket.io, gRPC, Kinesis 등도 지원한다.
  • Artillery에는 플러그인 API도 있고 오픈소스이기 때문에 확장이 용이하다.
  • 시나리오 단위로 테스트도 가능하다.

설치 및 실행방법은 간단하다.

$ npm install -g artillery@latest

먼저 위 명령어로 artillery를 설치해주고,

config:
  # This is a test server run by team Artillery
  # It's designed to be highly scalable
  target: http://asciiart.artillery.io:8080
  phases:
    - duration: 60
      arrivalRate: 1
      rampTo: 5
      name: Warm up phase
    - duration: 60
      arrivalRate: 5
      rampTo: 10
      name: Ramp up load
    - duration: 30
      arrivalRate: 10
      rampTo: 30
      name: Spike phase
  # Load & configure a couple of useful plugins
  # https://docs.art/reference/extensions
  plugins:
    ensure: {}
    apdex: {}
    metrics-by-endpoint: {}
  apdex:
    threshold: 100
  ensure:
      thresholds:
        - http.response_time.p99: 100
        - http.response_time.p95: 75
scenarios:
  - flow:
      - loop:
        - get:
            url: "/dino"
        - get:
            url: "/pony"
        - get:
            url: "/armadillo"
        count: 100

간단한 테스트 스크립트를 작성해준다. 테스트 스크립트를 자세히 살펴보자.

config, scenarios

Artilliery의 테스트 스크립트는 config와 scenarios 두 부분으로 구성되어 있다.
config는 로드 테스트 실행 방법(예: 테스트 중인 시스템의 URL, 생성되는 부하량, 사용할 플러그인 등)을 정의하는 부분이다.
scenarios는 Artillery에서 생성한 가상 사용자가 수행할 작업을 정의하는 곳이다. 시나리오는 일반적으로 앱에서 사용자 세션을 설명하는 일련의 단계이다.

target

target: "http://asciiart.artillery.io:8080"

위 스크립트는 모든 요청이 해당 URL을 기본적으로 사용하도록 target을 지정해주는 부분이다.

phases

phases:
  - duration: 60
    arrivalRate: 5
    rampTo: 10
    name: Warm up the API
  - duration: 60
    arrivalRate: 10
    rampTo: 50
    name: Ramp up to peak load
  - duration: 300
    arrivalRate: 50
    name: Sustained peak load

이 테스트에서는 세 가지 단계로 정의했는데,

  • API Warm up 단계 - 이 단계는 60초 동안 실행된다. Artillery는 초당 5명의 새로운 가상 사용자를 생성하는 것으로 시작하여(arrivalRate) 단계가 끝날 때까지 점차적으로 초당 10명(rampTo)의 새로운 가상 사용자까지 늘린다.
  • Ramp up to peak load 단계 - 이 단계도 60초 동안 지속된다. Artillery는 초당 10명의 가상 사용자에서 50명의 가상 사용자로 부하를 계속 증가시킨다.
  • Sustained peak load 단계 - 이 단계는 300초 동안 실행된다. 이 단계에서는 Artilliery가 매초 50명의 가상 사용자를 새로 생성한다.

이 단계에서는 짧은 시간 동안 API의 부하가 높은 수준으로 치솟는 '스파이크 테스트'가 발생한다. 뉴스레터 발송, 깜짝 세일 등과 같은 최고치 수준의 트래픽 상황 예시라고 볼 수 있다.

plugins

plugins:
    ensure: {}
    apdex: {}
    metrics-by-endpoint: {}

테스트의 모든 URL에 대한 세부 지표를 생성하고 테스트 결과에 대한 자동 성공 검사를 설정하기 위해 몇 가지 기본 제공 플러그인을 로드한다. 현재 예시에서는 사용하지 않는다.

scenarios

scenarios:
  - name: Get 3 animal pictures
    flow:
      -loop:
        - get:
            url: "/dino"
        - get:
            url: "/pony"
        - get:
            url: "/armadillo"
      count: 100

시나리오 섹션에서는 하나의 시나리오를 정의한다. 이 테스트에서 생성된 각 가상 사용자는 이 시나리오를 실행하게 된다.

시나리오는 세 단계로 구성되어 있으며, 각 단계는 다른 엔드포인트에 대한 HTTP GET 요청으로 되어있다. countloop 를 사용하여 이 세 가지 요청을 100회 반복한다.

시나리오를 실행하는 모든 가상 사용자는 동일한 시나리오를 실행하는 다른 가상 사용자와 완전히 독립적이라고 볼 수 있다. 가상 사용자 간에 메모리, 네트워크 연결, 쿠키 또는 기타 상태가 공유되지 않는다.

테스트 실행

이제 테스트 스크립트에 대해 알았으니 실행해보자.

artillery run asciiart-load-test.yml

위 명령어를 실행하면 아래와 같은 부하테스트 결과 리포트를 10초마다 출력해준다.

 

 

리포트 지표 중 일부는 이름을 보고 의미를 유추할 수 있을텐데 한번 몇 가지만 알아보자.

  • http.codes.200: 이 지표에서 HTTP 응답 코드에 대해 볼 수 있는데 오른쪽 숫자는 해당 기간 동안 200인 HTTP 응답수가 몇 번이였는지를 알려준다.
  • http.downloaded_bytes: 이 기간 동안 다운로드된 데이터의 총 크기(바이트)이다.
  • http.request_rate: 이 기간 동안 초당 평균 HTTP 요청 속도이다.
  • http.requests: 이 기간 동안 이루어진 총 HTTP 요청 수이다.
  • http.response_time: 이 지표는 HTTP 요청의 응답 시간(밀리초)에 대한 통계를 제공한다.
    • min: 가장 짧은 응답 시간
    • max: 가장 긴 응답 시간
    • mean: 평균 응답 시간
    • median: 정렬된 응답 시간들의 중간 값
    • p95: 95번째 백분위수 응답 시간으로 응답 시간의 95%가 이 값보다 낮음을 의미한다.
    • p99: 99번째 백분위수 응답 시간으로 응답 시간의 99%가 이 값보다 낮음을 의미한다.
  • vusers.completed: 실행을 완료한 가상 사용자 수
  • vusers.created: 이 기간 동안 생성된 총 가상 사용자 수

위 캡쳐화면에는 안나와있지만 다음과 같은 지표도 제공한다.

  • vusers.session_length: 가상 사용자의 세션 길이(밀리초)에 대한 통계를 제공한다.
    • min: 가장 짧은 세션 길이
    • max: 가장 긴 세션 길이
    • mean: 평균 세션 길이
    • median: 정렬된 세션 길이 목록의 중간 값
    • p95: 95번째 백분위수 세션 길이로, 세션의 95%가 이보다 짧음을 의미
    • p99: 99번째 백분위수 세션 길이로, 세션의 99%가 이보다 짧음을 의미

이러한 각 지표는 요청에 얼마나 빠르고 안정적으로 응답하는지, 처리할 수 있는 트래픽 양, 전반적인 사용자 경험을 포함하여 로드 시 애플리케이션이 어떻게 수행되는지 테스트를 위한 중요한 정보들을 제공한다.

CI/CD 제공

Artillery는 CLI를 제공하고 Github actions, Jenkins, Circle CI, Gitlab CI/CD 등을 지원하여 CI/CD 파이프라인에서도 부하테스트를 해볼 수 있도록 한다. 이러한 도구들은 자동화가 중요한데 다양한 CI/CD 툴과 결합할 수 있으니 현업에서도 충분히 사용해볼만 한 것 같다.

정리

간단히 Artillery는 어떤 오픈소스인지 알아봤다. 기본적인 개념을 알아봤으니 다음편에서 실제 정상서버, 메모리가 낭비되고 있는 서버 두개를 구성하여 어떻게 부하테스트를 신뢰성 있게 테스트 해볼 수 있는지 정리해보려 한다.

참고자료