LESSON 30分

ストーリー

高橋アーキテクト
負荷テストを実施する前に、テストシナリオを設計する必要がある

高橋アーキテクトが続けた。

高橋アーキテクト
全エンドポイントに均等にリクエストを送るのは現実的じゃない。実際のユーザー行動を模倣したシナリオでテストしないと、意味のある結果は得られない

シナリオ設計の3ステップ

Step 1: ユーザー行動の分析

実際のトラフィックパターンをアクセスログから分析します。

// アクセスログから行動パターンを抽出
interface UserBehaviorPattern {
  name: string;
  percentage: number;  // 全トラフィックに占める割合
  actions: Action[];
}

const patterns: UserBehaviorPattern[] = [
  {
    name: '閲覧のみユーザー',
    percentage: 60,  // 60%のユーザー
    actions: [
      { endpoint: 'GET /products', weight: 50 },
      { endpoint: 'GET /products/:id', weight: 30 },
      { endpoint: 'GET /categories', weight: 20 },
    ],
  },
  {
    name: '検索ユーザー',
    percentage: 25,
    actions: [
      { endpoint: 'GET /search?q=...', weight: 40 },
      { endpoint: 'GET /products/:id', weight: 40 },
      { endpoint: 'POST /cart', weight: 20 },
    ],
  },
  {
    name: '購入ユーザー',
    percentage: 15,
    actions: [
      { endpoint: 'GET /products/:id', weight: 20 },
      { endpoint: 'POST /cart', weight: 20 },
      { endpoint: 'GET /cart', weight: 20 },
      { endpoint: 'POST /orders', weight: 20 },
      { endpoint: 'GET /orders/:id', weight: 20 },
    ],
  },
];

Step 2: ワークロードモデルの定義

// ワークロードモデル
interface WorkloadModel {
  // 目標負荷
  targetRPS: number;
  targetVUs: number;      // Virtual Users

  // エンドポイント別の負荷配分
  endpoints: EndpointLoad[];

  // 思考時間(ユーザーがページを見ている時間)
  thinkTime: {
    min: number;  // 最小(秒)
    max: number;  // 最大(秒)
    avg: number;  // 平均(秒)
  };
}

const workload: WorkloadModel = {
  targetRPS: 3000,
  targetVUs: 500,
  endpoints: [
    { path: 'GET /products',     rpsShare: 30 }, // 900 RPS
    { path: 'GET /products/:id', rpsShare: 25 }, // 750 RPS
    { path: 'GET /search',       rpsShare: 15 }, // 450 RPS
    { path: 'GET /categories',   rpsShare: 10 }, // 300 RPS
    { path: 'POST /cart',        rpsShare: 8 },  // 240 RPS
    { path: 'GET /cart',         rpsShare: 5 },  // 150 RPS
    { path: 'POST /orders',     rpsShare: 4 },  // 120 RPS
    { path: 'GET /orders/:id',  rpsShare: 3 },  // 90 RPS
  ],
  thinkTime: { min: 1, max: 10, avg: 3 },
};

Step 3: テストデータの準備

// テストデータの設計
interface TestDataRequirements {
  // ユーザーデータ
  users: {
    count: number;         // 必要なテストユーザー数
    distribution: string;  // 均等 or 偏りあり
  };

  // 商品データ
  products: {
    count: number;
    popularProducts: number;  // 人気商品(アクセス集中)
    accessPattern: string;    // べき乗分布(一部に集中)
  };

  // 検索クエリ
  searchQueries: {
    count: number;
    source: string;  // 実際のアクセスログから抽出
  };
}

const testData: TestDataRequirements = {
  users: {
    count: 10000,
    distribution: 'unique per VU',
  },
  products: {
    count: 5000,
    popularProducts: 100,    // 上位100商品にアクセスの80%が集中
    accessPattern: 'zipf',   // べき乗分布
  },
  searchQueries: {
    count: 500,
    source: 'production access log (anonymized)',
  },
};

テストの成功基準(SLO)

// Service Level Objectives
interface TestSLO {
  // レイテンシ
  latency: {
    p50: number;  // 100ms
    p95: number;  // 300ms
    p99: number;  // 500ms
  };

  // スループット
  throughput: {
    minRPS: number; // 最低3000 RPS
  };

  // エラー率
  errorRate: {
    max: number;  // 0.1%以下
  };

  // リソース使用率
  resources: {
    maxCPU: number;     // 80%以下
    maxMemory: number;  // 80%以下
  };
}

const slo: TestSLO = {
  latency: { p50: 100, p95: 300, p99: 500 },
  throughput: { minRPS: 3000 },
  errorRate: { max: 0.1 },
  resources: { maxCPU: 80, maxMemory: 80 },
};

シナリオ設計のチェックリスト

  1. 現実的か — 実際のユーザー行動を反映しているか
  2. 再現可能か — 同じ条件で何度でも実行できるか
  3. 測定可能か — 明確な成功基準が定義されているか
  4. テストデータは十分か — キャッシュヒットが100%にならないか
  5. 思考時間を含むか — 実ユーザーの待ち時間を模倣しているか

まとめ

ポイント内容
ユーザー行動分析アクセスログから実際のパターンを抽出
ワークロードモデルエンドポイント別の負荷配分を定義
テストデータべき乗分布で現実的なアクセスパターン
SLOレイテンシ、スループット、エラー率の成功基準

チェックリスト

  • ユーザー行動パターンの分析方法を理解した
  • ワークロードモデルの定義方法を把握した
  • テストデータの設計ポイントを理解した
  • テストの成功基準(SLO)を定義できる

次のステップへ

次は「k6による負荷テスト」を学びます。設計したシナリオを実際にコードとして実装しましょう。


推定読了時間: 30分