パフォーマンステスト計画#
テスト目標の明確化#
- ビジネス要件:重要なビジネスシナリオ(ログイン、支払い、照会など)のパフォーマンス指標(応答時間、スループット、エラー率など)を特定する。
- パフォーマンス指標:基準値(95% のリクエスト応答時間が 2 秒を超えない)、ピーク値(10 万人のユーザー同時接続をサポート)およびフォールトトレランスを設定する。
- 非機能要件:安定性、拡張性、リソース利用率(CPU、メモリ、ディスク I/O、ネットワーク帯域幅)など。
テスト範囲#
- システム範囲:テスト対象システム(SUT)の境界(フロントエンド、バックエンド、データベース、サードパーティサービスなど)。
- テストタイプ:負荷テスト、ストレステスト、安定性テスト、容量テストなど。
テスト環境#
- 環境構築:可能な限り本番環境と一致させる(ハードウェア構成、ネットワークトポロジー、データベース規模)。
- データ準備:実データまたはシミュレーションデータを使用する(典型的なシナリオをカバーし、データの偏りを避ける)。
シナリオ設計#
- 単一シナリオテスト:単一機能(ユーザーログインなど)のパフォーマンステスト。
- 混合シナリオテスト:実際のユーザー行動をシミュレートする(同時にログイン、注文、照会)。
- ピークテスト:突発的なトラフィックをシミュレートする(セールイベントなど)。
- 安定性テスト:長時間の実行(7×24 時間)でメモリリークやパフォーマンス低下を観察する。
実行戦略#
- 段階的加圧:低負荷から段階的にピーク負荷に増加させ、パフォーマンスの転換点を観察する。
- 複数回の反復:最適化後に再テストを行い、改善効果を検証する。
結果分析と報告#
- パフォーマンスベースライン:現在のパフォーマンス状態を基準として記録する。
- 問題特定:ログや監視データを組み合わせてボトルネックを特定する(データベースの遅いクエリ、コードのデッドロックなど)。
- 最適化提案:コード、設定、またはアーキテクチャレベルの最適化案を提案する。
パフォーマンステストの注目点#
システムレベル#
- CPU、メモリ、ディスク I/O、ネットワーク帯域幅の使用率。
- オペレーティングシステムのパラメータ設定(Linux カーネルパラメータなど)。
アプリケーションレベル#
- コードの実行効率(アルゴリズムの複雑さ、スレッドプールの設定)。
- データベースのパフォーマンス(遅いクエリ、インデックスの欠如、接続プールの設定)。
- ミドルウェアのパフォーマンス(Redis キャッシュのヒット率、メッセージキューの積み残し)。
ネットワークレベル#
- レイテンシ、パケットロス率、帯域幅のボトルネック。
- CDN またはロードバランサーのパフォーマンス。
ビジネスレベル#
- ユーザーの同時接続数、TPS(毎秒トランザクション数)、RT(応答時間)。
- ビジネス成功率(エラー率が 0.1% を超えない)。
パフォーマンステストの方法#
ベンチマークテスト(Benchmark Test)#
- 目的:システムが通常の負荷下でのパフォーマンスベースラインを特定する。
- 方法:単一ユーザーまたは低同時接続シナリオのテスト。
負荷テスト(Load Test)#
- 目的:システムが予想される負荷下でのパフォーマンスを検証する。
- 方法:同時ユーザー数を段階的に増加させ、応答時間とリソース消費を観察する。
ストレステスト(Stress Test)#
- 目的:システムのパフォーマンス限界とクラッシュポイントを見つける。
- 方法:システムがクラッシュするまで加圧を続け、最大負荷能力を記録する。
同時テスト(Concurrency Test)#
- 目的:複数のユーザーが同時に操作する際のリソース競合問題を検証する。
- 方法:高同時接続シナリオをシミュレートする(例:購入)。
安定性テスト(Endurance Test)#
- 目的:長時間の実行下でのメモリリークやパフォーマンス低下を検出する。
- 方法:12 時間以上連続して実行し、リソース使用の傾向を観察する。
容量テスト(Capacity Test)#
- 目的:システムの最大処理能力を特定し、拡張の根拠を提供する。
- 方法:データ量またはユーザー数を段階的に増加させ、パフォーマンスが基準を下回るまで。
よく使われるパフォーマンステストツール#
負荷生成ツール#
- JMeter(オープンソース):
- HTTP、JDBC、FTP など多様なプロトコルをサポート。
- 拡張性が高く、BeanShell スクリプトやプラグインをサポート。
- Web アプリケーションや API テストに適している。
- LoadRunner(商用):
- 機能が豊富で、複雑なシナリオの録画や IP 偽装をサポート。
- エンタープライズ向けの大規模システムに適している。
- Gatling(オープンソース):
- Scala ベースで高性能、レポートが直感的。
- 高同時接続シナリオに適している。
- Locust(オープンソース):
- Python ベースで分散型負荷テスト、カスタムスクリプトをサポート。
- 柔軟性が高い。
監視と分析ツール#
- Prometheus + Grafana:
- システムリソース、アプリケーション指標、およびカスタム指標をリアルタイムで監視。
- パフォーマンストレンドを視覚化表示。
- APM ツール(例:New Relic、SkyWalking):
- コードレベルのパフォーマンス問題を追跡(遅い SQL、メソッドの実行時間など)。
- JVM 監視ツール(例:JConsole、VisualVM):
- Java アプリケーションのメモリ、スレッド、GC 状況を分析。
- データベースツール(例:Percona Toolkit、MySQL 遅いクエリログ):
- SQL パフォーマンス問題を特定。
クラウドテストプラットフォーム#
- BlazeMeter:JMeter スクリプトに互換性のあるクラウド負荷テストサービス。
- AWS Load Testing:AWS に基づく分散型負荷テストソリューション。
テストシナリオとテストケース#
テストの注目点に基づく#
システムレベル#
1. CPU 使用率
- シナリオ:高同時接続ユーザーリクエストによる CPU 負荷の上昇。
- 用例:1000 の同時ユーザーがクエリ操作を実行するシミュレーション、10 分間継続。
- ステップ:
- JMeter を使用して 1000 スレッドグループを設定し、クエリ API をループ実行。
- サーバーの CPU 使用率を監視(Prometheus+Grafana を通じて)。
- 期待結果:CPU 使用率のピーク値≤80%、持続的なフルロード現象なし。
- 合格基準:CPU がボトルネックに達せず、システムがクラッシュしない。
- ステップ:
- 用例:1000 の同時ユーザーがクエリ操作を実行するシミュレーション、10 分間継続。
2. メモリリーク
- シナリオ:システムが長時間実行された後にメモリが解放されない。
- 用例:システムを 48 時間継続して実行し、ユーザーログイン、操作、退出プロセスをシミュレート。
- ステップ:
- Locust を使用して毎日アクティブなユーザーの行動をシミュレート(毎時 500 ユーザー)。
- JVM ヒープメモリを監視(VisualVM を通じて)。
- 期待結果:メモリ使用率の曲線が安定し、持続的な増加傾向がない。
- 合格基準:メモリ使用率の変動が ±5% 以内。
- ステップ:
- 用例:システムを 48 時間継続して実行し、ユーザーログイン、操作、退出プロセスをシミュレート。
3. ディスク I/O パフォーマンス
- シナリオ:大量のファイルアップロード / ダウンロードによるディスクの読み書きボトルネック。
- 用例:100 ユーザーが同時に 1GB のファイルをアップロードするシミュレーション。
- ステップ:
- JMeter の HTTP リクエストを使用して大きなファイルをアップロード。
- ディスク IOPS と読み書き遅延を監視(Linux の
iostat
を通じて)。
- 期待結果:ディスク利用率≤90%、平均遅延≤50ms。
- 合格基準:ファイルが正常にアップロードされ、タイムアウトエラーがない。
- ステップ:
- 用例:100 ユーザーが同時に 1GB のファイルをアップロードするシミュレーション。
アプリケーションレベル#
1. データベースの遅いクエリ
- シナリオ:複雑な SQL クエリによる応答時間の長さ。
- 用例:複数のテーブルを結合したクエリを実行(10 万件のデータ)。
- ステップ:
- アプリケーションを通じてクエリインターフェースをトリガーし、SQL 実行時間を記録。
- MySQL の遅いクエリログにその文が記録されているか確認。
- 期待結果:クエリ時間≤2 秒、遅いクエリログに記録なし。
- 合格基準:インデックスを最適化した後、クエリ時間が 50% 短縮。
- ステップ:
- 用例:複数のテーブルを結合したクエリを実行(10 万件のデータ)。
2. Redis キャッシュヒット率
- シナリオ:キャッシュの無効化によりデータベースへの頻繁なアクセスが発生。
- 用例:90% のキャッシュヒット率の読み取りシナリオをシミュレート。
- ステップ:
- Gatling を使用してユーザーがホットデータ(商品詳細など)を高頻度で読み取るシミュレーション。
- Redis の
keyspace_hits
とkeyspace_misses
指標を監視。
- 期待結果:キャッシュヒット率≥90%。
- 合格基準:データベースのクエリ回数が大幅に減少(例:80% 減少)。
- ステップ:
- 用例:90% のキャッシュヒット率の読み取りシナリオをシミュレート。
3. スレッドプールの設定
- シナリオ:スレッドプールが小さすぎてリクエストがキューに入る。
- 用例:突発的なトラフィックをシミュレート(500 の同時リクエスト、スレッドプール容量 100)。
- ステップ:
- JMeter を使用して 500 の同時リクエストをバックエンドサービスに送信。
- スレッドプールのアクティブスレッド数とキューの積み残し状況を監視(Spring Boot Actuator を通じて)。
- 期待結果:キューの待機時間≤1 秒、リクエストが拒否されない。
- 合格基準:スレッドプールを調整した後、スループットが 30% 向上。
- ステップ:
- 用例:突発的なトラフィックをシミュレート(500 の同時リクエスト、スレッドプール容量 100)。
ネットワークレベル#
1. 高レイテンシシナリオ
- シナリオ:地域を越えたアクセスによるネットワークレイテンシの増加。
- 用例:異なる地域(米東部、ヨーロッパ)から API を呼び出す。
- ステップ:
- BlazeMeter を使用して複数の地理的ノードで負荷テストを設定。
- 平均応答時間(RT)を測定。
- 期待結果:RT≤3 秒(国を越えたアクセス)。
- 合格基準:CDN を有効にした後、RT が≤1 秒に短縮。
- ステップ:
- 用例:異なる地域(米東部、ヨーロッパ)から API を呼び出す。
2. 帯域幅のボトルネック
- シナリオ:ビデオストリーミングサービスが大量の帯域幅を占有。
- 用例:1000 ユーザーが同時に 1080P のライブストリーミングを視聴するシミュレーション。
- ステップ:
- LoadRunner を使用してビデオストリームリクエストをシミュレート。
- サーバーの出口帯域幅を監視(
iftop
を通じて)。
- 期待結果:帯域幅利用率≤80%、カクつき現象なし。
- 合格基準:ロードバランサーを有効にした後、帯域幅の配分が均等になる。
- ステップ:
- 用例:1000 ユーザーが同時に 1080P のライブストリーミングを視聴するシミュレーション。
ビジネスレベル#
1. 高同時接続の注文(EC シナリオ)
- シナリオ:セールイベントによる瞬時のトラフィックの急増。
- 用例:1 万人のユーザーが同時に 100 件の商品を購入するシミュレーション。
- ステップ:
- JMeter を使用して 1 万スレッドを 1 秒以内に起動。
- 注文成功率と在庫の一貫性を確認。
- 期待結果:成功した注文数 = 100、超売れや重複注文なし。
- 合格基準:データベースのトランザクション隔離レベルを最適化した後、汚染読み取りがない。
- ステップ:
- 用例:1 万人のユーザーが同時に 100 件の商品を購入するシミュレーション。
2. ビジネス成功率
- シナリオ:高負荷下での支払いインターフェースのエラー率。
- 用例:毎秒 500 件の支払いリクエストをシミュレート(5 分間継続)。
- ステップ:
- Gatling を使用して支払いリクエストを送信し、HTTP ステータスコードを監視。
- エラー率(5xx エラーの割合)を集計。
- 期待結果:エラー率≤0.1%。
- 合格基準:サーキットブレーカーが発動した後、エラー率が 0% に低下。
- ステップ:
- 用例:毎秒 500 件の支払いリクエストをシミュレート(5 分間継続)。
3. 混合シナリオのパフォーマンス
- シナリオ:ユーザーが同時にログイン、ブラウジング、注文操作を実行。
- 用例:70% のユーザーがブラウジング、20% のユーザーがカートに追加、10% のユーザーが支払いをシミュレート。
- ステップ:
- Locust を使用して行動モデルを比例配分。
- 全体の TPS と RT(95 パーセンタイル≤2 秒)を監視。
- 期待結果:TPS≥500、ビジネスプロセスにブロッキングなし。
- 合格基準:各インターフェースの応答時間の変動が ±10% 以内。
- ステップ:
- 用例:70% のユーザーがブラウジング、20% のユーザーがカートに追加、10% のユーザーが支払いをシミュレート。
テスト方法に基づく#
ベンチマークテスト(Benchmark Test)#
目標
低負荷または単一ユーザーシナリオにおけるシステムのパフォーマンスベースラインを特定し、後続のテストの比較基準を提供する。
シナリオ
- 単一ユーザー操作:同時接続の圧力がない状態で、システムの最適なパフォーマンスをテスト。
- 典型的な用例:ユーザーログイン、商品詳細ページの読み込み、簡単なクエリ。
テストケース
用例 1:単一ユーザーのログイン応答時間
- ステップ:
- JMeter を使用して 1 つのスレッド(ユーザー)を設定し、ログインインターフェースリクエストを 10 回ループ実行。
- 各リクエストの応答時間(RT)を記録。
- 期待結果:
- 平均 RT ≤ 500ms、標準偏差 ≤ 50ms。
- 合格基準:
- HTTP エラーなし、RT の変動が 10% 以内。
負荷テスト(Load Test)#
目標
システムが予想される最大負荷下でのパフォーマンス(応答時間、スループット)が要件を満たすかどうかを検証する。
シナリオ
- 予想同時接続ユーザー:日常のピークトラフィック(EC の大規模プロモーション期間中に 5000 の同時ユーザー)をシミュレート。
- 典型的な用例:複数のユーザーが同時に注文、在庫照会、支払いを行う。
テストケース
用例 2:5000 の同時ユーザーによる商品検索
- ステップ:
- LoadRunner を使用して 5000 ユーザーが同時に商品キーワード検索(例:「スマートフォン」)を実行するシミュレーション。
- 段階的に加圧:30 秒ごとに 500 ユーザーを追加し、5000 の同時接続に達するまで。
- 監視指標:TPS(毎秒トランザクション数)、RT(95 パーセンタイル)、エラー率。
- 期待結果:
- TPS ≥ 1000、RT ≤ 2 秒、エラー率 ≤ 0.5%。
- 合格基準:
- スループットが安定し、リソース(CPU / メモリ)が持続的に 80% を超えない。
ストレステスト(Stress Test)#
目標
システムのパフォーマンス限界とクラッシュポイントを見つけ、過負荷時のフォールトトレランス能力を検証する。
シナリオ
- 予想負荷を超える:設計容量を大幅に超える突発的なトラフィックをシミュレート(例:日常のピークの 10 倍)。
- 典型的な用例:セールイベントのトラフィック急増、API が悪意のあるリクエストで押し寄せる。
テストケース
用例 3:10 万人の同時ユーザーによる購入負荷テスト
- ステップ:
- Gatling を使用して 10 万人のユーザーを瞬時に起動し、セールスインターフェースにリクエストを送信。
- システムがクラッシュするまで加圧を続ける(大量の 5xx エラーやサービス不可が発生するまで)。
- クラッシュ時の同時接続数、エラータイプ、復旧時間を記録。
- 期待結果:
- システムはクラッシュ前に少なくとも 8 万人の同時接続を処理し、クラッシュ後 10 分以内に自動復旧する。
- 合格基準:
- 重要なサービス(注文在庫)でデータの不整合が発生しない。
同時テスト(Concurrency Test)#
目標
複数のユーザーが同時に操作する際のリソース競合と同期問題(デッドロック、データの汚染読み取りなど)を検証する。
シナリオ
- 高競争操作:同一リソースが頻繁に変更される(在庫の減少、アカウント残高の更新など)。
- 典型的な用例:複数の人が同時に同一の注文を変更する、チケットを購入するシナリオ。
テストケース
用例 4:100 ユーザーが同一商品在庫を同時に変更
- ステップ:
- JMeter を使用して 100 スレッドが同時に「在庫を 1 減少させる」リクエストを送信。
- 初期在庫が 100 であることを確認し、最終在庫が 0 であることを検証。
- データベースのトランザクションログにデッドロックやタイムアウトが存在するか確認。
- 期待結果:
- 最終在庫 = 0、超売れや負の在庫なし。
- 合格基準:
- データベースのトランザクション隔離レベル(楽観的ロックを使用)により、汚染読み取りが効果的に回避される。
安定性テスト(Endurance Test)#
目標
システムが長時間実行される際のパフォーマンス低下(メモリリーク、接続プールの枯渇など)を検出する。
シナリオ
- 持続的な負荷運用:システムが 7×24 時間サービスを提供し、リクエストを中断なく処理することをシミュレート。
- 典型的な用例:金融システムのデイエンドバッチ処理、IoT デバイスがデータを継続的に報告。
テストケース
用例 5:72 時間の持続的な注文処理
- ステップ:
- Locust を使用して毎時 1000 ユーザーが注文を行うシミュレーションを 72 時間継続。
- JVM ヒープメモリ、データベース接続プールの使用率、スレッドリークを監視。
- 12 時間ごとに負荷テストツールを再起動し、ツール自体のリソースリークを回避。
- 期待結果:
- メモリ使用率の変動範囲 ≤ 10%、OOM(メモリオーバーフロー)エラーなし。
- 合格基準:
- スループット(TPS)の低下幅 ≤ 5%。
容量テスト(Capacity Test)#
目標
システムの最大処理能力(ユーザー数 / データ量)を特定し、拡張の根拠を提供する。
シナリオ
- データ量の拡張:データベースの単一テーブルデータを百万件から億件に増加させる。
- ユーザー数の拡張:登録ユーザーを 10 万から 100 万に段階的に増加させる。
テストケース
用例 6:億件のデータ量におけるクエリパフォーマンス
- ステップ:
- データベースに 1 億件のテストデータを挿入し、複合インデックスを構築。
- JMeter を使用して 100 の同時ユーザーがページネーションクエリを実行(page=10000, size=10)。
- SQL 実行時間とディスク I/O を監視。
- 期待結果:
- クエリ時間 ≤ 1 秒、インデックスカバレッジが 100% に達する。
- 合格基準:
- データベースのシャーディング後、クエリパフォーマンスが 50% 向上。
ベストプラクティス#
-
層別設計:
- 基盤層:ベンチマークテストを使用してコアインターフェースの単一ユーザー性能をカバー(注目点:応答時間)。
- ビジネス層:負荷 / ストレステストを使用して複雑なシナリオを検証(注目点:スループット、エラー率)。
- システム層:安定性テストを使用してリソースリークをチェック(注目点:メモリ、接続プール)。
-
マトリックスカバレッジ法:
注目点と方法を組み合わせたマトリックスを作成し、各注目点が少なくとも 1 つの方法でカバーされることを確認する。例えば:負荷テスト ストレステスト 安定性テスト CPU 使用率 ✅ ✅ メモリリーク ✅ データベース性能 ✅ ✅