Artillery를 이용한 부하 테스트
2019-10-27 17:22:19

부하 테스트

예로 내가 어떤 게임 서버를 만들었는데 아마도 유저가 최대 얼마 정도 접속 해서 API를

호출 하지 않을까? 예상해서 가상의 유저를 생성하여 API를 계속 호출해서 서버가 어떤 상태가

되는지 확인을 하는 것을 부하 테스트라 이해 했다.

부하 테스트를 통해 현재 이 서비스의 서버 사양이 괜찮은지, 어플리케이션이 점점 느려진다는지

등등 이러한 부분을 체크 하여 수정 및 개선을 한다.

실제로 온라인 게임등을 보면 종종 오픈 시 서버가 터지는데 얼마나 몰린건지.. 무섭다

Artillery

Artillery는 Node.js에서 쓸 수 있는 부하 테스트 도구 인데 아래와 같은 방법을 지원 한다.

  • HTTP
  • Socket.io
  • WebSocket

다른 부하 테스트 도구를 아직 안 써봐서 장점이나 단점은 잘 모르겠다..

설치

node.js가 설치되어 있어야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
npm i artillery -g # npm
artillery -V # 버전 확인
# ___ __ _ ____ _
# _____/ | _____/ /_(_) / /__ _______ __ (_)___ _____
# /____/ /| | / ___/ __/ / / / _ \/ ___/ / / / / / __ \/____/
# /____/ ___ |/ / / /_/ / / / __/ / / /_/ / / / /_/ /____/
# /_/ |_/_/ \__/_/_/_/\___/_/ \__, (_)_/\____/
# /____/

# ------------ Version Info ------------
# Artillery: 1.6.0-29
# Artillery Pro: not installed (https://artillery.io/pro)
# Node.js: v10.16.1
# OS: darwin/x64
# --------------------------------------

연습할 어플리케이션

아주 간단한 API를 Express로 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const express = require('express');
const bodyParser = require('body-parser');
const uuid = require('nanoid');

const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true,
}));

const port = 3000;

app.post('/join', (req, res) => {
return res.json({ code: 200, id: uuid.nanoid(), create_at: new Date().getTime() });
});

app.get('/data', (req, res) => {
const { id } = req.query;
if (!id) {
return res.json({ code: 500, message: 'something wrong' });
}
return res.json({ code: 200, id });
});

app.listen(port, (req, res) => {
console.log(`running on port ${port}`);
});

시나리오

시나리오를 작성한대로 API를 여러 번 호출을 하여 부하를 줄 수가 있다.

지금은 연습으로 HTTP 테스트 시나리오를 작성 한다.

  1. /join을 통해 ID를 응답 받는다.
  2. /data에 ID를 보낸다.

artillery는 json 또는 yaml을 지원하는데 yaml이 나은 듯(주석을 쓸 수 있어서!)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
config:
target: "http://localhost:3000" # host
phases:
- duration: 30 # 해당 초만큼 실행
arrivalRate: 300 # 가상 사용자 수
processor: "./util.js" # 참조할 js
defaults:
headers: # header 세팅
Content-Type: 'application/json'
scenarios:
- flow:
- post: # method 설정
url: "/join" # api url
body: ""
afterResponse: "responseData" # api 응답받은 후의 실행할 함수
match: # 해당 값이 맞는지 체크
json: "$.code" # json 데이터 중에 code를 선택
value: 200 # 200이면 success 아니면 fail
- function: "setParam" # get 실행하기전에 참조할 함수
- get:
url: "/data?id={{ id }}" # setParam에서 넣은 ID
match:
json: "$.code"
value: 200

이전엔 몰랏는데 함수를 시나리오 로직에 추가할 수가 있었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

const fs = require('fs');

const data = [];

const responseData = (requestParams, response, context, ee, next) => {
const json = JSON.parse(response.body);
if (json.code === 200) {
data.push(json.id);
}
return next(); // next를 리턴해줘야 다시 시나리오 실행
};

let i = 0;

const setParam = (context, events, done) => {
context.vars['id'] = data[i]; // id라는 값에 파라미터 설정
i++;
return done(); // 콜백
}

exports.responseData = responseData;
exports.setParam = setParam;

실행 및 결과

1
2
artillery run -o 결과.json 실행할 파일명.yaml
artillery report 결과.json
  1. 작성한 yaml파일의 실행 결과를 json으로 저장을 한다.
  2. report 명령어로 실행을 하면 html로 차트 등 결과 화면을 보여 준다.

참고

Prev
2019-10-27 17:22:19
Next