🤖
負荷試験ツール k6 を Docker Compose で速攻で動かす
💁♂️ はじめに
株式会社EGSTOCKの日下繕章です。
現在担当している案件で負荷試験を行なうツールを検討していたところ、k6がイケてるということなので検証がてらDocker Composeを使用してk6を動かしてみた
公式サイト: https://k6.io/
GitHub: https://github.com/grafana/k6
📃 k6の特徴
- JSでテストロジックを記述できるため保守性・再利用性が高い
- テストロジックと設定オプションがJSで記述できるのでバージョン管理が容易
- HTTP/1.1, HTTP/2, WebSocket, gRPCプロトコルをサポート
- checks や thresholds などのCI向けのサポートがある
🏃♂️ 動かしてみる
とりあえずgit clone
してサンプルで付属しているHTTPのGET通信のシナリオをDocker Compose
で動かしてみる
$ git clone https://github.com/grafana/k6.git
$ cd k6
$ docker compose up influxdb grafana -d
$ docker compose run --rm -T k6 run - < samples/http_get.js
/\ |‾‾| /‾‾/ /‾‾/
/\ / \ | |/ / / /
/ \/ \ | ( / ‾‾\
/ \ | |\ \ | (‾) |
/ __________ \ |__| \__\ \_____/ .io
execution: local
script: -
output: InfluxDBv1 (http://influxdb:8086)
scenarios: (100.00%) 1 scenario, 1 max VUs, 10m30s max duration (incl. graceful stop):
* default: 1 iterations for each of 1 VUs (maxDuration: 10m0s, gracefulStop: 30s)
running (00m00.7s), 0/1 VUs, 1 complete and 0 interrupted iterations
default ✓ [ 100% ] 1 VUs 00m00.7s/10m0s 1/1 iters, 1 per VU
data_received..................: 21 kB 29 kB/s
data_sent......................: 446 B 600 B/s
http_req_blocked...............: avg=526.25ms min=526.25ms med=526.25ms max=526.25ms p(90)=526.25ms p(95)=526.25ms
http_req_connecting............: avg=198.15ms min=198.15ms med=198.15ms max=198.15ms p(90)=198.15ms p(95)=198.15ms
http_req_duration..............: avg=215.06ms min=215.06ms med=215.06ms max=215.06ms p(90)=215.06ms p(95)=215.06ms
{ expected_response:true }...: avg=215.06ms min=215.06ms med=215.06ms max=215.06ms p(90)=215.06ms p(95)=215.06ms
http_req_failed................: 0.00% ✓ 0 ✗ 1
http_req_receiving.............: avg=87µs min=87µs med=87µs max=87µs p(90)=87µs p(95)=87µs
http_req_sending...............: avg=82.4µs min=82.4µs med=82.4µs max=82.4µs p(90)=82.4µs p(95)=82.4µs
http_req_tls_handshaking.......: avg=259.22ms min=259.22ms med=259.22ms max=259.22ms p(90)=259.22ms p(95)=259.22ms
http_req_waiting...............: avg=214.89ms min=214.89ms med=214.89ms max=214.89ms p(90)=214.89ms p(95)=214.89ms
http_reqs......................: 1 1.346112/s
iteration_duration.............: avg=741.48ms min=741.48ms med=741.48ms max=741.48ms p(90)=741.48ms p(95)=741.48ms
iterations.....................: 1 1.346112/s
こんな感じであっさり実行できて結果が取得できた
数値についてはこちらで解説してくれていた
Grafanak6 performance test
選択するとビジュアライズされた結果を参照できる
🔧 設定ポイント
samples/http_scenario.jsを準備し実際の負荷試験を想定した設定サンプル
import http from "k6/http";
import { group, check } from "k6";
import { scenario } from 'k6/execution';
export const options = {
// シナリオ設定
scenarios: {
'scenarios': {
executor: 'shared-iterations', // 複数のVUでiterationを共有
vus: 2, // 同時接続数
iterations: 2, // シナリオの総反復回数
maxDuration: '30s', // 試験の実行時間
},
},
// テスト対象システムの期待性能の合格・不合格を判断する閾値
thresholds: {
http_req_failed: ['rate<0.01'], // エラーが1%を超えない
http_req_duration: ['p(95)<200'], // リクエストの95%は200ms以下であること
},
};
export function setup() {
// テスト実行前に実行
console.log("setup");
}
export default function () {
// scenario.iterationInTestはシナリオを通して1テスト毎に一意な値を取得可能
const uuid = ( '10000000' + scenario.iterationInTest ).slice( -8 );
// 認証を行う通信を実行
const params = {
headers: {
'Content-Type': 'application/json',
}
};
const requestBody = JSON.stringify({
uuid: uuid
});
let accessToken;
group("/xxxxx/login", () => {
const response = http.post('http://localhost/api/xxxxx/login', requestBody, params);
check(response, {
'is status 200': (r) => r.status === 200,
});
accessToken = response.json().res.accessToken;
});
// アクセストークンの必要な通信実行
const authParams = {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer '+ accessToken,
}
};
group("/xxxxx/xxxxx", () => {
const response = http.post('http://localhost/api/xxxxx/xxxxx', null, authParams);
check(response, {
'is status 200': (r) => r.status === 200,
});
});
}
export function teardown() {
// テスト実行後に実行
console.log("teardown");
}
下記で実行
$ docker compose run --rm -T k6 run - < samples/http_scenario.js
Discussion