k6使ってDBの負荷テスト環境を構築してみた


はじめに

DBに対してSQL叩いて負荷テストしたいなぁ、という要件があり、その際にk6を利用し実施したことがあったので、内容についてまとめておこうという記事です。

k6とは

k6はオープンソースの負荷テストツールです。
無料、開発者中心、拡張可能という特徴があります。

k6を利用し、システムの信頼性やパフォーマンスをテストすることで、耐障害性とパフォーマンスの高いアプリケーションの構築をすることができます。

環境

今回はMacのローカル環境にk6xk6-sql(SQLを実行する拡張機能)を導入します。

  • macOS Montery (12.1)
  • k6 (0.36.1)
  • xk6 (v0.6.1)
  • go (1.17.8)

導入

goのインストール

拡張機能のインストールの関係で、goenvから導入します。

goをインストール

$ goenv install 1.17.8

有効化

$ goenv global 1.17.8

コマンドが実行できれば完了

$ go version
go version go1.17.8 darwin/arm64

k6とxk6-sqlのインストール

k6をインストール

$ go install go.k6.io/[email protected]

xk6をインストール

$ go install go.k6.io/xk6/cmd/[email protected]

作業用ディレクトリに移動

$ cd /path/to/workspace

xk6-sqlのビルドコマンドを実行

$ CGO_ENABLED=1 xk6 build master \
  --with github.com/grafana/xk6-sql

作業ディレクトリ直下にk6ファイルが作成されていることを確認

$ ls 
k6

作成したk6の実行が確認できたら完了

$ ./k6 version
k6 v0.36.0 ((devel), go1.17.8, darwin/arm64)

実行

今回はローカル環境にPostgreSQLの環境が既にあるものとして、PostgreSQLの接続をするようなシナリオを作成します。

シナリオの実装

シナリオの実装はJSで行います。
PostgreSQLに接続し、SQLを実行するコードは以下のようになります。

//
// postgreSQLに接続するサンプル
//
import sql from ‘k6/x/sql’;

// ユーザー名
const userName = ‘user’;
// パスワード
const password = ‘password’;
// ホスト名
const hostName =127.0.0.1;
// ポート番号
const port =5432;
// DB名
const dbName = ‘postgres’
// SSLモード
const sslMode = ‘sslmode=disable’

// 接続情報から接続用の文字列を作成
const connectionString = `postgres://${userName}:${password}@${hostName}:${port}/${dbName}?${sslMode}`;

// DBへ接続
const db = sql.open(“postgres”, connectionString);

export function setup() {
  db.exec(`CREATE TABLE IF NOT EXISTS table (
          key varchar,
          value varchar);`);
}
export function teardown() {
  db.close();
}
export default () => {
  db.exec(INSERT INTO table (key, value) VALUES (‘plugin-name’, ‘k6-plugin-sql’););
  let results = sql.query(db,SELECT * FROM table;);
  for (const row of results) {
    console.log(`key: ${row.key}, value: ${row.value}`);
  }
}

実際に実行すると以下のような結果が表示されます。

$ ./k6 run scenario.js

          /\      |‾‾| /‾‾/   /‾‾/
     /\  /  \     |  |/  /   /  /
    /  \/    \    |     (   /   ‾‾\
   /          \   |  |\  \ |  (‾)  |
  / __________ \  |__| \__\ \_____/ .io
  execution: local
     script: ./script.js
     output: -
  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)
INFO[0002] key: plugin-name, value: k6-plugin-sql        source=console
running (00m01.9s), 0/1 VUs, 1 complete and 0 interrupted iterations
default ✓ [======================================] 1 VUs  00m00.7s/10m0s  1/1 iters, 1 per VU
     █ setup
     █ teardown
     data_received........: 0 B 0 B/s
     data_sent............: 0 B 0 B/s
     iteration_duration...: avg=628.31ms min=53.58µs med=664.73ms max=1.22s p(90)=1.1s p(95)=1.16s
     iterations...........: 1   0.529856/s
     vus..................: 0   min=0      max=0
     vus_max..............: 1   min=1      max=1

これでDBに対しSQLを直接実行できるようになりました。
後は必要に応じて、シナリオの内容を変更するだけです。

さいごに

k6を使ってDBに対しSQLを直接実行できる環境を構築するところまでをまとめました。
k6は機能が豊富なSaasであり、ここでは書ききれなかった数多くの機能があります。その辺りはドキュメントに記載がありますので、必要に応じて参照してください。
それでは!

参考