- 伊藤真彦
- 約 3,400 文字
- 12,900 View
TIGの伊藤真彦です。
業務で行っている開発がいよいよリリースを視野に入れたフェーズに入り、E2Eテストや各種性能試験をしました。
負荷試験とは
リリース前に行いたい試験の1つに負荷試験があります。
なるべく実際の運用に近い環境、データベースの状態を整え、実際に利用されるであろうユーザー数、もしくはそれ以上の同時接続にシステムが耐えられるかを試験します。特にソーシャルゲームの世界では想定を超えたアクセスによりリリース直後にサーバーがダウンしてしまう悲劇が発生しがちです。IT業界の外にいる人々にとっても覚えのある経験かもしれません。
そんな負荷試験ですが、実際に数百人、数万人規模の同時アクセスを人力で再現するには膨大な予算が必要です。そのため、一台のコンピュータで複数人からの同時アクセスを再現する負荷試験ツールが数多く存在します。
負荷試験ツールの定番と言えばApache Jmeterがあります。改めて確認してみたところ2021年をもって生誕20周年を記念する老舗プロダクトでした、おめでとうございます。
Jmeterの使用は勿論検討したのですが、モダンな技術が大好きな性分であり、我らが渋川さんもおススメしているためk6を試してみました。
k6とは
2016年頃から開発がスタートした負荷試験ツールです。
ワニのキャラクターが印象的です、かわいいですね。
OSSとして公開されている事が特徴です、リポジトリはこちらです。
k6はGoで開発されています、これだけでも今時な印象を受けますね。
公式サイトの説明にある通り。
DevOpsの概念の成熟、現在のあり方に対応し、継続的な性能試験を行えるものである事を意識して設計されています。
In tandem with the growth of DevOps, we started to notice gaps emerging in the market that we knew we could address. Users were no longer testing things one-off. APIs were becoming more prevalent in usage and required testing. Users wanted to test continuously. For many companies, testing was moving into the responsibility of developers.
k6のインストール
k6のインストールはどのプラットフォームであっても簡単です。
installationに記載があります、書いてあるコマンドをコピー&ペーストするだけで問題なく導入できました。
Windows向けにはインストーラが用意されています。
brew, apt-get, yum, dokcerでの配布がサポートされています、バイナリ形式でダウンロードもできます、インストールに苦戦することはほぼ無いと言っても良いと思います。
docker形式の配布形態を利用し、CIで性能試験し、デフォルトの性能を下回ったら警告するような使い方もできるかもしれません。
k6の使い方
基本的な利用方法
k6は基本的に負荷試験のシナリオをJavaScriptで記載し、CLIで実行する利用形態で負荷試験を行います。
import http from 'k6/http'; |
各種ユーティリティをimportし、負荷試験のシナリオを記載します。
特定のエンドポイント1か所にGETでアクセスするだけなら、上記のような4行程度の記載でテストを行うことが可能です。
今回は下記のシンプルなWebサーバーをローカル環境に立てて上記k6_test.jsの動作を検証します。
package main |
k6 run ファイル名 で実行できます。
アスキーアートと試験結果が出力されます。
k6 run .\k6_test.js |
負荷を変更する
--vusオプション--duration等のオプションで負荷の重さを変えることが可能です。
詳しくは公式ドキュメントを参照してください。
主に使うものは、下記のオプションです。
--vus: 同時接続数 |
--vusオプションだけではエラーが発生します、試験時間、もしくはシナリオの実行回数を指定する必要があります。
k6 run .\k6_test.js --vus 10 |
同時接続数10人で10秒間負荷をかけてみます。
デフォルトの時間を超えるまでシナリオを繰り返します、レポートのiterationsを見ると999039回繰り返されたことがわかります。
k6 run .\k6_test.js --vus 10 --duration 10s |
同時接続数100人で100回シナリオを繰り返す例です。
k6 run .\k6_test.js --vus 100 --iterations 100 |
これらの負荷設定はJavaScriptに記載できます。
import http from 'k6/http'; |
stagesという書き方で段階的に負荷を変更できます。
この場合vusではなくtargetが同時接続数です。
下記の書き方の場合、同時接続数10人で1秒負荷をかけた後に20人、30人と接続数を増やしていく試験になります。--stagesのようにCLIオプションとして渡すことはできません。
import http from 'k6/http'; |
GETリクエスト以外を検証する。
動作確認ではGETリクエストを確認しましたが、k6のhttpライブラリはGETリクエスト以外も検証可能です、GET, POSTなどは勿論OPTIONSなどのリクエストも対応しています。
詳しくは公式ドキュメントを確認してください。
よく使うであろうPOST, PUT, DELETEについて簡単なスニペットを用意しました。
import http from 'k6/http'; |
import http from 'k6/http'; |
import http from 'k6/http'; |
DELETEリクエストの場合、リクエストボディにパラメータを含めることはあまり一般的ではありませんが、技術的には可能であったりといった側面に対応できるようになっています。
(k6公式ドキュメントにもDELETEリクエストのリクエストボディはセマンティクスが定まっていないため非推奨と記載があります)
リクエストの応答を検証する
サーバーが負荷に耐えきれず正常な応答を返せない割合をcheckライブラリで検証できます。
import http from 'k6/http'; |
上記コードで同時接続2万人分のリクエストの1割を捌くことに失敗することをレポートできました。
k6 run k6_test.js --vus 20000 --iterations 20000 |
ちなみに26000人~29000人分のアクセスを再現するあたりで64GBのメモリを使い切り動かなくなりました。
要求スペック的には1000人オーダーであれば8~16GBのメモリのマシンであっても耐えられそうです。
メモリに余裕のない環境ではマシンスペックの限界を超えたときにGoのランタイムエラーが出力され、Go製ツールであることを感じることができます。
check関数はそのまま真偽値として扱う事が可能です。
試験の失敗をログ出力するfailライブラリと組み合わせることが可能です。
import http from 'k6/http'; |
その他テストシナリオの品質を高めるためのユーティリティ等が沢山用意されています、詳しくは公式ドキュメントのjavascript-apiの章を確認してください。
JavaScriptで再利用性の高い高品質なテストシナリオをどのように書いていくかが、腕の見せ所ですね。
負荷試験のアウトプットについて
試験レポートは標準出力で確認できるものを手作業で纏めるだけでも充分ではありますが、--outオプションで出力先、形式を変更できます。
k6 run .\k6_test.js --out json=out.json |
公式ドキュメントでは下記のような形式が想定されています。
| plugin | usage |
|---|---|
| Amazon CloudWatch | k6 run –out statsd |
| Apache Kafka | k6 run –out kafka |
| Cloud | k6 run –out cloud |
| CSV | k6 run –out csv |
| Datadog | k6 run –out datadog |
| InfluxDB | k6 run –out influxdb |
| JSON | k6 run –out json |
| New Relic | k6 run –out statsd |
| StatsD | k6 run –out statsd |
公式のダッシュボードであるk6 Cloudも提供されています。
試験結果の可視化、前回との差分の比較を様々な手段で行う事や、CloudWatchのメトリクスとして定期的なパフォーマンスチェックを行う監視システムの構築等が想像できます。
これらの機能の存在からも現在のDevOpsの成長に追従した継続的な性能試験という設計思想を感じることができます。
まとめ
- k6はGoで開発されたモダンな負荷試験ツールです。
- 軽快なフットワークでインストールが可能です。
- JavaScriptで書いたシナリオを実行する形で利用します。
- 試験結果は様々な外部システムと組み合わせることが可能です。
負荷試験を検討の際はぜひ選択肢の1つとして検討してみてください。