あなたはエンドポイントを出荷しました。Postmanでは正しいJSONが返されます。しかし、200のクライアントが同時にアクセスしたときに何が起こるか全く分かりません。毎秒500リクエストを処理できるのか、それとも50リクエストでレイテンシが崩壊するのか?ApacheBenchは、その疑問をたった1つのコマンドで解決します。
abとして呼び出されるApacheBenchは、単一のURLに対して固定数のHTTPリクエストを発行し、スループットとレイテンシを報告するコマンドラインツールです。Apache HTTP Serverに同梱されており、何十年も前から存在します。小さくて実行が速く、1つのエンドポイントがどれだけの負荷に耐えられるかを素早く把握できます。
このガイドでは、abのインストール、基本的なテストの実行、POSTエンドポイントのテスト、出力の読み方、そしてabが適切なツールでなくなるタイミングについて説明します。ここにあるすべてのコマンドは、公式のApache abリファレンスに記載されているフラグに対応しています。
ApacheBenchとは何か、どこから来たのか
abは、Apache HTTP Serverにバンドルされているベンチマーククライアントです。名前はApacheBenchの略です。単一のURLに接続を開き、同時実行設定が許す限り高速にリクエストを送信し、各レスポンスの時間を計測して、概要を出力します。

それは1つのことをうまく測定します。単一のエンドポイントが毎秒どれだけのリクエストを処理できるか、そして負荷がかかったときにレスポンス時間がどのように分散されるかです。これは、1つのURLに対するスループットとレイテンシです。
何ができないかも同様に重要です。abは、レスポンスボディが正しいかどうかを確認しません。スキーマを検証したり、フィールドをアサートしたりしません。ログイン、取得、更新といった多段階のフローをたどることもありません。1つのURLにアクセスし、数を数えるだけです。この範囲を念頭に置けば、abは有用であり続けます。それ以上を期待すると、がっかりするでしょう。
abが適合する分野のより広い視野を知りたい場合は、API負荷テストとは何か、そしてAPIレスポンス時間がなぜ重要かを参照してください。
abのインストール
abはApacheユーティリティと一緒にパッケージ化されています。パッケージ名はプラットフォームによって異なります。
DebianおよびUbuntuでは、apache2-utilsパッケージをインストールします。
sudo apt-get update
sudo apt-get install -y apache2-utils
CentOS、RHEL、およびFedoraでは、パッケージはhttpd-toolsです。
# CentOS 7
sudo yum install -y httpd-tools
# Fedora and CentOS 8+
sudo dnf install -y httpd-tools
macOSでは、システムにApacheが同梱されているため、abはすでに存在します。確認してください。
ab -V
Version 2.3のようなバージョン行が表示されるはずです。macOSでコマンドが見つからない場合は、HomebrewのApacheフォーミュラを通じてインストールしてください。ab -Vがバージョンを出力すれば準備完了です。
基本的な負荷テストの実行
毎回使用する2つのフラグは-nと-cです。
-n requestsは実行するリクエストの総数を設定します。デフォルトは1つのリクエストですが、これでは何もわからないので、常に設定してください。-c concurrencyは同時に実行するリクエストの数を設定します。デフォルトは1で、完全にシリアルであることを意味します。
以下は、JSONエンドポイントに対して1000リクエストを50同時実行で実行する例です。
ab -n 1000 -c 50 https://api.example.com/v1/users
末尾のパスに注意してください。abにはパスを含む完全なURLが必要です。パスのない裸のホストを指定すると、エラーになります。ルートの場合は、末尾のスラッシュを使用します: https://api.example.com/。
実際のクライアントは、リクエストごとに新しい接続を開く代わりにTCP接続を再利用します。HTTP KeepAliveを有効にする-kを追加して、abがセッション内で接続を再利用するようにします。
ab -n 1000 -c 50 -k https://api.example.com/v1/users
-kを使った実行は、通常、ブラウザや適切に動作するAPIクライアントの動作により近いです。なぜなら、すべてのリクエストで接続設定のコストを支払うのを避けるからです。両方の数値を比較して、レイテンシのうち接続オーバーヘッドがどれくらいを占めているかを確認してください。
実行を回数ではなく時間で制限することもできます。-tは最大秒数を設定し、内部的には-n 50000を意味するため、最初に達した制限でテストは停止します。
ab -t 30 -c 50 -k https://api.example.com/v1/users
これは、同時実行数50で最大30秒間実行されます。固定回数ではなく固定期間の測定を行いたい場合に便利です。
POSTエンドポイントのテスト
ほとんどのAPIの作業はGETではありません。POSTをテストするには、リクエストボディをファイルに入れ、-pで渡します。また、-Tでコンテンツタイプを設定する必要があります。さもないと、サーバーはボディを拒否します。
ペイロードを作成します。
cat > payload.json <<'EOF'
{"name": "Ada Lovelace", "email": "ada@example.com"}
EOF
そして送信します。
ab -n 500 -c 25 -k \
-p payload.json \
-T application/json \
https://api.example.com/v1/users
-pフラグはPOSTボディを含むファイル名を指定します。-TフラグはContent-Typeヘッダーを設定します。デフォルトのコンテンツタイプはtext/plainですが、これはJSON APIが求めるものではほとんどないため、明示的に-T application/jsonを設定してください。
エンドポイントが認証や他のヘッダーを必要とする場合は、-Hで追加します。各ヘッダーに対してフラグを繰り返します。
ab -n 500 -c 25 -k \
-p payload.json \
-T application/json \
-H "Authorization: Bearer YOUR_TOKEN" \
https://api.example.com/v1/users
JSONリクエストボディを手動で構築する方法の復習については、curlでJSONデータをPOSTする方法を参照してください。同じボディがabペイロードファイルとしても機能します。
出力の読み方
実行すると、数値のブロックが出力されます。トリミングされた例を以下に示します。
Concurrency Level: 50
Time taken for tests: 4.212 seconds
Complete requests: 1000
Failed requests: 0
Non-2xx responses: 0
Requests per second: 237.42 [#/sec] (mean)
Time per request: 210.598 [ms] (mean)
Time per request: 4.212 [ms] (mean, across all concurrent requests)
Transfer rate: 142.31 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 5 18 9.4 16 64
Processing: 22 189 41.2 182 310
Waiting: 21 177 39.8 171 295
Total: 31 207 42.7 201 338
Percentage of the requests served within a certain time (ms)
50% 201
66% 221
75% 236
90% 268
95% 291
99% 324
100% 338 (longest request)
まず、これらのフィールドを読みます。
- Requests per second (毎秒リクエスト数) は、スループットの主要な指標です。リクエスト数を総時間で割ったものです。数値が高いほど良いです。
- Failed requests (失敗したリクエスト) と Non-2xx responses (2xx以外のレスポンス) は、サーバーが実際に負荷を処理できたか、エラーが発生し始めたかを示します。レスポンスの半分が500エラーの場合、高い毎秒リクエスト数には意味がありません。スループットの数値を信頼する前に、常にこれら2つを確認してください。
- Time per request (リクエストあたりの時間) は2回表示されます。最初の行は、単一ユーザーが待つ平均時間(同時実行数に総時間を掛けてリクエスト数で割ったもの)です。2番目の行は「全同時実行リクエストにわたる平均」と表示され、完了したリクエスト間の平均ギャップです。ユーザーが感じるのは最初の数値です。
「Percentage of the requests served within a certain time (ms)」の表が最も役立ちます。これはパーセンタイルごとの内訳です。50%の行が中央値です。95%と99%の行は遅延のテールを示します。この例では、リクエストの半分が201msまでに完了しましたが、1%は324ms以上かかりました。テールレイテンシは実際のユーザーが影響を受ける部分なので、平均よりも95パーセンタイルと99パーセンタイルに注目してください。
チャート用の生のリクエストごとの数値が必要ですか?-e results.csvを追加すると、パーセンタイルと時間のペアのCSVファイルが書き込まれます。-g results.tsvを追加すると、gnuplotで使いやすいファイルが生成されます。
abが適切なツールでなくなる場合
abは意図的に範囲が狭いです。誤用を避けるために、その制限を明確に述べる価値があります。
実行につき1つのURL。 abは単一のエンドポイントを攻撃します。認証、リソースの作成、その後の読み取りといった一連のスクリプトは実行できません。実際のユーザーの行動は多くのエンドポイントに順番に触れるものであり、abにはその概念がありません。
正確性のチェックなし。 abはステータスコードとバイト長を数えます。JSONを解析したり、フィールドが期待値と等しいことをアサートしたりしません。レスポンスは構造的に間違っていても、成功としてカウントされることがあります。負荷の数値は、合格するテストスイートの代わりにはなりません。
HTTP処理の古さ。 公式ドキュメントには、abがHTTP/1.xを完全に実装しておらず、一部の期待される形式のレスポンスのみを受け入れると記載されています。HTTP/2のサポートはありません。HTTP/2で異なる動作をするサーバーの場合、abはその動作を反映しません。
単一マシンの負荷。 abは1つのマシンと1つのプロセスから実行されます。特定の同時実行数を超えると、サーバーの限界ではなく、自身のクライアントの限界を測定することになります。ドキュメントには、ab自身の解析がプロファイルでボトルネックとして現れる可能性があると警告されています。
これらすべてがabを悪いものにするわけではありません。これらはabを特定のツール、つまり1つのエンドポイントに対する高速なスループットプローブにするものです。スクリプト化されたフロー、分散負荷、またはHTTP/2が必要な場合は、そのために構築されたツールを使用してください。JMeterは多段階のシナリオと分散実行を処理でき、オプションを比較している場合は負荷テストツールのより広範なまとめがあります。
機能テストが役立つ場面
スループットは一つの軸です。正確性はもう一つの軸であり、abはそれに触れません。エンドポイントの負荷テストを行う前に、それが通常の条件下で正しい形式の正しいデータを返すことを知る必要があります。それが機能テストと契約テストであり、それは異なる仕事です。
ここで、完全なAPIプラットフォームがabと並んでその役割を果たします。Apidogを使用すると、視覚的なアサーションでテストシナリオを構築し、リクエストを多段階のフローに連結し、スキーマに対してレスポンスを検証することができます。これらはabが設計上できないことです。これらのシナリオを一度保存すれば、どこでも実行できます。
継続的インテグレーションのために、Apidog CLIは保存されたシナリオをヘッドレスで実行します。Nodeでインストールします。
npm install -g apidog-cli
次に、選択した環境に対して保存されたシナリオまたはスイートを実行し、CIがアーカイブできるレポートを出力します。
apidog run \
--access-token "$APIDOG_ACCESS_TOKEN" \
-t \
-e \
-r cli,html,junit
-tフラグは、保存されたシナリオ、フォルダー、またはスイートをIDで指定します。-eフラグは環境を選択します。-rフラグは、cli、html、json、junitの中から1つ以上のレポーターを選択します。データ駆動型実行の場合、-d(または--iteration-data)をデータファイルのパスまたはテストデータIDとともに追加します。CLIはヘッドレスで保存されたシナリオを実行するため、Nodeを実行できるCIステップに適合します。これはリクエスト送信者でもロードジェネレーターでもなく、abが実行することを意図していなかった機能テストを実行します。
健全なセットアップでは両方を使用します。Apidogシナリオを実行してエンドポイントが正しいことを証明します。abを実行して十分な速度であることを証明します。正確性の側面については、Apidogのパフォーマンス テスト ガイドと一般的なAPIパフォーマンス テスト チュートリアルを参照してください。
よくある質問
ApacheBenchはApacheサーバー専用ですか?
いいえ。名前とは裏腹に、abはプレーンなHTTPおよびHTTPSリクエストをあらゆるサーバーに送信します。Nginx、Node、Go、Python、またはHTTPを話すあらゆるホストに対して機能します。Apacheとの関連は、このツールがApache HTTP Serverに同梱されているという点だけです。
どの同時実行数とリクエスト数を使用すべきですか?
低い値から始めて徐々に増やしてください。-n 1000 -c 10から始め、次に-cを25、50、100と上げていき、毎秒リクエスト数が上昇を止め、失敗したリクエストが出始める点に注目してください。その変曲点が、おおよそエンドポイントが飽和する点です。大きな丸い数字を選ぶのではなく、ピーク時の同時実行数を予想される実際のトラフィックに合わせてください。
APIが正常に動作しているのに、失敗したリクエストが多いのはなぜですか?
abは、レスポンスの長さがリクエスト間で異なる場合(これは動的なJSONでは正常です)にリクエストを失敗としてフラグ付けします。-lフラグを追加して、長さの違いを失敗としてカウントしないようにしてください。その後、Non-2xx responsesの行を確認して、根本に実際のエラーがあるかどうかを確認します。
abはログインが必要なエンドポイントをテストできますか?
はい、トークンをすでに持っている場合です。-H "Authorization: Bearer YOUR_TOKEN"で渡します。abができないのは、最初にログインして新しいトークンを取得し、それを使用することです。それは多段階のフローであり、Apidogのようなシナリオベースのツールが必要です。
abはHTTP/2をサポートしていますか?
いいえ。abはHTTP/1.xを話し、公式ドキュメントによると、それすら完全に実装していません。HTTP/2下でのサーバーの動作が重要である場合は、代わりにHTTP/2をサポートする負荷ツールを使用してください。
