k6での性能試験を試してみる

# 始めに

この記事は [mediba アドベントカレンダー](https://qiita.com/advent-calendar/2021/mediba) 13 日目の記事です。

新卒入社 から早 3 年目ですが、技術ブログを書くのはプライベート含めて初めてです。🥺

所属プロダクトの軽い性能試験で k6 を使用してみたので、少しだけアドベントカレンダーの記事にしてみます。

# k6 とは

- Github: https://github.com/grafana/k6

- 公式ドキュメント: https://k6.io/docs/

k6 は JavaSctipt でシナリオを作成できる 負荷試験ツールです。

ツール自体は Go で作られています。JS でシナリオを作れて Go 製なんですとなると「使いたい！」と思う WEB 界隈の人は多いのではないのでしょうか。

# インストール

Mac の方は brew でインストール出来ますね。

```
$ brew install k6

$ k6 version
k6 v0.34.1 ((devel), go1.17, darwin/arm64)
```

実行用コンテナも用意されています。

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

# コマンド

コマンドを見ていきましょう。
用意したシナリオの JS ファイルを run コマンドに渡すだけです。

```
$ k6 run test_scenario.js
```

手っ取り早く使えそうなオプションはこの辺りでしょうか。

| オプション         | 詳細                 |
| ------------------ | -------------------- |
| --vus              | 同時接続数           |
| --duration         | 実行時間             |
| --out csv = \*.csv | CSV レポートファイル |

アウトプット形式については [公式ドキュメント](https://k6.io/docs/getting-started/results-output/) に記載されています。

色々なアウトプット形式に対応しているとのことなので、弊社で最近取り入れている NewRelic にメトリクスを送信してみましょう。

# NewRelic 統合

ローカルに立てたスタブサーバーにGETするだけのシナリオです。

[公式ドキュメント](https://k6.io/docs/using-k6/http-requests/)にサンプルも豊富に用意されてますね。

サンプルが充実してるツールは大好きです ❤️

```
[test_scenario.js]

import http from 'k6/http';
export default function () {
  const params = {
        headers: {
          'Cache-Control': 'no-cache',
        }
      };
  http.get('http://localhost:8080/v1/status', params);
}
```

公式ドキュメント通りにローカルに NewRelic エージェントコンテナをバックグラウンドで起動させておきます。アカウントIDとAPIキーは自前のモノに置き換えます。

```
$ docker run \
  -d --restart unless-stopped \
  --name newrelic-statsd \
  -h $(hostname) \
  -e NR_ACCOUNT_ID=<NR-ACCOUNT-ID> \
  -e NR_API_KEY="<NR-INSERT-API-KEY>" \
  -p 8125:8125/udp \
  newrelic/nri-statsd:latest

$ docker ps | grep newrelic
0c184418ed9e   newrelic/nri-statsd:latest            "/nri-statsd.sh"         7 minutes ago   Up 7 minutes   0.0.0.0:8125->8125/udp, :::8125->8125/udp             newrelic-statsd
```

この状態でシナリオを動かしてみます。

```
$ K6_STATSD_ENABLE_TAGS=true k6 run -u 10 -d 1m --out statsd test_scenario.js
```

シナリオは終わるとこんな感じで出てくれます。

ただ標準出力だとやはり時系列でのデータ変化は見にくいですね。。😡

```

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

  execution: local
     script: test_scenario.js
     output: statsd (localhost:8125)

  scenarios: (100.00%) 1 scenario, 10 max VUs, 1m30s max duration (incl. graceful stop):
           * default: 10 looping VUs for 1m0s (gracefulStop: 30s)


running (1m00.0s), 00/10 VUs, 258811 complete and 0 interrupted iterations
default ✓ [======================================] 10 VUs  1m0s

     data_received..................: 37 MB  621 kB/s
     data_sent......................: 30 MB  492 kB/s
     http_req_blocked...............: avg=684ns  min=0s       med=1µs    max=7.84ms  p(90)=1µs    p(95)=1µs
     http_req_connecting............: avg=13ns   min=0s       med=0s     max=372µs   p(90)=0s     p(95)=0s
     http_req_duration..............: avg=2.29ms min=264µs    med=1.61ms max=64.75ms p(90)=4.23ms p(95)=5.86ms
       { expected_response:true }...: avg=2.29ms min=264µs    med=1.61ms max=64.75ms p(90)=4.23ms p(95)=5.86ms
     http_req_failed................: 0.00%  ✓ 0          ✗ 258811
     http_req_receiving.............: avg=9.85µs min=3µs      med=7µs    max=2.03ms  p(90)=14µs   p(95)=25µs
     http_req_sending...............: avg=3.13µs min=1µs      med=2µs    max=1.37ms  p(90)=4µs    p(95)=7µs
     http_req_tls_handshaking.......: avg=0s     min=0s       med=0s     max=0s      p(90)=0s     p(95)=0s
     http_req_waiting...............: avg=2.28ms min=253µs    med=1.6ms  max=64.73ms p(90)=4.21ms p(95)=5.84ms
     http_reqs......................: 258811 4312.80491/s
     iteration_duration.............: avg=2.31ms min=281.58µs med=1.63ms max=64.77ms p(90)=4.26ms p(95)=5.89ms
     iterations.....................: 258811 4312.80491/s
     vus............................: 10     min=10       max=10
     vus_max........................: 10     min=10       max=10
```

NewRelic のメトリクスで見てみましょう。
Data explorer の Metrics から `k6.*` で出力されているのが k6 のメトリクスです。

今回はリクエスト時間(http_req_duration)のメトリクスを見ていきます。

![スクリーンショット 2021-12-09 8.40.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301899/a7feedd2-a77a-8475-72a6-10dee9ce1805.png)



時系列に沿ってリクエスト時間が可視化できていますね 😏

出力単位も `Average, Sum, Max , Min` 等が出力できていたので、充分業務でも使えそうです。

# まとめ

初めて k6 という性能試験ツールを使ってみましたが、データインテグレーションやドキュメントを見てもかなりモダンな性能試験ツールという印象を受けました。

JavaScript の勉強も兼ねてこれからも k6 を使いたいですね。

ありがとうございました。

# 参考 URL

- https://k6.io/docs/