システムリリース前の負荷テストにおいて、「JMeterでテストを実行した際は問題なかったが、本番稼働後に想定以上の負荷でシステムが遅延・停止した」というトラブルは少なくありません。この原因の多くは、JMeterのシナリオが実運用のアクセスパターンやユーザーの挙動を十分に再現できていないことにあります。
この記事では、実運用に近い負荷シナリオをJMeterで構築するための具体的な設計手法、設定例、およびテスト実施前のチェックリストについて解説します。
対象読者と前提条件
- 対象読者: JMeterの基本的な操作(スレッドグループ、サンプラー、リスナーの追加など)を理解しており、実務で負荷テストのシナリオ設計を担当するエンジニア。
- 前提条件: JMeter 5.0以降のバージョンを使用していることを想定しています。テスト対象のWebアプリケーションやAPIの仕様が定義されている必要があります。
実運用と乖離しやすい3つのポイントと対策
JMeterのデフォルト設定や単純なレコーディングのみで作成したシナリオは、以下の3点において実運用と大きく乖離しがちです。
- リクエストの間隔(思考時間)の欠如
- セッションやキャッシュの不適切な扱い
- データパターンの固定化(同一パラメータの繰り返し)
それぞれの対策と具体的な設定方法を説明します。
1. 思考時間(Think Time)の適切な設定
人間がブラウザを操作する場合、ページが表示されてから次のリンクをクリックするまでに数秒から数十秒の「思考時間」が発生します。思考時間を設定しない場合、JMeterはミリ秒単位で連続してリクエストを送信するため、実運用よりも極端に高い負荷が短時間に集中します。
対策: 「定数タイマ」ではなく「ガウスランダムタイマ」または「一様ランダムタイマ」を使用する
常に一定の間隔でリクエストを送る「定数タイマ」は、実運用のばらつきを再現できません。ランダムタイマを使用することで、ユーザーごとの操作間隔の揺らぎを再現します。
-
設定例(一様ランダムタイマ / Uniform Random Timer):
-
Delay Offset (ms):
3000(基本となる待ち時間:3秒) -
Random Delay Maximum (ms):
2000(追加されるランダムな待ち時間:最大2秒) - この設定により、リクエスト間の待ち時間は 3,000ms 〜 5,000ms の間でランダムに決定されます。
-
Delay Offset (ms):
2. キャッシュとCookieの制御
ブラウザは通常、静的ファイル(CSS、JavaScript、画像など)をキャッシュし、2回目以降のアクセスではサーバーへのリクエストを省略または軽量化(304 Not Modified)します。また、ログイン状態の維持にはCookieが使用されます。
対策: 専用のマネージャー要素を追加する
スレッドグループの直下に以下の要素を追加し、ブラウザの挙動をシミュレートします。
-
HTTP クッキーマネージャ (HTTP Cookie Manager):
- 「各繰り返しでクッキーをクリア? (Clear cookies each iteration?)」を有効にするか否かは、テストの目的に応じて判断します。
- 新規ユーザーが次々と訪れるシナリオ: 有効にする
- 同一ユーザーがログインしたまま操作を続けるシナリオ: 無効にする
- 「各繰り返しでクッキーをクリア? (Clear cookies each iteration?)」を有効にするか否かは、テストの目的に応じて判断します。
-
HTTP キャッシュマネージャ (HTTP Cache Manager):
- 「各繰り返しでキャッシュをクリア? (Clear cache each iteration?)」を有効にすることで、スレッドのループごとに初回アクセス(キャッシュなし状態)を再現できます。
3. 送信データの動的パラメータ化
すべてのスレッドが同じIDや検索キーワードでリクエストを送信すると、データベースやアプリケーションサーバー側でキャッシュが効いてしまい、本来の負荷がかからない場合があります。また、一意制約のある項目(ユーザー登録など)では、2件目以降のリクエストがエラーになります。
対策: CSV Data Set Config によるデータの分散化
テストデータを記述したCSVファイルを用意し、リクエストパラメータを動的に変更します。
-
CSVファイルの例 (
test_users.csv):user01,passWord123 user02,passWord456 user03,passWord789 -
CSV Data Set Config の設定例:
-
Filename:
test_users.csv(相対パスまたは絶対パス) -
Variable Names:
USERNAME,PASSWORD -
Sharing mode:
All threads(すべてのスレッドでデータを共有し、重複を防ぐ)
-
Filename:
-
HTTP リクエストでの使用例:
- パラメータ値に
${USERNAME}や${PASSWORD}と記述して呼び出します。
- パラメータ値に
負荷シナリオ設計の比較表
実運用に近いシナリオ(推奨)と、不適切なシナリオ(非推奨)の構成の違いを以下にまとめます。
| 項目 | 非推奨な例(単純なシナリオ) | 推奨される例(実運用に近いシナリオ) | 影響と効果 |
|---|---|---|---|
| リクエスト間隔 | タイマなし(連続送信) | ランダムタイマ(3〜5秒など) | サーバーへの瞬間的なスパイクを防ぎ、現実的な同時接続数を再現する。 |
| 静的コンテンツ | すべて無視、またはすべて毎回取得 | キャッシュマネージャを使用 | ネットワーク帯域とWebサーバーのコネクション消費を実態に近づける。 |
| テストデータ | 同一のIDやパラメータを固定で使用 | CSVファイル等から動的にインジェクション | DBキャッシュによるレスポンスの「見かけ上の高速化」を防ぐ。 |
| セッション管理 | Cookieを考慮せずエラーになる | HTTPクッキーマネージャを使用 | ログインやカート保持など、状態を持つ遷移を正確にテストする。 |
実務用:負荷シナリオ作成チェックリスト
テスト計画・シナリオ作成時に、以下の項目が満たされているか確認してください。
-
テスト環境のスペックは本番環境とスケールが合っているか
- スペックが異なる場合は、結果から本番の性能をどう推測するか(線形スケールするか等)の基準が合意されていること。
-
ネットワーク経路(CDN、WAF、ロードバランサー)を考慮しているか
- テスト元IPアドレスがWAFやDDos対策機能によってブロックされないよう、事前に除外設定やIPホワイトリスト登録を行っていること。
-
スレッド数(同時実行数)とランプアップ期間(Ramp-Up Period)は適切か
- 開始直後に全スレッドが一斉にリクエストを送る設定(Ramp-Upが極端に短い)になっていないこと。
-
エラーハンドリング(アサーション)が設定されているか
- ステータスコード
200 OKだけでなく、レスポンスボディに特定のエラーメッセージ(例: "システムエラーが発生しました")が含まれていないかを検証する「応答アサーション」が入っていること。
- ステータスコード
-
JMeter実行マシンのリソース限界に達していないか
- GUIモードで負荷テストを実行していないこと(本番テストは必ず
-nオプションを使用したCLIモードで実行する)。
- GUIモードで負荷テストを実行していないこと(本番テストは必ず
CLIモードでの実行コマンド例
JMeterのGUIはシナリオ作成・デバッグ用です。実際の負荷テスト実行時は、JMeter自体のリソース消費を抑えるためにCLIモードを使用します。
jmeter -n -t scenario.jmx -l results.jtl -e -o ./report
-
-n: 非GUI(CLI)モードで実行 -
-t: 実行するJMXシナリオファイルのパス -
-l: 結果を保存するJTLファイルのパス -
-e: テスト終了後にダッシュボードレポートを生成 -
-o: レポートを出力するディレクトリのパス
注意点とまとめ
- 最新情報の確認: JMeterのバージョンアップに伴い、推奨されるプラグインや設定項目の挙動が変更される場合があります。実装時には必ずApache JMeter公式ドキュメントを確認してください。
- 段階的な負荷適用: 最初から最大負荷をかけるのではなく、まずは1スレッド、次に想定の10%、50%と段階的に負荷を上げてシナリオ自体の動作やエラーの有無を確認してください。
実運用に近い負荷テストを実施するためには、単にツールを動かすだけでなく、実際のユーザー行動ログ(アクセスログなど)を分析し、それに近いアクセス比率や遷移パターンをシナリオに落とし込むことが重要です。