おんぶろぐ ver.2

おんぶろぐがインチキだらけなので改心しました

K6

f:id:kooyoo:20191204152956j:plain:w500

概要

今回は 性能測定用の負荷クライアントである K6 を紹介します。 K6golang製の負荷テストツールとなります。特徴はシンプルで強力なところです。

K6はインストール、シナリオ記述、そして実行の各局面でサクッと進められるよう、とてもシンプルな仕様となっています。

性能試験でバタバタしている時に、仮に良いツールがあったとしても学習コストをかけていられないですよね?そんなユーザの心の声を汲んでかK6の習得は簡単です。

インストール

インストールの方法は3種類です。どれも簡単な手順で導入が可能です。

  • パッケージマネージャ
  • シングルバイナリ
  • Docker イメージ

K6CLIのツールなので、Homebrewや apt-get等のパッケージマネージャから落としてくることができます。

$ brew install k6

Mac (Homebrew) の場合これだけです。Linuxの場合は Debian系, RedHat系に応じて インストールすることができます。

また、k6golang製ですので、シングルバイナリのファイルも GitHub上で提供されています。この場合ファイルを落としてきて実行するだけです。簡単ですね。

シナリオ定義

次にシナリオファイルです。シナリオファイルは JSで用意します。こんな感じ。

[basic-test.js]

import http from "k6/http";
import { check, sleep } from "k6";

export default function() {
  http.get("http://test.loadimpact.com");
};

実行

ここまでできたなら、一旦実行してみます。

$ k6 run basic-test.js

1リクエストだけ実行するサンプルができました。次に同じスクリプトを利用して2ユーザによる5秒間, 10rpsでのアクセスを試みます。この指定はスクリプト内での固定定義も可能ですし実行時の引数で動的に指定することも可能です。

$ k6 run -u 2 -d 5s --rps 10 basic-test.js

注意点

注意点として、一定の負荷を超えファイルディスクリプタが枯渇すると実行時にエラーが発生することがあります。 その際は OS上でファイルディスクリプタの最大値をチューニングすると収束します。

結果確認

結果が出力されたら内容を確認してみます。項目数が多いので面くらいますが、ポイントを抑えておけば大丈夫です。 Latencyが気になるなら http_req_duration を、Throughputなら data_received, data_sent を、そもそも全データを処理したかという点なら http_reqsを中心に確認します。

基本メトリクス

# 分類 要素名 内容 観点
1 設定 execution 実行環境 (基本は local) (設定ログ)
2 設定 output 出力先 (設定ログ)
3 設定 script シナリオスクリプト (設定ログ)
4 設定 duration 実行時間 (設定ログ)
5 設定 iterations JSの実行回数 (設定ログ)
6 設定 vus アクティブ仮想ユーザ数 (設定ログ)
7 設定 max 最大可能仮想ユーザ数 (設定ログ)
8 - done プログレスバー -
9 結果 data_received 受信データの総量と秒間データ量 N/Wが輻輳すると秒間転送率が低下
10 結果 data_sent 送信データの総量と秒間データ量 N/Wが輻輳すると秒間転送率が低下
11 結果 checks check関数がある場合の結果 -

HTTP系メトリクス

# 分類 要素名 内容 観点
12 結果 http_reqs k6が生成した総リクエスト数 指定との乖離大は N/W・Server 遅延の可能性
13 結果 http_req_blocked 空きTCPコネクションの待ち時間 TCPの接続プールは充分か
14 結果 http_req_looking_up DNSの名前解決に費やした時間 キャッシュは適切か
15 結果 http_req_tls_handshaking TLSセッションのハンドシェイクに費やした時間 接続におけるTLSの負荷は高いか
16 結果 http_req_sending リモートホストへのデータ送信にかかった時間 送信は遅くないか
17 結果 http_req_waiting リモートホストからの応答待ちにかかった時間 (= TTFB) サーバ処理は遅くないか
18 結果 http_req_receiving リモートホストからのデータ受信にかかった時間 受信は遅くないか
19 結果 http_req_duration リクエスト単体の合計時間 (sending + waiting + receiving) (接続・DNS lookupは含まない) 全体で遅くないか

(Option) レスポンスチェック

性能試験の結果に成功条件を盛り込みたい場合 check 関数を利用して実現することができます。
例えば つぎのスクリプトは 2種類のチェックを行っています。

  • ステータスコードが 200 (成功) であること
  • レスポンスタイムが 3秒 (3000ms) 以内であること
import { check } from "k6";
import http from "k6/http";

export default function() {
  let res = http.get("http://test.loadimpact.com/");
  check(res, {
    "is status 200": (r) => r.status === 200,
    "duration < 3000ms": (r) => r.timings.duration < 3000
  });
}

この様にして実行すると、実行結果上にチェックの結果も追記されます。

この際 ✓ 18 がOKで ✗ 0 がNGを意味します。日本と海外では の意味が逆だったりするので騙されないでください。 また、上記は全件OKですが、NGがある場合はチェック項目ごとに OK数と NG数が表示されます。

✓ status != 4xx
✓ status != 5xx
✗ duration < 3000ms
↳ 99% — ✓ 297 / ✗ 3

参考

まとめ

  • golang 利用で並列実行が強力
  • 環境構築が楽ちん
  • 実シナリオファイルは JavaScript という親切設計