본문 바로가기
개발 이야기/Tools

k6, 부하 테스트 도구 사용 해보기(with Docker)

by 농개 2024. 1. 27.
반응형

k6(https://k6.io/docs/)란 성능 테스트 및 부하 테스트를 위한 오픈 소스 도구입니다.

웹어플리케이션의 API 성능을 측정하는데에 사용됩니다.동시 접속, 가상의 유저, 반복 횟수 등을 설정해서 서버 응답 시간, 처리량 등을 확인 할 수 있습니다.또한 가장 큰 장점은 Javascript 코드를 통해 테스트 시나리오를 작성 할 수 있다는 것이고Grafana 진영에서 개발되어 Grafana와 연동이 수월합니다.

 

정리하자면

  • grafana에서 제공
  • javascript로 테스트 작성
  • 가상유저, 반복, 서버 응답 시간, 처리량 등 확인 가능

저는 익숙한 Javascript를 사용한다는 점에서 너무 편하더군요.

 

해당 글에서는 Docker를 통해 부하테스트 도구인 k6를 찍먹해보겠습니다.

 

1. 설치

docker pull grafana/k6:lastest

 

위 커멘드로 docker image를 다운로드 합니다.

 

2. 스크립트 작성

// test.js
import http from "k6/http";
import { check } from "k6";

export const options = {
  scenarios: {
    scenarios_example: {
      executor: "per-vu-iterations",
      vus: 100,
      iterations: 10,
      maxDuration: "30s",
    },
  },
};
export default function () {
  const params = {
    headers: {
      "Content-Type": "application/json",
    },
  };
  const response = http.get("http://host.docker.internal:8080/api/test", {
    params,
  });
  check(response, { "status is 200": (r) => r.status === 200 });
}

위와 같은 javascript 코드로 된 테스트를 정의 할 수 있습니다.

여기서는 k6의 scenarios라는 개념을 사용합니다.

다양한 방법의 테스트를 할 수 있지만, 저는 scenarios가 가장 편하더군요.

 

먼저 options를 보겠습니다.

scenarios가상 사용자(VUs)반복(Iterations)을 상세하게 구성하는 것입니다.

시나리오를 사용하면 다양한 워크로드나 부하 테스트에서의 트래픽 패턴을 모델링할 수 있습니다.

maxDuration은 부하 테스트의 timeout 정도로 보면 됩니다.

만약 부하 테스트에 걸리는 시간이 30초를 초과하게 된다면 도중 테스트를 종료하고 나머지 작업은 drop으로 간주합니다.

 

그리고 아래부분은 실제 javascript 코드로

로컬환경의 8080포트에 띄워진 서버에 GET(/apitest)요청을 하게 됩니다.

docker로 localhost를 호출할 때에는 host.docker.internal:{port} 형식으로 기입해주면 됩니다.

로드 테스트가 외부 환경이라면 그에 맞는 Host를 기입하여 줍니다.

 

check는 k6 모듈에서 제공하는 기능입니다.

위 코드에선 HTTP 상태 코드가 200일 때 성공으로 보고 처리율을 계산하게 됩니다.

그 외에 유용한 기능은 공식 문서에서 확인 가능합니다.(https://k6.io/docs/javascript-api/k6/)

 

 

3. Docker로 실행

cat test.js | docker run --rm -i --net=host grafana/k6 run -

위 커맨드로 실행해 봅시다.

 

          /\      |‾‾| /‾‾/   /‾‾/
     /\  /  \     |  |/  /   /  /
    /  \/    \    |     (   /   ‾‾\
   /          \   |  |\  \ |  (‾)  |
  / __________ \  |__| \__\ \_____/ .io

  execution: local
     script: test.js
     output: -

  scenarios: (100.00%) 1 scenario, 10 max VUs, 1m0s max duration (incl. graceful stop):
           * scenarios_example: 3 iterations for each of 10 VUs (maxDuration: 30s, gracefulStop: 30s)


     ✓ status is 200

     checks.........................: 100.00% ✓ 30       ✗ 0
     data_received..................: 2.6 kB  866 B/s
     data_sent......................: 3.0 kB  996 B/s
     http_req_blocked...............: avg=824.45µs min=1.67µs med=2.86µs  max=2.9ms   p(90)=2.45ms  p(95)=2.75ms
     http_req_connecting............: avg=373.44µs min=0s     med=0s      max=1.46ms  p(90)=1.1ms   p(95)=1.36ms
     http_req_duration..............: avg=2.86ms   min=2.05ms med=2.48ms  max=4.21ms  p(90)=3.95ms  p(95)=4.13ms
       { expected_response:true }...: avg=2.86ms   min=2.05ms med=2.48ms  max=4.21ms  p(90)=3.95ms  p(95)=4.13ms
     http_req_failed................: 0.00%   ✓ 0        ✗ 30
     http_req_receiving.............: avg=44.52µs  min=9.12µs med=26.02µs max=196.6µs p(90)=93.51µs p(95)=135.83µs
     http_req_sending...............: avg=20.23µs  min=5.46µs med=13.72µs max=69.58µs p(90)=44.25µs p(95)=62.86µs
     http_req_tls_handshaking.......: avg=0s       min=0s     med=0s      max=0s      p(90)=0s      p(95)=0s
     http_req_waiting...............: avg=2.79ms   min=2ms    med=2.45ms  max=4ms     p(90)=3.86ms  p(95)=3.98ms
     http_reqs......................: 30      9.955399/s
     iteration_duration.............: avg=1s       min=1s     med=1s      max=1s      p(90)=1s      p(95)=1s
     iterations.....................: 30      9.955399/s
     vus............................: 10      min=10     max=10
     vus_max........................: 10      min=10     max=10
     
     running (0m03.0s), 00/10 VUs, 30 complete and 0 interrupted iterations
scenarios_example ✓ [======================================] 10 VUs  03.0s/30s  30/30 iters, 3 per VU

 

위와 같이 콘솔에 테스트 결과가 잘 정리되어 표시되는 것을 확인 할 수 있습니다.

 

4. docker-compose로 실행

## docker-compose.yml
version: '3.7'
networks:
  k6:
services:
  k6:
    image: grafana/k6:latest
    networks:
      - k6
    volumes:
      - ./scripts:/scripts

위와 같이 docker-compose.yml 파일을 생성해줍니다.

(편의를 위해 scripts 폴더내에 javascript파일을 옮겨 줬습니다. 그리고 볼륨 마운트 해줬습니다.)

 

아래 커맨드로 실행해보면 정상 동작함을 확인 할 수 있습니다.

docker-compose run k6 run /scripts/test.js

 

반응형