Web アプリケーションの負荷テスト戦略: ユーザーがテストを行う前にブレーク ポイントを見つける

k6、Artillery、Locust を使用して Web アプリケーションをロード テストします。テスト設計、トラフィック モデリング、パフォーマンス ベースライン、結果解釈戦略について説明します。

E
ECOSIRE Research and Development Team
|2026年3月16日5 分で読める955 語数|

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 応答時間<500ms500ms-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 が発行 -- 企業がプレッシャーの下でもパフォーマンスを発揮するアプリケーションを構築できるように支援します。

E

執筆者

ECOSIRE Research and Development Team

ECOSIREでエンタープライズグレードのデジタル製品を開発。Odoo統合、eコマース自動化、AI搭載ビジネスソリューションに関するインサイトを共有しています。

Performance & Scalabilityのその他の記事

AI エージェントのパフォーマンスの最適化: 速度、精度、コスト効率

迅速なエンジニアリング、キャッシュ、モデル選択、監視のための実証済みの技術により、応答時間、精度、コスト全体にわたって AI エージェントのパフォーマンスを最適化します。

AI エージェントのテストと監視: 自律システムの信頼性エンジニアリング

AI エージェントのテストと監視に関する完全なガイド。単体テスト、統合テスト、動作テスト、可観測性、運用監視戦略をカバーします。

CDN パフォーマンスの最適化: グローバル配信を高速化するための完全ガイド

キャッシュ戦略、エッジ コンピューティング、画像の最適化、マルチ CDN アーキテクチャにより CDN パフォーマンスを最適化し、グローバル コンテンツ配信を高速化します。

e コマース向けモバイル SEO: 2026 年の完全な最適化ガイド

eコマースサイト向けのモバイルSEOガイド。モバイル ファースト インデックス、Core Web Vitals、構造化データ、ページ速度の最適化、モバイル検索のランキング要素をカバーします。

本番環境の監視とアラート: 完全なセットアップ ガイド

Prometheus、Grafana、Sentry を使用して、本番環境の監視とアラートを設定します。メトリクス、ログ、トレース、アラート ポリシー、インシデント対応ワークフローをカバーします。

API パフォーマンス: レート制限、ページネーション、非同期処理

レート制限アルゴリズム、カーソルベースのページネーション、非同期ジョブ キュー、応答圧縮のベスト プラクティスを使用して、高パフォーマンスの API を構築します。

WhatsAppでチャット