포스트

K6 를 활용한 웹소켓 부하 테스트

K6 를 활용한 웹소켓 부하 테스트

이런 말이 있습니다.

“나를 죽이지 못하는 고통은 나를 더 강하게 만든다.” - 프리드리히 니체

견고한 소프트웨어를 만들기 위해서는 부하 테스트를 통해서 약점을 찾아야 합니다. 롱쿼리, 병목이 되는 응답 등을 여러 시나리오를 통해서 발견하고, 개선할 수 있어야 합니다.


ubuntu 환경에서 docker 를 이용해서 k6 부하 테스트를 해보겠습니다. k6 를 사용하는 이유는 다음과 같습니다

  1. js 로 fe 에서 요청을 보내는 형식과 유사하게 테스트를 작성할 수 있다.
  2. 웹 소켓 프로토콜을 지원한다.
  3. grafana 에서 만들었기에, grafana 템플릿이 다양하고, 문서가 잘되어 있다.

docker 로 k6 설치

1
2
3
docker pull grafana/k6

test 를 수행할 script 코드 작성

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import ws from 'k6/ws';
import { check } from 'k6';

const FIXED_HEADER_LENGTH = 64;

let fixedHeader = new ArrayBuffer(FIXED_HEADER_LENGTH);
let headerBytes = new Uint8Array(fixedHeader);

let conneceted = false;
let waplAuth = null;
let stack = [];

function connectWebSocketAndTest() {

    ws.connect(url, {}, function(socket) {
        conneceted = true;
        console.log('WebSocket connection opened');

        socket.on('open', function() {
            console.log('Connection opened');
            init(socket);
        });

        socket.on('message', function(e) {

          // socket 에서 수행할 테스트
            const jsonObjects = parseMultipleJSONs(decodeData);
            jsonObjects.forEach((obj) => {
                const textContent = JSON.stringify(obj, null, 2) + "\n\n";
                stack.push(textContent);
            });

            console.log(stack.join(""));
            console.log("Response JSON objects: ", jsonObjects);

            const varHeader = jsonObjects[0];
						// 응답 결과 검증
            check(varHeader, {
                'status is OK': (r) => r && (r.statusCode === 'OK' || r.statusCode === 200)
            });
        });

        socket.on('close', function() {
            conneceted = false;
            stack = [];
            console.log('Connection closed');
        });
    });
}

async function init(socket) {
    connect();
    await sendMessage(socket);
}


export const options = {
    stages: [
        { duration: '2m', target: 400 }, // 테스트 수행할 stage 설정 400 명의 vuser 로 2 분간 테스트
        { duration: '10m', target: 0 }, // scale down. Recovery stage.
    ],
};

export default function () {
    connectWebSocketAndTest();
}


위의 test.js 코드를 인자로 docker 명령어를 수행합니다.

1
2
3
4
docker run -i --rm -v $(pwd):/scripts -w /scripts grafana/k6 run /scripts/test.js


test 결과 모니터링 및 시각화

테스트를 수행해도 결과가 나오지만, 시각화를 하면 더욱 이해하기 좋습니다. influxDb 로 데이터를 보내고, grafana 를 통해서 그래프로 만들겠습니다.

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
28
29
30
version: "3.7"

services:
  influxdb:
    image: bitnami/influxdb:1.8.5
    container_name: influxdb
    ports:
      - "8086:8086"
    environment:
      - INFLUXDB_ADMIN_USER_PASSWORD=bitnami123
      - INFLUXDB_ADMIN_USER_TOKEN=admintoken123
      - INFLUXDB_HTTP_AUTH_ENABLED=false
      - INFLUXDB_DB=myk6db
    volumes:
      - influxdb_data:/bitnami/influxdb

  grafana:
    image: bitnami/grafana:latest
    container_name: grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin123
    depends_on:
      - influxdb

volumes:
  influxdb_data:

influxdb 및 grafana 를 설치해줍니다.

1
2
3
docker run -i --rm -v $(pwd):/scripts -w /scripts grafana/k6 run --out influxdb=http://influxdb:8086/myk6db /scripts/test.js

이제, 테스트를 수행하면 그 결과 지표가 influxdb 로 들어갑니다. influxdb 는 docker container 로 띄웠기에, grafana/k6 내부에서 influxdb 에 접근할 수 있도록 방화벽 확인을 잘 해줍시다.


이후, grafana 에서 influxdb 를 datasource 로 설정한 후, 각종 metrics 를 바탕으로 그래프를 만들어주면 됩니다. 다만 아직 websocket 에 대해서는 grafana template 이 잘 없어서 직접 시각화 대시보드를 구성해줘야 합니다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.