wrk: コマンドラインでAPIの負荷テストを行う方法

コマンドラインからwrkでAPIをロードテストする方法:インストール、スレッドとコネクションのフラグ、レイテンシ出力の読み方、LuaによるPOSTリクエスト。

Ashley Innocent

Ashley Innocent

6 7月 2026

wrk: コマンドラインでAPIの負荷テストを行う方法

Apidog エンタープライズ

オンプレミスデプロイ

SSO & RBAC

SOC 2 準拠

Apidog Enterpriseを見る

エンドポイントをリリースしました。ブラウザでは動作します。しかし、400人が同時にアクセスしたときに何が起こるか、あなたは全く知りません。レイテンシは一定のままですか、それとも99パーセンタイルは跳ね上がりますか?そのボックスは毎秒1,000リクエストを処理できますか、それとも300で落ちてしまいますか?

wrkがそれに答えます。これは、URLに大量のHTTPトラフィックを発生させ、その負荷の下でサーバーがどれだけ速く応答したかを報告する小さなコマンドラインツールです。

ボタン

wrkとは何か、そしていつ使うべきか

wrkは最新のHTTPベンチマークツールです。単一のマルチコアマシンから負荷を生成し、サーバーが返すレイテンシとリクエストレートを測定します。マルチスレッドとスケーラブルなイベントループ(Linuxではepoll、macOSではkqueue)を使用するため、1つのインスタンスで多数の負荷生成ボックスを必要とせずに大量のトラフィックをプッシュできます。

生のパフォーマンス数値が必要な場合は、wrkを利用しましょう。

wrkはベンチマークツールであり、テストスイートではありません。速度を測定します。JSONボディが正しいか、ステータスコードが200であるか、API契約が維持されているかを確認しません。この区別を心に留めておいてください。実際のテストワークフローにwrkをどのように組み込むかという点で重要になるため、この点については後で詳しく説明します。まず全体像を把握したい場合は、このAPI負荷テストガイドがwrkが実践する概念をカバーしています。

wrkのインストール

macOS

Homebrewにはビルド済みのバイナリがあり、これが最も簡単な方法です。

brew install wrk

Apple Siliconではこれが重要です。ソースからビルドするとLuaJIT ARM64の問題に遭遇する可能性があり、Homebrewのバイナリを使用すればその手間を省けます。

Linux (ソースからビルド)

公式のaptパッケージがないため、自分でビルドします。まずツールチェーンとOpenSSLヘッダーをインストールしてください。

sudo apt-get install build-essential libssl-dev git -y

次にクローンしてコンパイルします。

git clone https://github.com/wg/wrk.git
cd wrk
make

これにより、現在のディレクトリにwrkバイナリが生成されます。どこからでも呼び出せるように、PATHに移動してください。

sudo cp wrk /usr/local/bin

実行できることを確認します。

wrk --version

基本的なコマンド

wrkの実行は常にこのような形になります。

wrk -t12 -c400 -d30s http://127.0.0.1:8080/index.html

4つのことが行われています。フラグを詳しく見ていきましょう。

常に使用するフラグがさらに2つあります。

よく利用する実行コマンドは次のようになります。

wrk -t8 -c200 -d30s --latency http://localhost:3000/api/users

8つのスレッド、200の接続、30秒間実行し、最後に完全なレイテンシ分布が出力されます。

出力の読み方

wrkは簡潔なレポートを出力します。小規模なサービスに対する実際の実行例です。

Running 5s test @ http://10.135.232.163:3000
  2 threads and 5 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     3.82ms    2.64ms  26.68ms   85.81%
    Req/Sec   550.90    202.40     0.98k    68.00%
  5494 requests in 5.01s, 1.05MB read
Requests/sec:   1096.54
Transfer/sec:    215.24KB

下から上に読んでください。最後の2行が主な結果だからです。

Requests/sec はスループットです。サーバーが平均して1秒あたりに完了したリクエスト数を示します。ここでは1,096です。これは、異なる実行間やコード変更間で比較する数値です。

Transfer/sec は帯域幅です。1秒あたりに転送されたデータ量を示します。ペイロードが大きい場合や、CPUバウンドではなく帯域幅がボトルネックになっていると思われる場合に役立ちます。

次に、平均値だけでなく分布を説明するThread Stats テーブルです。

+/- Stdev 列は、サンプルのうち1標準偏差内に収まった割合を示します。割合が低いほど、ばらつきが大きく、予測しにくいことを意味します。

5494 requests in 5.01s の行は、実際に実行がプッシュした総リクエスト量を確認します。

--latency を追加すると、wrkはパーセンタイルブロックを出力し、テールを直接確認できます。

  Latency Distribution
     50%    3.21ms
     75%    4.86ms
     90%    7.09ms
     99%   14.13ms

99パーセンタイルは注目すべき数値です。99%のリクエストが14msで完了しても、平均が3.82msであれば、100人のユーザーのうち1人は平均が示唆するよりもはるかに長く待っていることになります。平均値はテールについて嘘をつきますが、パーセンタイルはそうではありません。

LuaスクリプトでPOSTリクエストとカスタムヘッダーを送信する

デフォルトでは、wrkはGETリクエストを送信します。POSTを送信したり、ボディを追加したり、カスタムヘッダーを設定したりするには、-s オプションでLuaスクリプトを渡します。

post.luaという名前のファイルを作成します。

wrk.method = "POST"
wrk.body   = '{"name": "Ada", "role": "engineer"}'
wrk.headers["Content-Type"] = "application/json"

3つのフィールドが機能します。wrk.method はHTTP動詞を設定します。wrk.body はリクエストボディを設定します。wrk.headers は、各キーがヘッダー名であるテーブルです。

スクリプトに-sを向けて実行します。

wrk -t4 -c100 -d30s -s post.lua --latency http://localhost:3000/api/users

JSONではなくフォームエンコードされたPOSTの場合、wrkリポジトリにはこの正確な例が同梱されています。

wrk.method = "POST"
wrk.body   = "foo=bar&baz=quux"
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"

より単純なケースでは、スクリプトなしで-Hフラグを使用してヘッダーを設定することもできます。

wrk -t4 -c100 -d30s -H "Authorization: Bearer TOKEN123" --latency http://localhost:3000/api/protected

1つか2つのヘッダーには-Hを使用します。ボディ、GET以外のメソッド、またはリクエストごとのロジックが必要な場合は、Luaスクリプトを使用します。

制限事項:wrkは正しさをチェックしない

これは人々が見落としがちな部分です。wrkはサーバーがどれだけ速く応答したかを教えてくれますが、その応答が正しかったかどうかは教えてくれません。

すべてのリクエストでHTTP 500を返すエンドポイントにwrkを向けても、高いRequests/secの数値を持つきれいに見えるレポートが得られます。wrkは完了したHTTP交換を数えます。ステータスコードをアサートしたり、応答ボディをスキーマに対して検証したり、APIが意図したとおりに動作したことを確認したりはしません。サーバーがリクエストを早期に拒否する場合、1リクエストあたりの作業が少ないため、エラーでさえ高速に見えることがあります。

したがって、wrkは「負荷の下で十分に速いか?」という問いには答えます。「正しいか?」という問いには答えられません。どちらの質問も重要であり、異なるツールが必要です。壊れたエンドポイントの負荷数値は信頼すべきではありません。まさにこの理由から、チームはベンチマークツールと機能テストスイートを組み合わせます。一方は速度を証明し、もう一方は動作を証明します。

Apidogと機能テストの役割

クリーンなワークフローは、順序通りに実行される2つの層から構成されます。

機能テスト層は、ラップトップだけでなくCIでも実行されます。Apidog CLIはヘッドレスなので、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 はレポート形式(clihtmljsonjunitの1つ以上)を選択します。JUnit出力は、ほとんどのCIシステムに直接接続され、合格/不合格のゲートとして機能します。データ駆動型実行の場合、ファイルパスまたはテストデータIDとともに-d(または--iteration-data)を追加して、同じシナリオを多くの入力行で反復します。

CLIは、保存されたApidogのシナリオとスイートを実行します。これはヘッドレスであり、インタラクティブなリクエスト送信ツールではなく、ロードジェネレーターでもありません。これは正しさのゲートです。wrkは速度の測定器です。パイプラインで正しさのゲートを実行し(コピー&ペースト可能な設定については、このCLI CI/CDウォークスルーまたはGitHub Actionsガイドを参照)、スループット数値が必要なときにwrkでベンチマークを実行します。完全なCLIリファレンスには、残りのフラグが記載されています。

よくある質問

wrkとab (ApacheBench)の違いは何ですか? どちらもHTTP負荷を発生させ、毎秒のリクエスト数を報告します。wrkはマルチスレッドでイベントループを使用するため、1台のマシンからより多くの負荷を生成し、高い同時実行性をより良く処理します。abはシングルスレッドです。単一のボックスから重い負荷をかける場合、通常wrkの方がよりスケーラブルです。どちらも応答の正しさをチェックしません。

いくつのスレッドと接続を使用すべきですか? CPUコアあたり1つのスレッドから始め、シミュレートしたい同時実行レベルに接続を設定します。8コアで200の同時クライアントをシミュレートしたい場合、-t8 -c200を試してください。クライアントマシンを監視してください。もしwrk自体がCPUバウンドであれば、あなたの数値はサーバーの限界ではなく、負荷生成器の限界を反映しています。スループットが上昇しなくなるまで接続を増やしてください。

wrkはHTTPSエンドポイントをテストできますか? はい、できます。https:// URLを指すようにすると、wrkはTLSを処理します。これがLinuxビルドでlibssl-devが必要な理由です。TLSハンドシェイクは両端でCPUコストを追加するため、通常のHTTPよりもHTTPSに対する生のスループットは低くなると予想されます。

wrkは応答ボディやステータスコードを検証しますか? いいえ。wrkは完了したHTTP交換を数え、時間を測定します。ステータスコードやボディをアサートしないため、エラーを返すエンドポイントでも高いRequests/secの数値を報告することがあります。Apidog CLIを通じて実行される機能テストスイートなどを使用して正しさを検証し、その後wrkでスループットを測定してください。

負荷テストはどれくらいの期間実行すべきですか? コールドキャッシュやJITコンパイルなどのウォームアップ効果を乗り越えるのに十分な長さです。簡単な確認には数秒で十分ですが、30秒から数分間実行すると、より安定した数値が得られ、持続的な負荷の下でのみ現れる劣化を明らかにできます。健全なデフォルトとして-d30sを使用し、遅いメモリリークなどを追跡している場合は、それを長くしてください。

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

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