負荷試験とOSSツール選定の話

この記事は 面白法人グループ Advent Calendar 2022 の15日目の記事です。

こんにちは、カヤックボンドの松本です。

今回は弊社の技術顧問をご担当いただいている、ドレッドノート株式会社の佐々木様よりご寄稿いただいた記事となります!


 みなさん、はじめまして!  主にパフォーマンスチューニングや検証用のボット開発等を行っているドレッドノート株式会社の佐々木と申します。 

 この度、カヤックグループの皆様より Advent Calendar 2022 に寄稿する機会を頂戴しましたので、2022年12月時点の方法を元に負荷試験とモダンなOSSツールについて書いてみたいと思います。

負荷試験の重要性

 突然ですが、みなさんが関わっている案件で負荷試験を行っていますか?

サービス開始前・提供中、どちらであっても負荷のかけ方によって様々な情報を得ることができます。

  • 現状の性能・台数・実装で、どの程度のアクセスを捌けるのか
  • 長時間リクエストを捌いたときの挙動や発生したデータ量
  • 負荷発生時の応答性能
  • 想定以上のアクセスが発生した場合の挙動
  • どこでボトルネックが発生するのか
  • スケールアウト動作の確認
  • インフラコスト試算

 リリース前にこうした情報を得ることは プロジェクトの成否以前にサイトがまともに動くのかという観点でとても重要 で、特に不特定多数に公開するサービスなのに負荷試験のスケジュールや予算が入っていない場合は、クライアントや偉い人に掛け合って実施することをお勧めしたいです。

負荷試験ツールの必要性

 多くの場合、同じリクエストを送り続けるだけではリリース後に発生するであろう負荷1を再現できないのではないでしょうか?

 負荷をかけた状態で各種データを取得したり検証したいのに負荷が掛けられないのではコストの無駄遣いになってしまうので、きちんと負荷が掛かる負荷試験になっているかどうかは重要なポイントです。

 稀に負荷試験の為にガッツリ手を入れて処理をバイパスしたり、専用のAPIを用意するといった類の是非を問われる事がありますが、原則2として実際の負荷とかけ離れてしまう原因は極力排除すべきと考えています。

 負荷の掛かるリクエストを効果的に発生させる為にリクエストパラメータにばらつきを持たせたり、効率よく大量のリクエストを投げ続けるには複雑なシナリオとクラスタ構成に対応した負荷試験ツールが必要なのです。

どの負荷試験ツールを使うか

 Apache BenchやApache JMeterを使って負荷試験やったことあるよ!という方もいると思いますが、結論から言ってしまえば目的(データ取得や検証)が満たせればどの負荷試験ツールでも良いと考えています。

 でも、モダンな負荷試験ツールは低スペックマシンでも効率的に高い負荷を発生させたり、コンテナ化やCIとの連携が意識されているので、まだ使ったことが無い方には是非ともモダンな負荷試験ツールを使ってみてほしいです。

 とはいえオープンソースソフトウェアとして公開されているもの3からSaaSまで含めると選択肢が多くなりすぎて、どのツールを使うか選定するだけでもけっこうな労力が必要です。

 そこで、この記事ではGitHubで公開されているオープンソースソフトウェアの負荷試験ツールから、獲得スター数順の上位トップ3に絞って、特徴や使い勝手をお伝えしていきたいと思います。

GitHubで公開されている負荷試験ツール人気トップ3

2022年12月現在、GitHubで公開されているリポジトリからトピック load-testing を指定して検索した結果は次のとおりでした。

順位 プロジェクト名 獲得スター数 作者 ライセンス
1 vegeta 20.5k Tomás Senart MIT License
2 locust 20.3k Carl Byström, Jonatan Heyman MIT License
3 k6 18.9k Grafana Labs GNU AGPL

 獲得スター数だけで見ると、オープンソース負荷試験ツールのうち上位3つは僅差でした。

続いて、個々のツールについて特徴と気になったことを挙げてみます。

1. vegeta

vegetaは一定のレートでHTTPリクエストを投げ続けるために開発され、コマンドラインから使う方法とライブラリとして利用することができます。名前の由来とか、いろいろツッコミたいのですが今回はやめておきます。

  • 主な特徴

    • 一定のレートでHTTPリクエストを投げることに重きを置いている
    • golangで実装、goroutineによるマルチスレッド動作
    • 動的なパラメータ、レスポンス処理が不要ならコマンドラインだけで完結可能
    • golangでシナリオを記述することで複雑なシナリオも実現
    • vegeta attackの出力結果をパイプでvegeta encode、vegeta plotに送ることでグラフの画像生成可能
    • MacとiTerm2を使っている場合に限り、コンソールでグラフ表示可能(jplotとjaggrが必要)
  • 気になったこと

    • HTTP前提の作りになっており、その他のプロトコルには未対応
    • 複雑なシナリオを書くためのドキュメントが少ない
    • vegeta自体にはクラスタ構成で動作するための機能はない
      • 負荷をかけたり結果の回収は自分でなんとかしないといけない(READMEにサンプルあり)

 例えば、あるファイルの中身をPOSTした後にGETする動作を毎秒2,000リクエストで30秒間流したい場合は以下のようなコマンドで負荷をかけられます。

echo -e "POST http://target/api/v1/file\n@/tmp/upload_test_payload.bin\n\nGET http://target/api/v1/list" | \
    vegeta attack -duration=3s -rate=2000 | vegeta report

 任意のHTTPヘッダを指定できるのでAuthorizationや独自ヘッダ等にも対応できますが、リクエスト毎にパラメータのばらつきを持たせたい場合や、前段のレスポンス内容を処理して次のリクエストを送りたい場合は、vegetaをライブラリとしてimportするシナリオをgolangで記述する必要があります。

vegeta attackコマンドでリクエストを投げ始めますが、出力をパイプでvegeta plotコマンドに渡してグラフを出力させたり、vegeta report -type=jsonで結果をJSONで出力させることが出来るので、CIに組み込む等してパフォーマンスを測定して比較するのに便利そうです。

2. Locust

 Locustはどんなシステムもテストできるよう、使いやすさ・テストのコード化・スケーラビリティを重視して開発された性能試験ツールです。

 LocustにはHTTPリクエストを生成するためのUser派生クラスがバンドルされていますが、自分でUser派生クラスを書くことで任意のプロトコルに対応させることが出来ます。

  • 主な特徴

    • Pythonで実装、シナリオもPythonで記述するのが基本。
      • Python以外の言語でシナリオを書いて動かすためのワーカー4実装がある。
    • Web UIが用意されており、ブラウザから負荷試験の開始や停止、パフォーマンス確認が可能
    • 大規模なクラスタ構成をサポートしているのでマスタ経由で複数のワーカーを制御可能
    • User派生クラスを自分で用意することで幅広い負荷試験に対応可能
  • 気になったこと

    • 単純なテストでも必ずシナリオファイルが必要
    • シナリオを書く際、Locustが単一スレッドで動作している点を考慮しておく必要がある
    • クラスタ構成で動かす場合、マスターと全ワーカーのシナリオを同期させておく必要がある

 弊社に相談いただく案件は専用のSDKやライブラリが必要だったり、TCPやUDPで独自仕様のパケット送受信が求められることが多いので、Python用のモジュールが提供されていない場合はPython用のバインディングを書いて対応しています。

 Locustの自由度の高さもですが、Web UIで負荷をかけたりパフォーマンスを確認できてレポートも出力しやすいため、Locustを使用することが多いです。

3. k6

 k6は開発者にとって最高の体験を提供するためにGrafana Labsが開発した負荷試験ツールです。開発元のGrafana Labsは可視化プラットフォームで有名なGrafanaの開発元です。

  • 特徴

    • 低スペックマシンでも大量のトラフィックを再現可能
    • スクリプトの再利用、ロジックのモジュール化、バージョン管理、CI連携によって試験をコード化
    • 実際のアプリケーション通信を再現する為に必要な機能を網羅したスクリプティングAPI
    • テストをJavaScriptで書くだけなのに速度面でGoの恩恵が受けられる
    • HTTP、WebSocket、gRPCなど複数のプロトコルをサポート
    • 必要に応じてエクステンションを利用してk6にプロトコルを追加したり、レポート出力を拡張できる
    • ドキュメントがとても充実している
    • オープンソースで公開されているがSaaSでも利用可能
  • 気になったこと

    • なし

 何かしら気になったことに書きたかったのですが、本当に文句のつけどころが見当たらない…。 シナリオはJavaScriptで気楽に書けるし、低スペックマシンでも効率よくリクエスト生成するし、ドキュメントも充実しているし、取得できるデータも過不足なしときて、本当に良いバランスの負荷試験ツールだな…と思います。

まとめ

個々のツールをもっと掘り下げたいものの、既に各負荷試験ツールの記事はそれなりにあがっているので使い方や詳細はそちらに譲るとして、今回ご紹介した3つのツールについて、私だったらこんな場面に向いてるんじゃないかという使いどころをまとめてみたいと思います。

vegeta

 複雑なシナリオを書くためのドキュメントが少なく、ソースを見ながら分析してウェブアプリケーション用の負荷試験を書くのはよほど時間的に余裕がない限り厳しいんじゃないかと感じました。

 リクエスト自体は複雑じゃないけど、とにかく大量のHTTPリクエストを流し続けたい場合はコマンドラインで完結できてしまうので、インフラ寄りのテストやplotで作図が出来るApache Benchの代替として重宝している方が多いのではないかと思います。

 複雑なシナリオが求められないケースであれば積極的に利用してみたいです。

Locust

 特筆すべきは何といってもクラスタ構成で大規模な負荷を無償で生成できる点と、幅広いテストに利用できる点が魅力だと思います。

 ドキュメントも充実しており、Locustに関するノウハウもネット上で多数公開されているので敷居の低さも魅力だと思います。

k6

 先にも述べたとおり、大変バランスの良い負荷試験ツールだと思います。

 あったらいいのにを綺麗に実現しました的なツールで、今後ますます利用者が増える可能性大です。

さいごに

 この記事は多少でも皆様の参考になりましたでしょうか?

 KAYAC engineers’ blogで記事を投稿するのは初めてということもあり手探りでしたが、この記事で紹介した負荷試験ツールに興味をお持ちいただいた方は是非、導入して試したり他の方の記事を参考にしてみてください。


というわけで、15日は特別寄稿記事となりました。

佐々木さん快諾頂きありがとうございました!

KAYAC engineers' blogでは、他にも負荷試験関連の記事がございますので、興味がある方は是非御覧ください! techblog.kayac.com


  1. リクエストヘッダやパラメータが同じだと常にキャッシュが効いてしまう等、負荷をかけたい場合には不都合なことが多いため。
  2. とはいえ外部サービスの多くは大量のアカウント取得や負荷試験を禁止していることが多いので必ず確認しましょう。
  3. 2022年12月現在、全部が負荷試験ツールではなさそうですがGitHub上でload-testingトピックで検索すると、公開リポジトリが647件ヒットします。
  4. 現在もメンテナンスされているようなので、興味のある方はboomer(Golang)、Locust4j(Java)を調べてみてください。