// 전역 설치
npm install -g artillery@latest
// 프로젝트 설치
npm install -D artillery@latest
온라인 쇼핑몰의 백엔드에서 동작하는 한 API의 성능을 테스트 한다고 가정해보자.
보통 온라인 쇼핑몰은 블랙프라이데이나 사이버먼데이와 같은 행사기간에 트래픽이 급증하는 현상이 발생한다.
백엔드가 위와 같은 대용량 트래픽을 무리 없이 처리할 수 있는지 확인할 수 있는 매우 좋은 방법은 사용자들이 실제로 어떤 행동을 할지 시뮬레이션을 해보는 것이다.
온라인 쇼핑몰에서 상품을 구매하려 할 때 사용자는 다음과 같은 행동들을 할 것이다.
위의 동작들이 동시에 100명에 의해서 실행되도 잘 작동하는지 확인하고자 한다.
테스트하고자 하는 URL.
config:
target: "https://example.com/api"
각 단계마다 몇 명의 가상의 사용자를 생성할지, 얼마나 자주 요청을 보낼지 등을 정의하면 된다.
config:
target: "https://example.com/api"
phases:
- duration: 60
arrivalRate: 5
name: Warm up
- duration: 120
arrivalRate: 5
rampTo: 50
name: Ramp up load
- duration: 600
arrivalRate: 50
name: Sustained load
첫번째 단계: 백엔드를 웜업하는 (느린 증가)단계이다. 60초마다 5명의 가상 사용자를 백엔드로 보냄.
두번째 단계: 120초 동안 5명의 가상 사용자로 시작해서 매 초마다 수를 증가시켜 단계가 끝나는 피크에는 50명의 사용자를 보냄.
세번째 단계: 600초 동안 매 초마다 50명의 가상 사용자를 유지하는 지속적인 스파이크를 시뮬레이션.
상품 검색은 성능 테스트에서 확인할 섹션 중 하나다. 제품 검색과 같은 동적 콘텐츠에 접근할 때 시스템이 어떻게 처리하는지 확인하는 것이 좋다.
artillery에서는 외부 csv파일을 불러와서 시나리오의 변수로 주입시킬 수 있다.
// keywords.csv
computer
video game
vacuum cleaner
toys
hair dryer
위와 같은 파일이 있을 때
config:
...
...
payload:
path: "keywords.csv"
fields:
- "keyword"
payload 키로 불러올 수 있다.
fields의 value값도 여러 개 선언할 수 있다)위에서는 테스트에 필요한 구성을 설정했다면 이제 실제로 가상의 사용자들이 어떤 과정을 거치면 좋을지 시나리오를 구상해볼 것이다.
각 가상 사용자들에 대해서 다양한 시나리오를 정의할 수 있고 각 시나리오는 한개 이상의 동작을 수행한다.
테스트 스크립트에 scenarios를 추가해아한다.
scenarios:
- name: "Search and buy"
flow:
- post:
url: "/search"
json:
kw: "{{ keyword }}"
POST /search 요청을 생성한다.kw(JSON 객체)가 있어야 하고 config.payload의 키워드 중 하나로 설정한다.{ "kw": "toys" }를 요청으로 보내고, 가상의 사용자 B는 { "kw": "computer" }를 요청으로 보낸다.다음으로는 백엔드로부터 반환받은 결과값의 상세정보를 조회하는 것이다.
scenarios:
.
.
- post:
.
.
capture:
- json: "$.results[0].id"
as: "productId"
POST /search 요청을 보내면 백엔드는 키워드가 포함된 객체들을 배열로 반환해준다. 첫 번째 결과물의 ID만 필요하다고 했을 때 capture옵션을 사용하여 id 프로퍼티를 productId에 저장할 수 있다.저장된 productId는GET /product/:productId/details 요청 등에 사용할 수 있다.
scenarios:
.
.
- post:
.
.
- get:
url: "/product/{{ productId }}/details"
가상의 사용자가 요청을 보낸 뒤 사이트에 머무르는 것을 시뮬레이션할 수 있다.
.
.
- get:
url: "/product/{{ productId }}/details"
- think: 5
think: 5는 가장 최근 요청인 get 요청을 보낸 뒤 5초 동안 테스트가 일시정지된다.상품을 장바구니에 추가하는 시나리오를 생각해보자. 이 동작을 수행하는 요청은 POST /cart이다. 요청 바디로 productId가 필요하다.
.
.
.
- post:
url: "/cart"
json:
productId: "{{ productId }}"
여기서 사용되는 productId는 POST /search 요청 때 캡쳐해둔 productId이다.
# search-and-add-to-cart.yml
config:
target: "https://example.com/api"
phases:
- duration: 60
arrivalRate: 5
name: Warm up
- duration: 120
arrivalRate: 5
rampTo: 50
name: Ramp up load
- duration: 600
arrivalRate: 50
name: Sustained load
payload:
path: "keywords.csv"
fields:
- "keyword"
scenarios:
- name: "Search and buy"
flow:
- post:
url: "/search"
json:
kw: "{{ keyword }}"
capture:
- json: "$.results[0].id"
as: "productId"
- get:
url: "/product/{{ productId }}/details"
- think: 5
- post:
url: "/cart"
json:
productId: "{{ productId }}"
위의 파일이 최종 테스트 스크립트이다.
테스트 실행 방법:artillery run search-and-add-to-cart.yml