코딩마을방범대
Artillery를 이용해 부하 테스트 진행하기 본문
프로젝트를 배포했을 때 사용자가 몰리게 된다면 쓰레드 부족 등으로 서버가 터질 수 있다.
이를 사전에 체크하는 것이 필요할 수 있는데, 부하테스트 프로그램을 알아보자면 제일 유명한 JMeter 와 Artillery가 있다.
JMeter은 쓰레드 수를 지정해놓고 테스트를 진행하는거라 내가 진행해야할 테스트와는 부합하지 않았으므로 Artillery를 사용해볼 예정이다.
부하테스트란?
임계치의 한계에 도달할 때까지 시스템에 부하를 꾸준히 증가시키며 진행하는 테스트
Artillery
ArtilleryVisit Website는 Node.js로 작성된 스트레스 테스트 도구이다.
특징
- HTTP(S), Socket.io, Websocket 등 다양한 프로토콜을 지원한다.
- 시나리오 테스트를 할 수 있다.
- JavaScript로 로직을 작성해서 추가할 수 있다.
- statsd를 지원해서 Datadog이나 InfluxDB 등에 실시간으로 결과를 등록할 수 있다.
- 풍부한 CLI 커맨드를 제공한다.
- 리포트 페이지를 따로 제공한다.
Artillery는 Node.js 를 이용한 부하 테스트이며, 사전에 Node.js와 npm 설치가 필요하다.
사이트에서 Node.js 설치 시 npm도 추가적으로 설치가 가능하다.
설치
> npm i -D artillery
설치 확인
1. 버전 확인
> npx artillery version
2. 공룡 그림 확인
> npx artillery dino
귀여운 공룡그림이 나온다는데 내껀 하나도 안귀엽다
사용
사용에는 두 가지 방법이 있다.
quick을 이용한 간단한 방법과 json 파일을 별도로 생성하여 이용하는 방법이 있다.
quick은 request 등이 없이 GetMapping으로 해당 주소로 바로 연결한다.
시나리오 버전은 request 값 등을 설정하여 실제 사용자처럼 연결해볼 수 있다.
우선 quick을 알아보고 그 다음으로 시나리오 버전을 알아볼 것이다!
Quick 테스트
> npx artillery quick --count 50 -n 1 http://localhost:80/test
옵션 | 설명 |
--count | 가상의 사용자 수 |
-n | 요청 횟수 |
--rate | 초당 요청 |
아래 명령어를 통해 quick의 옵션들을 조회할 수 있다.
> npx artillery quick --help
위 명령어 실행 시 아래와 같이 quick의 옵션들이 출력되는 것을 확인 할 수 있다.
run a simple test without writing a test script
USAGE
$ artillery quick [TARGET] [-c <value>] [-n <value>] [-o <value>] [-k] [-q]
FLAGS
-c, --count=<value> [default: 10] Number of VUs to create
-k, --insecure Allow insecure TLS connections
-n, --num=<value> [default: 10] Number of requests/messages that each VU will send
-o, --output=<value> Filename of the JSON report
-q, --quiet Quiet mode
DESCRIPTION
run a simple test without writing a test script
결과 예시
출력되는 통계 종류가 두가지가 있는데, 최종 결과만 확인하고 싶은 경우 aggregate를 보면 된다.
통계 종류 | 설명 |
intermediate | 테스트가 실행될 때 콘솔에 인쇄되는 통계 (10초마다 발생) |
aggregate | 전체 테스트 기간 동안의 통계로, 테스트 종료 시 콘솔에 출력되는 최종 통계 |
All VUs finished. Total time: 3 seconds
--------------------------------
Summary report @ 14:01:46(+0900)
--------------------------------
http.codes.200: ....................................................................... 50 // 상태 코드가 200(OK)인 HTTP 응답 수
http.downloaded_bytes: .......................................................... 850
http.request_rate: .................................................................... 50/sec // 초당 HTTP 요청 수
http.requests: .......................................................................... 50 // 총 HTTP 요청 수
http.response_time:
min: ................................................................................... 73 // 최소 응답시간
max: .................................................................................. 99 // 최대 응답시간
median: ............................................................................. 85.6 // 중간 응답시간
p95: ................................................................................... 94.6 // 95%의 응답 시간
p99: ................................................................................... 96.6 // 99%의 응답 시간
http.responses: ........................................................................ 50 // 수신된 총 HTTP 응답 수
vusers.completed: ................................................................... 50 // 테스트를 완료한 총 가상 사용자 수
vusers.created: ........................................................................ 50 // 테스트 중에 생성된 총 가상 사용자 수
vusers.created_by_name.0: .................................................... 50 // 각 시나리오에 대해 생성된 가상 사용자 수
vusers.failed: ............................................................................ 0 // 테스트 중 실패한 총 가상 사용자 수
vusers.session_length:
min: .................................................................................... 142.6
max: ................................................................................... 195
median: .............................................................................. 165.7
p95: .................................................................................... 186.8
p99: .................................................................................... 190.6
응답에 대한 코드들
응답코드 | 설명 |
errors.ECONNREFUSED | 연결이 거부되었음을 의미 |
errors.ECONNRESET | TCP conversation의 다른 쪽이 갑자기 닫혔음을 의미 |
http.codes.200 | 요청이 정상적으로 완료되었음을 의미 |
http.codes.301 | 서버에서 리다이렉트 페이지 이동이 발생했을 경우 |
http.codes.400 |
HTTP 구문 분석 규칙을 충족하지 못했거나 시간 제한을 초과했거나 IIS 또는 HTTP.sys 들어오는 요청을 준수해야 하는 다른 규칙에 실패했기 때문 |
http.codes.401 | 유효한 인증정보를 가지지 않은 경우 |
http.codes.403 | 인증이 실패한 경우 |
http.codes.405 | 메소드가 허용되지 않았을 경우 |
http.codes.500 | 예외적인 또는 예측하지 못한 에러 |
http.codes.501 | 알 수 없는 메소드를 호출했을 경우 |
http.codes.502 |
CGI 프로세스가 IIS 7.0에 응답을 다시 보내기 전에 CGI 프로세스가 예기치 않게 종료되었을 때, 잘못된 게이트웨이 오류 |
http.codes.503 | 서버가 요청을 받을 준비가 되지 않은 경우 |
ECONNREFUSED와 ECONNRESET의 경우 그 수만큼 vusers.failed의 수가 커진다.
시나리오 테스트
json 또는 yaml 파일을 이용하여 실제 사용자의 행동을 모방하여 시나리오를 작성할 수 있다.
( request 값을 보낼 수 있다 )
JSON or YML 파일 만들기
json 예시
{
"config": {
"target": "http://localhost:80",
"phases": [
{
"duration": 60,
"arrivalRate": 30
}
],
"payload": {
"path": "./data.csv",
"fields": ["email", "password"]
}
}, "scenarios": [
{
"flow": [
{
"post":{
"url": "/auth/login",
"json": {
"email": "{{email}}",
"password": "{{password}}"
}
}
},
{
"get": {
"url": "/hashtag?hashtag=test"
}
}
]
}
]
}
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
payload:
path: "keywords.csv"
fields:
- "keyword"
scenarios:
- name: "Search and buy"
flow:
- post:
url: "/search"
headers:
authorization: "Bearer {token}"
json:
kw: "{{ keyword }}"
capture:
- json: "$.results[0].id"
as: "productId"
- get:
url: "/product/{{ productId }}/details"
Config section
Key | 설명 |
target | 테스트할 URL |
phases | 테스트 요청 시간과 비율을 정한다. (ex. { "duration": 60, "arrivalRate": 30 } : 60초 동안 매초 30개의 요청을 보낸다.) |
defaults | 테스트할 시나리오의 기본값을 설정 |
payload | 임의의 데이터를 보내기 위해서 사용 (csv 파일은 여러 필드를 가져올 경우 콤마로 구분에서 1열에 정렬) |
socketio | 소켓을 테스트할 수 있음 |
plugins | 플러그인 설정 |
ensure | 에러나 지연 시간에 대해 성공 조건을 세팅 |
processor | 커스텀 js코드를 load |
Config section
Key | 설명 |
name | 시나리오 이름 |
flow | 시나리오에서 진행하는 테스트 동작을 순서대로 적기 [ url(링크), headers(헤더), json(body) |
*capture | 응답으로 받은 데이터를 변수로 지정해서 뒤에 보내는 요청에 사용할 수 있음 |
*match | 응답 데이터가 원하는 값이 오는지 확인할 수 있음 |
weight | 시나리오에 대한 가중치 ( 이 값이 높으면 해당 시나리오는 더 많이 발생한다 ) |
※ *는 flow의 Mapping 안에 있는 설정값
사용
-o가 위에 help에서 봤듯이 report에 대한 파일을 생성해주는 옵션이다.
나는 확장자를 적어주지 않으면 오류가 발생해서 확장자를 적어주었다!
> npx artillery run -o myTest.json test.yml
실행 시 json 데이터로 결과가 담긴 파일이 생성된다.
이 때 이 결과 파일을 웹에서 그래프로 확인하고 싶은 경우 아래 명령어를 실행하면 된다!
> npx artillery report myTest.json
나는 결과 파일을 확장자 붙여서 저장했기 때문에 이름이 저렇게 저장된다!
생성된 html을 크롬에서 열어보면 그래프를 확인할 수 있다.
참고사이트
NodeJS 환경에서 부하테스트 진행하기(Artillery 이용)
Internal Server Error, 서버 500 에러는 어떤 경우에 발생하나요?
'👀 프론트엔드' 카테고리의 다른 글
React의 useRef 와 JavaScript의 객체 구조 분해 할당 (0) | 2023.07.21 |
---|---|
웹 소켓을 이용한 메시지 전송(클라이언트) (0) | 2023.07.21 |
window에서 Node.js 여러 버전 사용하기 (0) | 2023.07.20 |
자바스크립트의 Promise 의 역할 (0) | 2023.07.20 |
프론트(web)의 package.json (0) | 2023.07.18 |