Performance & Scalabilityシリーズの一部
完全ガイドを読むWeb アプリケーションの負荷テスト戦略: ユーザーが実行する前にブレーク ポイントを見つける
パフォーマンスの問題の 80% は、テストではなくエンド ユーザーによって発見されます。 負荷テストでは、ユーザーが問題に遭遇する前にアプリケーションに対して現実世界のトラフィック パターンをシミュレートすることで、この比率を逆転させます。ブラック フライデーのトラフィックを処理するサイトとクラッシュするサイトの違いは、ほとんどの場合、誰かが最初に負荷テストを実行したかどうかです。
このガイドでは、Web アプリケーション、e コマース プラットフォーム、ERP システムの負荷テスト方法、ツールの選択、テスト設計、結果の解釈について説明します。
重要なポイント
- 負荷テストでは、単一のエンドポイントを攻撃するだけでなく、現実的なユーザーの動作をシミュレートする必要があります
- 最適化する前にパフォーマンスのベースラインを確立する --- 測定していないものを改善することはできません
- 運用環境に似た環境で負荷テストを実行します。ステージングの結果は本番環境の動作を反映していない可能性があります
- CI/CD での負荷テストを自動化し、展開前にパフォーマンスの低下を検出します
負荷テストの種類
| テストの種類 | 目的 | 期間 | 負荷パターン |
|---|---|---|---|
| 煙テスト | 最小限の負荷で基本機能を検証する | 1 ~ 2 分 | 1 ~ 5 ユーザー |
| 負荷テスト | 予想されるトラフィックの下でパフォーマンスを検証する | 10~30分 | 通常の交通 |
| ストレステスト | 限界点を見つける | 15~30分 | 徐々に増加 |
| スパイクテスト | 突然のトラフィックの急増をテストする | 5~10分 | 突然のジャンプ |
| 浸漬試験 | メモリ リークとメモリ劣化を検出する | 2~8時間 | 持続通常負荷 |
k6 による負荷テスト
基本的な負荷テスト
// k6/load-test.js
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '2m', target: 50 }, // Ramp up to 50 users
{ duration: '5m', target: 50 }, // Stay at 50 users
{ duration: '2m', target: 100 }, // Ramp up to 100 users
{ duration: '5m', target: 100 }, // Stay at 100 users
{ duration: '2m', target: 0 }, // Ramp down
],
thresholds: {
http_req_duration: ['p(95)<500', 'p(99)<1000'],
http_req_failed: ['rate<0.01'],
http_reqs: ['rate>100'],
},
};
export default function () {
// Simulate realistic user behavior
const homeResponse = http.get('https://example.com/');
check(homeResponse, {
'homepage status is 200': (r) => r.status === 200,
'homepage loads in under 1s': (r) => r.timings.duration < 1000,
});
sleep(Math.random() * 3 + 1); // 1-4 seconds think time
const productsResponse = http.get('https://example.com/api/v1/products');
check(productsResponse, {
'products API is 200': (r) => r.status === 200,
'products API under 500ms': (r) => r.timings.duration < 500,
});
sleep(Math.random() * 2 + 1);
}
eコマース ユーザー ジャーニー テスト
// k6/ecommerce-journey.js
import http from 'k6/http';
import { check, group, sleep } from 'k6';
export const options = {
scenarios: {
browsing: {
executor: 'ramping-vus',
startVUs: 0,
stages: [
{ duration: '5m', target: 200 },
{ duration: '10m', target: 200 },
{ duration: '5m', target: 0 },
],
exec: 'browsingScenario',
},
purchasing: {
executor: 'ramping-vus',
startVUs: 0,
stages: [
{ duration: '5m', target: 20 },
{ duration: '10m', target: 20 },
{ duration: '5m', target: 0 },
],
exec: 'purchaseScenario',
},
},
thresholds: {
'http_req_duration{scenario:browsing}': ['p(95)<800'],
'http_req_duration{scenario:purchasing}': ['p(95)<2000'],
http_req_failed: ['rate<0.01'],
},
};
export function browsingScenario() {
group('Browse Products', () => {
http.get('https://store.example.com/');
sleep(2);
http.get('https://store.example.com/products');
sleep(3);
http.get('https://store.example.com/products/sample-product');
sleep(2);
});
}
export function purchaseScenario() {
group('Purchase Flow', () => {
// Browse
http.get('https://store.example.com/products/sample-product');
sleep(1);
// Add to cart
http.post('https://store.example.com/api/cart', JSON.stringify({
productId: 'prod_123',
quantity: 1,
}), { headers: { 'Content-Type': 'application/json' } });
sleep(2);
// Checkout
http.get('https://store.example.com/cart');
sleep(3);
// Place order (simulated)
const orderResponse = http.post('https://store.example.com/api/checkout/validate', JSON.stringify({
email: `test-${__VU}@example.com`,
}), { headers: { 'Content-Type': 'application/json' } });
check(orderResponse, {
'checkout validates': (r) => r.status === 200 || r.status === 201,
});
sleep(1);
});
}
ストレス テスト (限界点を見つける)
// k6/stress-test.js
import http from 'k6/http';
import { check } from 'k6';
export const options = {
stages: [
{ duration: '2m', target: 100 },
{ duration: '5m', target: 100 },
{ duration: '2m', target: 200 },
{ duration: '5m', target: 200 },
{ duration: '2m', target: 500 },
{ duration: '5m', target: 500 },
{ duration: '2m', target: 1000 },
{ duration: '5m', target: 1000 },
{ duration: '5m', target: 0 },
],
};
export default function () {
const res = http.get('https://example.com/api/v1/products');
check(res, {
'status is 200': (r) => r.status === 200,
});
}
結果の解釈
主要な指標
| メトリック | 健康 | 警告 | クリティカル |
|---|---|---|---|
| P95 応答時間 | <500ms | 500ms-2s | >2秒 |
| P99 応答時間 | <1秒 | 1-5秒 | >5秒 |
| エラー率 | <0.1% | 0.1-1% | >1% |
| スループット | 目標を達成 | 目標の 80% | 目標の 80% 未満 |
一般的なボトルネック パターン
CPU バウンドのボトルネック: 応答時間は負荷に応じて直線的に増加します。 P95 と P99 はゆっくりと発散します。
- 修正: ホット コード パスの最適化、CPU 容量の追加、または水平方向のスケーリング
データベースのボトルネック: 応答時間は、特定の負荷しきい値で指数関数的に増加します。接続プールが枯渇しました。
- 修正: クエリの最適化、接続プーリング、リードレプリカ (データベース スケーリング ガイド を参照)
メモリのボトルネック: 時間の経過とともに徐々に劣化します。 GC の一時停止により、レイテンシのスパイクが発生します。
- 修正: メモリを増やし、メモリ リークを修正し、オブジェクト割り当てを最適化します。
ネットワークのボトルネック: 応答時間はすべてのエンドポイントで均一に増加します。帯域幅の飽和。
- 修正: 静的アセットの CDN、圧縮、ペイロード サイズの削減
パフォーマンスのベースライン
ベースラインの確立
最適化する前に、現在のパフォーマンスを文書化します。
# Run baseline test
k6 run --out json=baseline-results.json k6/load-test.js
# Compare after optimization
k6 run --out json=optimized-results.json k6/load-test.js
パフォーマンス予算
各エンドポイントの許容可能なパフォーマンスを定義します。
| エンドポイント | P95 ターゲット | スループット目標 |
|---|---|---|
| ホームページ | 500ミリ秒 | 200 リクエスト/秒 |
| 製品一覧 | 800ミリ秒 | 150 リクエスト/秒 |
| 製品詳細 | 600ミリ秒 | 200 リクエスト/秒 |
| カートに追加 | 300ミリ秒 | 100 リクエスト/秒 |
| チェックアウト | 2000ミリ秒 | 50 リクエスト/秒 |
| 検索 | 500ミリ秒 | 100 リクエスト/秒 |
| 管理者ダッシュボード | 1500ミリ秒 | 20 リクエスト/秒 |
CI/CD の統合
自動パフォーマンス回帰テスト
# .github/workflows/performance.yml
name: Performance Test
on:
push:
branches: [main]
jobs:
load-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run k6 load test
uses: grafana/[email protected]
with:
filename: k6/load-test.js
flags: --out json=results.json
env:
K6_TARGET_URL: ${{ secrets.STAGING_URL }}
- name: Check thresholds
run: |
if grep -q '"thresholds":{".*":"fail"' results.json; then
echo "Performance thresholds exceeded!"
exit 1
fi
負荷テストのチェックリスト
テストの前に
- 環境は本番環境と一致します (インスタンス タイプ、データベース サイズ)。
- テスト データは代表的なものです (現実的な製品数、ユーザー数)。
- モニタリングがアクティブです (テスト中にサーバーのメトリクスを追跡します)
- 関係者に通知されます (負荷テストによりアラートがトリガーされる可能性があります)
- CDN とキャッシュは運用環境と同じように構成されています
テスト中
- サーバーの CPU、メモリ、ディスク I/O を監視します
- データベース接続とクエリ遅延を監視します。
- エラー率の増加に注意してください
- リソースの枯渇をチェックします (ファイル記述子、接続)
- パフォーマンスが低下する負荷レベルに注意してください
テスト後
- ベースライン結果を文書化する
- ボトルネックとその負荷しきい値を特定します
- パフォーマンス向上のためのチケットを作成する
- パフォーマンス バジェットと比較する
- 最適化後のフォローアップ テストをスケジュールする
よくある質問
テストの本番環境またはステージングをロードする必要がありますか?
できれば両方。定期的なテストと CI/CD 統合のためのステージング。ステージングではデータベース サイズ、キャッシュ ウォーム、CDN 構成、およびネットワーク トポロジが異なることが多いため、定期的な検証 (トラフィックの少ない時間帯) のための運用。 1 つの環境しかテストできない場合は、ステージングをテストしますが、できる限り実稼働環境に近づけてください。
負荷テストはどれくらいの頻度で実行する必要がありますか?
すべてのデプロイメントでスモーク テストを実行します (CI/CD で自動化)。全負荷テストは毎週、またはメジャー リリース前に行われます。ストレス テストは四半期ごと、または既知のトラフィックの多いイベント (販売、発売) の前に実施します。ソーク テストを四半期ごとに実施して、メモリ リークと長期的な劣化を検出します。
ERP システムの負荷テストはどのように行うのでしょうか?
ERP 負荷テストでは、請求書の生成、注文書の作成、レポートの実行、データのインポートなど、さまざまなタスクを実行する同時ユーザーをシミュレートする必要があります。最も負荷の高い操作 (レポート生成、データ インポート) と最も同時実行される操作 (ピーク時の注文入力) に焦点を当てます。 ECOSIRE は、サポート サービスの一環として Odoo パフォーマンス テスト を提供します。
リクエスト間の現実的な思考時間はどれくらいですか?
e コマースのブラウジングの場合: 2 ~ 5 秒。フォーム入力の場合: 10 ~ 30 秒。チェックアウトの場合: 15 ~ 60 秒。管理者/ERP 使用の場合: 5 ~ 15 秒。負荷テストには常にランダム化された思考時間を追加してください。一定の間隔では、非現実的な同期負荷パターンが作成されます。
次に何が起こるか
負荷テストにより、最適化の取り組みの指針となるボトルネックが明らかになります。データベースのボトルネックについては データベース スケーリング、静的アセット配信については CDN 最適化、エラスティック キャパシティについては 自動スケーリング をフォローアップします。
パフォーマンスのテストと最適化については ECOSIRE にお問い合わせ、完全なインフラストラクチャ戦略については DevOps ガイド をご覧ください。
ECOSIRE が発行 -- 企業がプレッシャーの下でもパフォーマンスを発揮するアプリケーションを構築できるように支援します。
執筆者
ECOSIRE TeamTechnical Writing
The ECOSIRE technical writing team covers Odoo ERP, Shopify eCommerce, AI agents, Power BI analytics, GoHighLevel automation, and enterprise software best practices. Our guides help businesses make informed technology decisions.
関連記事
Monorepo プロジェクトの GitHub アクション CI/CD
Turborepo モノリポジトリ用の完全な GitHub Actions CI/CD ガイド: 影響を受けるのみのビルド、並列ジョブ、キャッシュ戦略、環境ベースのデプロイ、およびセキュリティのベスト プラクティス。
k6 負荷テスト: 起動前に API のストレス テストを行う
Node.js API の k6 負荷テストをマスターします。仮想ユーザーの増加、しきい値、シナリオ、HTTP/2、WebSocket テスト、Grafana ダッシュボード、CI 統合パターンをカバーします。
Odoo パフォーマンス チューニング: PostgreSQL とサーバーの最適化
Odoo 19 のパフォーマンス チューニングに関する専門ガイド。 PostgreSQL の構成、インデックス作成、クエリの最適化、Nginx キャッシュ、エンタープライズ展開のためのサーバーのサイジングについて説明します。
Performance & Scalabilityのその他の記事
Webhook のデバッグと監視: 完全なトラブルシューティング ガイド
障害パターン、デバッグ ツール、再試行戦略、監視ダッシュボード、セキュリティのベスト プラクティスを網羅したこの完全なガイドを利用して、Webhook デバッグをマスターしてください。
k6 負荷テスト: 起動前に API のストレス テストを行う
Node.js API の k6 負荷テストをマスターします。仮想ユーザーの増加、しきい値、シナリオ、HTTP/2、WebSocket テスト、Grafana ダッシュボード、CI 統合パターンをカバーします。
Nginx 実稼働構成: SSL、キャッシュ、およびセキュリティ
Nginx 実稼働構成ガイド: SSL 終端、HTTP/2、キャッシュヘッダー、セキュリティヘッダー、レート制限、リバースプロキシセットアップ、Cloudflare 統合パターン。
Odoo パフォーマンス チューニング: PostgreSQL とサーバーの最適化
Odoo 19 のパフォーマンス チューニングに関する専門ガイド。 PostgreSQL の構成、インデックス作成、クエリの最適化、Nginx キャッシュ、エンタープライズ展開のためのサーバーのサイジングについて説明します。
Odoo 対 Acumatica: 成長するビジネスのためのクラウド ERP
2026 年の Odoo と Acumatica の比較: 独自の価格モデル、スケーラビリティ、製造の深さ、成長軌道に適合するクラウド ERP はどれですか。
本番環境での AI エージェントのテストと監視
実稼働環境で AI エージェントをテストおよび監視するための完全なガイド。 OpenClaw 導入の評価フレームワーク、可観測性、ドリフト検出、インシデント対応について説明します。