こんにちは!インフラの裏側やネットワークのロマンにどっぷり浸かっているプロトコルスペシャリストの私です。
皆さんは、自分が作ったWeb APIが「どれだけのアクセスに耐えられるか」気になったことはありませんか?「とりあえず動くものは作ったけれど、実際にたくさんの人が同時に使ったらどうなるんだろう…」と、夜も眠れなくなる瞬間、エンジニアなら一度はあるはずです。
今回は、APIの健康状態を測るための「負荷テスト」について、身近な例えを交えながら一歩ずつ優しく紐解いていきましょう!難しそうな専門用語も、蓋を開けてみれば意外とシンプルな現実世界のルールと同じなんですよ。
—
1. 郵便配達で例える「Web APIの負荷テスト」
想像してみてください。あなたが小さな郵便局の窓口係だとします。普段は1時間に数通の手紙が来る程度なので、のんびり対応できていますよね。
では、世間の大セールが始まって、一気に1000通の手紙が押し寄せてきたらどうでしょう?
- 窓口の人がパニックになって手紙を取りこぼしてしまうかもしれません。
- 手紙を受け取るまでに何時間も並ばされるかもしれません。
- 最悪の場合、窓口のカウンターがドーンと壊れてしまうかもしれません。
Web APIの負荷テストも、これと全く同じです。プログラムという「窓口」に対して、JMeterやk6といったツールを使って、わざと大量の「リクエスト(手紙)」を送りつけます。そして、システムがどこまで耐えられるか、どこで息切れするのかを観察するわけですね。
このテストで必ずチェックすべき「3つの重要メトリクス(指標)」について、詳しく見ていきましょう!
—
2. 監視すべき3つの主要パフォーマンスメトリクス
負荷テストを実行するとき、私たちはダッシュボードやコンソールに表示される数字をじっと見つめます。特に大切なのは、以下の3つの指標です。
① スループット(Throughput / RPS): 単位時間あたりの処理能力
これは「1秒間にシステムが何個のリクエストを処理できたか」を表す数字です。単位は RPS(Request Per Second)などが使われます。
郵便局の例で言えば、「1分間に何通の手紙をさばききれたか」ですね。この数字が大きければ大きいほど、働き者のAPIということになります。
② レイテンシ(Latency): 応答速度と待ち時間
これは「リクエストを投げてから、返事(レスポンス)が返ってくるまでの時間」です。
窓口に行って「これお願いします!」と言ってから、控えをもらうまでの待ち時間ですね。テストでは、平均値だけでなく「95パーセンタイル(p(95))」という値によく注目します。これは、「遅い方から数えて上位5%に入るような、一番混雑している時でもこれくらいの時間で返せているよ」という、より現実に即したシビアな指標です。
③ エラー率(Error Rate): 失敗したリクエストの割合
全体のリクエストのうち、何パーセントがエラー(500 Internal Server Error や 404 Not Found など)になってしまったかを表します。
せっかく手紙を出したのに、「すみません、今受け付けられません!」と突き返されてしまった割合ですね。これが1%を超えてくると、実運用では危険信号となります。
—
3. 実践!モダンな負荷テストツール「k6」で計測してみよう
「なんだか難しそうだな…」と思いましたか?大丈夫です!最近のトレンドであるオープンソースの負荷テストツール k6 を使えば、JavaScriptでとてもシンプルにテストを書くことができます。
まずは、実際に動かすためのテストスクリプト(load-test.js)のサンプルを見てみましょう。
import http from 'k6/http';
import { check, sleep } from 'k6';
// 負荷テストのシナリオ(段階的にアクセスを増やす設定)
export const options = {
stages: [
{ duration: '30s', target: 10 }, // 30秒かけて、ユーザー数を10人に増やす(助走)
{ duration: '1m', target: 50 }, // 1分間、50人のユーザーで維持する(本番の負荷)
{ duration: '30s', target: 0 }, // 30秒かけて、0人に戻す(クールダウン)
],
thresholds: {
// エラー率が1%未満であること
http_req_failed: ['rate<0.01'],
// リクエストの95%が500ミリ秒以内に完了していること
http_req_duration: ['p(95)<500'],
},
};
export default function () {
// テスト対象のAPIエンドポイント(ここでは自分のローカル環境を想定)
const res = http.get('http://localhost:8080/api/v1/items');
// レスポンスが正しいか(ステータスコードが200か)チェックする
check(res, {
'ステータスコードが200であること': (r) => r.status === 200,
});
// 1秒間の「待ち時間」を入れて、人間のブラウザ操作に近づける
sleep(1);
}
このコードを保存して、ターミナルで k6 run load-test.js と実行するだけで、先ほど説明したスループットやレイテンシが自動で計測されます。コメントにもある thresholds(しきい値)を設定しておけば、テストが終わった瞬間に「合格・不合格」を自動で判定してくれてとても便利ですよ!
—
4. ボトルネックを特定するための分析手法
もし負荷テストの結果、p(95) のレイテンシが跳ね上がったり、エラー率が増えたりした場合は、どこが悲鳴を上げているのか(ボトルネック)を突き止める必要があります。
郵便局に例えるなら、以下のどこが詰まっているのでしょうか?
1. 窓口の数(アプリケーションサーバのCPU/メモリ)が足りないのか?
- → サーバ自体のリソースがパンクしていないか、モニタリングツール(GrafanaやDatadogなど)でCPU使用率を確認しましょう。
2. 奥のバックヤード(データベース)での作業が遅いのか?
- → APIはすぐ返事をしたいのに、データベースに問い合わせるSQL文が重くて待たされているケースが非常に多いです。スロークエリ(時間がかかっているデータベースの処理)がないかログを覗いてみましょう。
3. ネットワークの道路が渋滞しているのか?
- → クラウドのロードバランサーやファイアウォールなどのネットワーク機器で、パケットが詰まっていないか確認します。
まずは「データベースの応答」と「アプリケーションのCPU負荷」、この2つを疑うのが早期解決の近道です。
—
まとめ:小さなテストから一歩を踏み出そう!
今回は、API負荷テストにおける主要なメトリクス(スループット、レイテンシ、エラー率)と、その分析手法について解説しました。
最初は難しく感じるかもしれませんが、要は「我が家のAPIというお店に、どれくらいのお客さんが来て、どれくらい待たされているか」を数字で可視化するだけのことです。
まずは開発環境やステージング環境で、小さな負荷テストから気軽に試してみてくださいね。きっと、あなたのAPIの知られざる一面や、改善すべきポイントが見えてくるはずです。
それでは、快適なインフラライフを!
コメント