ベジータ負荷テスト:定速HTTPチュートリアル

Vegetaロードテストについて学びます:一定レートのHTTP攻撃、インストール、攻撃/レポート/プロットのパイプライン、ターゲットファイル形式、そして機能テストがどのように組み込まれるか。

INEZA Felin-Michel

INEZA Felin-Michel

6 7月 2026

ベジータ負荷テスト:定速HTTPチュートリアル

Apidog エンタープライズ

オンプレミスデプロイ

SSO & RBAC

SOC 2 準拠

Apidog Enterpriseを見る

APIがまさに1秒あたり500リクエストでどのように動作するかを知りたいのであって、「Nスレッドがどれだけ高速に叩きつけられるか」ではありません。ほとんどの負荷ツールは同時実行数を固定し、リクエストレートを変動させます。Vegetaはその逆です。レートを設定すると、サーバーの応答に関わらず、その数のリクエストを1秒あたりに送信します。この違いは、回答シートが使用する数値、目標負荷でのスループット、およびSLOで実際に約束するであろうレイテンシを気にする場合に重要となります。ボタン

Vegetaとは

Vegetaは、Goで書かれたコマンドラインHTTP負荷テストツールです。Goライブラリとしても使用できますが、このチュートリアルではCLIに限定します。その中心的な考え方は、一定のリクエストレートです。Vegetaに「30秒間、1秒あたり100リクエストを送信する」と伝えると、必要な数のワーカーを追加してそのペースを維持します。サーバーの応答が遅くなっても、Vegetaは古いリクエストの終了を待つことなく、スケジュールどおりに新しいリクエストを発行し続けます。

この設計により、オープンモデルの負荷テストが可能になります。実際のリクエストは独自のタイミングで到着します。次のユーザーが現れる前に、ユーザーが一時停止して遅いエンドポイントを待つことはありません。レートベースのツールはその動作と一致します。

レートベースの負荷 vs 同時実行数ベースの負荷

ここでは、人々が混乱するポイントを説明します。

同時実行数ベースのツール(固定されたスレッドプールまたは仮想ユーザーがそれぞれリクエストとレスポンスをループする)は、クローズドモデルを使用します。サーバーが遅くなると、ループが停止し、実際のリクエストレートが低下します。負荷を要求したにもかかわらず、ツールは静かに処理を控えてしまいます。これは、本番環境で発生するであろうボトルネックを隠してしまいます。

Vegetaのようなレートベースのツールはオープンモデルを使用します。到着レートを固定します。サーバーが追いつけない場合、リクエストはキューにたまり、レイテンシが上昇し、レポートにそれが表示されます。需要が容量を超えたときに何が起こるかを正直に把握できます。

どちらのモデルも間違っているわけではありません。「同時に何人のユーザーを維持できるか」を知りたい場合は、同時実行数を使用します。「1秒あたり2,000リクエストで何が起こるか」を知りたい場合は、レートモデルを使用します。Vegetaは後者です。ツール領域のより広範なマップについては、「主要なAPI負荷テストツール」を参照してください。

Vegetaのインストール

セットアップに合うものを選んでください。

macOSでのHomebrew:

brew update && brew install vegeta

その他のパッケージマネージャー:

# MacPorts
port install vegeta

# Arch Linux
pacman -S vegeta

# FreeBSD
pkg install vegeta

Goがインストールされている場合、ソースから:

git clone https://github.com/tsenart/vegeta
cd vegeta
make vegeta

GitHubのリリースページからビルド済みバイナリをダウンロードすることもできます。インストールを確認するには:

vegeta --help

コアパイプライン

VegetaはUnixパイプを中心に構築されています。ターゲットが入力され、攻撃が実行され、レポートが出力されます。最小限で有用な実行は1行です。

echo "GET http://localhost:8080/" | vegeta attack -duration=5s -rate=100 | vegeta report

これを左から右に読み解きます:

  1. echoは1つのターゲット(メソッドとURL)を標準出力に書き込みます。
  2. vegeta attackは標準入力からそのターゲットを読み取り、5秒間、1秒あたり100リクエストを送信します。合計500リクエストです。
  3. vegeta reportはバイナリの結果ストリームを読み取り、要約を出力します。

-rateフラグは時間単位あたりのリクエスト数を取ります。-rate=100-rate=100/1sは同じ意味です。-rate=50/500msは500ミリ秒ごとに50リクエストを意味します。-rate=0に設定すると制限が解除され、可能な限り高速に送信されますが、これは全く異なるテストになります。

テキストレポートは次のようになります:

Requests      [total, rate, throughput]  500, 100.20, 100.18
Duration      [total, attack, wait]      4.991s, 4.990s, 1.2ms
Latencies     [min, mean, 50, 90, 95, 99, max]  412us, 1.3ms, 1.1ms, 1.9ms, 2.4ms, 5.1ms, 12ms
Bytes In      [total, mean]              128500, 257.00
Bytes Out     [total, mean]              0, 0.00
Success       [ratio]                    100.00%
Status Codes  [code:count]               200:500
Error Set:

まずレイテンシ行を読んでください。50列は中央値です。99列はテール(末端)です。つまり、リクエストの1パーセントはそれよりも遅かったということです。テールはユーザーが苦痛を感じる場所なので、平均値が良好でも99パーセンタイルがひどい場合は問題です。次にSuccess [ratio]Status Codesを確認してください。200のみで成功率100パーセントの場合、サーバーは負荷に耐えられたことを意味します。5xxコードや空でないError Setがある場合は、障害が発生し始めたことを意味します。

結果を保存し、様々な方法でレポートする

reportに直接パイプすることは、ちょっとした確認には問題ありません。再検討するようなものについては、まず生の結果をファイルに保存し、そのファイルから必要なすべてのレポートを生成します。

echo "GET http://localhost:8080/" | \
  vegeta attack -duration=10s -rate=200 -output=results.bin

これで実行結果がresults.binにキャプチャされました。テキストレポートを生成します:

vegeta report results.bin

ダッシュボードや複数回の実行間の差分比較のために、構造化されたJSONを生成します:

vegeta report -type=json results.bin > metrics.json

選択したバケットでレイテンシヒストグラムを生成します:

vegeta report -type='hist[0,2ms,5ms,10ms,25ms,100ms]' results.bin

ヒストグラムは、各レイテンシ帯域に分類されたリクエストの数をカウントします。これにより、レイテンシが密接に集中しているか、広い範囲に散らばっているかをすばやく確認できます。

ターゲットファイル形式

実際のAPIでは、1つのGETだけでなく、より多くのリクエストが必要です。ターゲットをファイルに移動し、-targetsで渡します。デフォルトのHTTP形式は行ベースで読みやすいです。

targets.txtを作成します:

GET http://localhost:8080/api/users

POST http://localhost:8080/api/users
Content-Type: application/json
@./payload.json

GET http://localhost:8080/api/users/42

これを機能させるためのいくつかのルールがあります:

JSONボディをpayload.jsonに置きます:

{ "name": "Ada", "role": "engineer" }

ファイルに対して攻撃を実行します:

vegeta attack -targets=targets.txt -rate=50 -duration=30s | vegeta report

Vegetaはターゲットを順番に巡回し、指定された時間が終了するまでループを続けます。-headerを使用してコマンドラインでグローバルヘッダーを追加することもでき、認証に便利です:

vegeta attack -targets=targets.txt -rate=50 -duration=30s \
  -header="Authorization: Bearer $TOKEN" | vegeta report

プログラムによる実行や大容量の実行の場合、VegetaはJSONターゲット形式も読み取ります。各行は1つのJSONオブジェクトであり、-format=jsonで選択します:

{"method": "GET", "url": "http://localhost:8080/api/users"}
{"method": "POST", "url": "http://localhost:8080/api/users", "header": {"Content-Type": ["application/json"]}, "body": "eyJuYW1lIjoiQWRhIn0="}

bodyフィールドはbase64エンコードされています。この形式はストリーミングによく適しており、ターゲットをオンザフライで生成し、メモリ効率のために-lazyを使用して直接パイプで渡すことができます。

プロットとヒストグラム

単一の数値ではトレンドを隠してしまいます。実行途中でレイテンシが悪化した場合、そのカーブを確認したいでしょう。Vegetaのplotコマンドは、結果ストリームをインタラクティブなHTMLページに変換します:

vegeta attack -targets=targets.txt -rate=100 -duration=60s | \
  vegeta plot > plot.html

ブラウザでplot.htmlを開きます。実行中のレイテンシの時系列チャートが表示されるため、緩やかな上昇やテスト途中のスパイクがすぐにわかります。複数の実行結果をプロットして、負荷レベルを比較することもできます:

vegeta attack -rate=50  -duration=30s -targets=targets.txt -output=50qps.bin
vegeta attack -rate=100 -duration=30s -targets=targets.txt -output=100qps.bin
vegeta plot 50qps.bin 100qps.bin > compare.html

ヘッドレス環境の場合、プロットをスキップして、encodeを使用してヒストグラムまたは生のCSVをエクスポートします:

vegeta encode -to=csv results.bin > results.csv

Vegetaを使うべきとき

レートと容量に関する質問がある場合は、Vegetaを利用してください:

これは、目的に特化したツールです。HTTPリクエストを一定のレートで送信し、サーバーがどのように応答するかを測定します。複数のステップからなるユーザーの行動を分岐ロジックでスクリプト化したり、ステータスコード以外のレスポンスボディを検証したりすることはありません。この特化が特徴であり、ツールをコンパクトにし、結果をクリーンに保ちます。

他の実行ツールと比較検討している場合、「k6負荷テスト」と「JMeter負荷テスト」の比較は、同時実行モデルの代替手段をカバーしています。基本的な概念とメトリクスについては、「APIパフォーマンステストチュートリアル」が良い入門書です。

機能テストの位置づけ

負荷テストは「十分に速いか」という問いに答えます。「正しいか」という問いには答えません。Vegetaの実行結果が100%の200番台を報告したとしても、エンドポイントが間違ったユーザー、古い価格、または不正なJSONフィールドを返している可能性があります。負荷ツールに関する限り、これらの応答はすべて高速で成功した200番台の応答です。

正しさには別のチェックが必要です。それは、レスポンスボディ、スキーマ、およびビジネスルールに対するアサーションです。それが機能テストであり、負荷実行の前に、そして負荷実行と並行して行われるべきです。健全なパターンは、APIが正しいことを検証し、次にそれがレートの下でどのように動作するかを測定することです。

ここにApidogがVegetaと競合するのではなく、補完する関係にあります。Apidogでは、ステータス、ヘッダー、JSONフィールドに対する視覚的なアサーションでテストシナリオを構築し、リクエストを連結し、データファイルからそれらを駆動します。APIが正しいデータを返すことを確認します。その後、Vegetaは、その正しいパスが1秒間に何百回もヒットしたときに、それが高速を維持していることを確認します。2つのツール、2つの質問です。

ApidogはヘッドレスCLIも提供しており、これらの機能シナリオを負荷ステップと同じCIパイプラインで実行できます。Nodeでインストールします:

npm install -g apidog-cli

次に、保存されたシナリオまたはスイートをIDで実行し、パイプライン用のレポーターを指定します:

apidog run --access-token "$APIDOG_ACCESS_TOKEN" \
  -t <scenarioOrSuiteId> \
  -e <environmentId> \
  -r cli,html,junit

-tフラグはシナリオ、フォルダー、またはスイートIDを取り、-eは環境IDを取り、-rは1つ以上のレポーター(clihtmljsonjunit)を選択します。junit出力はほとんどのCIダッシュボードに組み込まれます。ステップバイステップの実行については「Apidog CLIコマンドラインチュートリアル」を、コピー&ペーストで使えるワークフローについては「CI/CDパイプラインガイド」を参照してください。まず機能ゲートを実行し、次に合格したエンドポイントをVegetaで測定します。

よくある質問

Vegetaはボディを持つPOSTリクエストをサポートしていますか?

はい。HTTPターゲットファイルでは、最初の行にメソッドとURLを置き、Content-Typeヘッダーを追加し、@./payload.jsonでボディファイルを参照します。JSON形式では、methodurl、およびbase64エンコードされたbodyフィールドを設定します。

-rate=0は何をしますか?

レート制限を解除し、ワーカーと接続が許す限り高速にリクエストを送信します。これは最大スループットテストであり、制御された一定レートテストとは異なります。再現性のある容量測定には、明示的なレートを設定してください。

レイテンシのパーセンタイルをどのように読み取ればよいですか?

レポートのレイテンシ行は、最小値、平均値、50、90、95、99パーセンタイル、および最大値を示します。95パーセンタイルと99パーセンタイルに注目してください。これらは、実際のユーザーが遭遇する遅延の末端を表しており、平均値だけでは隠れてしまうことがあります。

VegetaはAPIが正しいデータを返すことを確認できますか?

いいえ。スループット、レイテンシ、ステータスコードを測定します。レスポンスボディやスキーマに対してアサーションは行いません。正確性を確認するには機能テストツールと組み合わせて使用し、レートとレイテンシの測定にVegetaを使用してください。

CIでVegetaを実行するにはどうすればよいですか?

標準入力を読み込み、結果を書き出す単一のバイナリであるため、どのシェルステップにも組み込めます。-outputで結果を保存し、ビルド成果物としてテキストまたはJSONレポートを生成します。ロードステップの前に、Apidog CLIのような機能ゲートを追加して、アサーションに合格したエンドポイントのみを測定するようにします。

ApidogでAPIデザイン中心のアプローチを取る

APIの開発と利用をよりシンプルなことにする方法を発見できる