k6を使って負荷テストをやってみる

# はじめに

負荷テスト＝JMeterって疑いもなく思っていましたが、k6というパフォーマンス計測ツールを知ったので、試してみました。

公式サイトはこちら
[https://k6.io/](https://k6.io/)

JavaScriptで負荷テストのコードが書けるのですごく便利です。

## 環境

- Windows 10
- WSL2
- Docker Desktop
- Ubunt 20.04

## インストール
インストールしてもいいのですが、Dockerコンテナが提供されているので、それを利用することもできます。

公式サイトに従って、インストールします。

```bash
$ sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
$ echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
$ sudo apt-get update
$ sudo apt-get install k6
```

Docker使うなら、こうですね。

```bash
$ docker pull loadimpact/k6
```

# 負荷シナリオを書く
負荷シナリオはJavaScriptで書きます。以下のような形になるのですが、
リクエストの部分を、シナリオ風にしてもいいし、同じリクエストを繰り返して実行することもできます。
使えるAPIはマニュアルを見るのが一番ですね。[こちら](https://k6.io/docs/javascript-api)
あとは、サンプル集も参考になります。[こちら](https://k6.io/docs/examples)

```javascript
import http from "k6/http";
import { check } from "k6";

// 最初に1回だけ実行される
export function setup() {
    console.log("setup");
}

// ここにテストシナリオを記載する
export default function() {
    let url = 'http://xxxxxx.com/api/xxxxx/xxxx';
    const payload = JSON.stringify(data);

    const params = {
        headers: {
          'Content-Type': 'application/json;charset=UTF-8',
            }
        };

    const response = http.post(url, payload, params);
};

// 最後に一回実行される
export function teardown(data) {
    console.log("teardown");
}
```

# 負荷シナリオを実行する

では実行してみます。

```bash
k6 run example.js
```

と実行すると、こんな感じで実行結果が得られます。

```bash
    data_received..............: 14 MB  79 kB/s
    data_sent..................: 8.1 MB 45 kB/s
    http_req_blocked...........: avg=1.96ms   min=200ns   med=300ns    max=3.19s    p(90)=700ns    p(95)=1.1µs
    http_req_connecting........: avg=1.64ms   min=0s      med=0s       max=3.16s    p(90)=0s       p(95)=0s
    http_req_duration..........: avg=129.67ms min=41.77ms med=115.8ms  max=1.39s    p(90)=163.85ms p(95)=187.93ms
    http_req_receiving.........: avg=345.74µs min=21µs    med=99.05µs  max=213.61ms p(90)=326.04µs p(95)=565.87µs
    http_req_sending...........: avg=258.93µs min=25.2µs  med=112.6µs  max=91.84ms  p(90)=318.97µs p(95)=444.83µs
    http_req_tls_handshaking...: avg=226.59µs min=0s      med=0s       max=107.53ms p(90)=0s       p(95)=0s
    http_req_waiting...........: avg=129.07ms min=41.63ms med=115.38ms max=1.39s    p(90)=163.16ms p(95)=187.02ms
    http_reqs..................: 7224   39.837763/s
    iteration_duration.........: avg=999.17ms min=1.3µs   med=995.64ms max=4.16s    p(90)=1.04s    p(95)=1.06s
    iterations.................: 7224   39.837763/s
    vus........................: 7      min=7  max=40
    vus_max....................: 40     min=40 max=40
```

http_req_duration、http_reqsあたりが、性能指標値として使いやすいかと思います。

## ユーザ数や実行時間などを指定する

よく使うオプションを紹介します。

-u ユーザ数を指定する　5、10
-d 実行時間を指定する　180s、10m、などを指定する。デフォルト値は30秒
--rps 指定したｽﾙｰﾌﾟｯﾄになるように時刻を調整

```bash
 k6 run -u 180 -d 180s --rps 180 example.js
```

## 実行結果をinfluxdbに登録する
k6には標準で、便利な機能が備わっていて、influxdb実行結果を登録することができます。

```bash
 k6 run  --out influxdb=http://localhost:8086/k6db -u 180 -d 180s --rps 180 example.js
```

k6dbというローカルに立てたinfluxdbに登録できます。その結果をGrafanaでグラフ化。
わずか1時間程度で、計測→集計が完了。超らくちん。こんなグラフがすぐできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132118/0ffb5b0c-4406-b593-8b7e-1fe9b847e4a7.png)

# さいごに
JMeterに代わるものとして、k6を使ってみました。
今回、新しいAPIの機能の性能計測に利用しましたが、使い始めてから計測、評価完了まで1週間もかからず。
JavaScriptなので学習コストも低く、influxdbとの連携で、ログの集計とかもらくちんでした。

もう少し大きいシナリオを書いたりすると、少し難しい面も出てくる気がしますが、
現時点では、すごくいいツールという感想です。

またほかの機能を使ってみたら記事にしようとおもいます。