LESSON 40分

「負荷テストで限界が分かったら、次にやるべきことは何だ?」佐藤CTOはホワイトボードにグラフを描きながら言った。「**容量計画(キャパシティプランニング)**だ。今のシステムがどこまで耐えられて、いつスケールすべきか。勘ではなくデータで判断する。」

1. キャパシティプランニングの基礎

キャパシティプランニングのプロセス

フェーズ内容アウトプット
需要予測トラフィック増加のトレンド分析将来の負荷見積もり
現状評価現在のリソース使用率と限界把握ボトルネックマップ
ギャップ分析需要と供給の差分スケーリング要件
計画策定スケーリング戦略とタイムライン実行計画書
実行・検証スケーリング実施と負荷テスト検証レポート
// 需要予測モデル
interface DemandForecast {
  currentRps: number;
  growthRateMonthly: number;  // 月次成長率(例: 0.15 = 15%)
  seasonalPeakMultiplier: number;  // 季節変動のピーク倍率
  safetyMargin: number;  // 安全マージン(例: 0.3 = 30%)
}

interface CapacityPlan {
  month: number;
  expectedRps: number;
  peakRps: number;
  requiredCapacityRps: number;
  currentCapacityRps: number;
  needsScaling: boolean;
}

function generateCapacityPlan(
  forecast: DemandForecast,
  currentCapacityRps: number,
  months: number
): CapacityPlan[] {
  const plans: CapacityPlan[] = [];

  for (let m = 1; m <= months; m++) {
    const expectedRps = forecast.currentRps *
      Math.pow(1 + forecast.growthRateMonthly, m);
    const peakRps = expectedRps * forecast.seasonalPeakMultiplier;
    const requiredCapacityRps = peakRps * (1 + forecast.safetyMargin);

    plans.push({
      month: m,
      expectedRps: Math.round(expectedRps),
      peakRps: Math.round(peakRps),
      requiredCapacityRps: Math.round(requiredCapacityRps),
      currentCapacityRps,
      needsScaling: requiredCapacityRps > currentCapacityRps,
    });
  }

  return plans;
}

// 例: 現在 5,000 RPS、月次15%成長、ピーク2倍、マージン30%
const plan = generateCapacityPlan(
  { currentRps: 5000, growthRateMonthly: 0.15, seasonalPeakMultiplier: 2.0, safetyMargin: 0.3 },
  20000,
  12
);
// Month 3: required=19770 → OK (20000)
// Month 4: required=22737 → NG → スケーリング必要

2. リトルの法則を活用した容量計算

// 各レイヤーの容量をリトルの法則で計算
// L = λ × W → λ = L / W
interface LayerCapacity {
  name: string;
  maxConcurrency: number;
  avgLatencyMs: number;
  maxThroughputRps: number;
}

function calculateLayerCapacity(
  name: string, maxConcurrency: number, avgLatencyMs: number
): LayerCapacity {
  return {
    name,
    maxConcurrency,
    avgLatencyMs,
    maxThroughputRps: Math.round(maxConcurrency / (avgLatencyMs / 1000)),
  };
}

const layers = [
  calculateLayerCapacity('Load Balancer', 10000, 1),       // 10,000,000 RPS
  calculateLayerCapacity('Web Server (per pod)', 100, 50),  // 2,000 RPS
  calculateLayerCapacity('App Server (per pod)', 50, 80),   // 625 RPS
  calculateLayerCapacity('DB Connection Pool', 100, 15),    // 6,667 RPS
  calculateLayerCapacity('External API', 20, 200),          // 100 RPS ← ボトルネック
];

// ボトルネック = スループット最小のレイヤー
const bottleneck = layers.reduce((min, l) =>
  l.maxThroughputRps < min.maxThroughputRps ? l : min
);

3. 水平スケーリングと垂直スケーリング

観点垂直 (Scale Up)水平 (Scale Out)
方法マシンスペックを上げるマシン台数を増やす
上限ハードウェア物理限界理論上は無制限
ダウンタイム通常必要無停止で追加可能
コスト曲線指数的(高スペックほど割高)線形的
複雑性低い高い(分散の課題)
適用場面DB、キャッシュWeb/Appサーバー、ワーカー
function decideScalingStrategy(context: {
  component: string;
  isStateful: boolean;
  canBeSharded: boolean;
  hasSessionAffinity: boolean;
}): { strategy: 'scale_up' | 'scale_out' | 'hybrid'; reason: string } {
  if (context.isStateful && !context.canBeSharded) {
    return { strategy: 'scale_up', reason: `${context.component}はステートフル。垂直スケールが最適` };
  }
  if (!context.isStateful && !context.hasSessionAffinity) {
    return { strategy: 'scale_out', reason: `${context.component}はステートレス。水平スケールが最もコスト効率が良い` };
  }
  return { strategy: 'hybrid', reason: `まずScale Up、限界後にScale Out` };
}

4. オートスケーリング設計

「オートスケーリングは魔法ではない」と佐藤CTOは釘を刺した。「設定を間違えるとフラッピング(頻繁な増減)で逆に不安定になる。」

interface AutoScalingPolicy {
  minInstances: number;
  maxInstances: number;
  targetMetrics: {
    name: string;
    scaleOutThreshold: number;
    scaleInThreshold: number;
    evaluationPeriodSec: number;
    dataPointsRequired: number;
  }[];
  cooldown: {
    scaleOutCooldownSec: number;
    scaleInCooldownSec: number;
    instanceWarmupSec: number;
  };
}

const ecSitePolicy: AutoScalingPolicy = {
  minInstances: 3,
  maxInstances: 50,
  targetMetrics: [
    { name: 'CPUUtilization', scaleOutThreshold: 70, scaleInThreshold: 30,
      evaluationPeriodSec: 60, dataPointsRequired: 3 },
    { name: 'RequestCountPerTarget', scaleOutThreshold: 1200, scaleInThreshold: 500,
      evaluationPeriodSec: 60, dataPointsRequired: 2 },
  ],
  cooldown: {
    scaleOutCooldownSec: 120,
    scaleInCooldownSec: 300,
    instanceWarmupSec: 180,
  },
};

// スケーリングのタイムライン
// 検知(180s) + 判断(10s) + 起動(60s) + 準備(60s) = 約310秒(5分)
// → 5分間はトラフィック増加を既存インスタンスで吸収する必要がある

5. スケーリングの壁と対策

問題症状対策
DBボトルネックサーバーを増やしてもRPSが伸びないリードレプリカ、キャッシュ、CQRS
セッション管理スケールアウト後にセッション消失外部セッションストア、JWT
ホットスポット特定シャードに負荷集中パーティションキー見直し
サンダリングハードキャッシュ失効時にDB集中ジッター付きTTL
コーディネーションノード増加でスループット低下結果整合性への変更
コラム: コスト効率の分析

スケーリング効率は線形ではない。インスタンス数が増えると、コーディネーションのオーバーヘッドで効率が逓減する。定期的にコスト/リクエストを計測し、効率が急激に低下するポイントでアーキテクチャの見直しを検討すべき。

まとめ

トピック要点
キャパシティプランニング需要予測 → 現状評価 → ギャップ分析 → 計画 → 検証
リトルの法則各レイヤーで個別に容量算出しボトルネック特定
水平 vs 垂直ステートレス → Scale Out、ステートフル → Scale Up
オートスケーリングメトリクス選択、クールダウン、予測スケーリングが鍵
スケーリングの限界DB、セッション、ホットスポットが壁になる

チェックリスト

  • キャパシティプランニングの5フェーズを説明できる
  • リトルの法則でボトルネックを特定できる
  • 水平/垂直スケーリングの使い分けを判断できる
  • オートスケーリングのタイムラインを計算できる
  • スケーリングの限界と対策を説明できる

次のステップへ

容量計画とスケーリング戦略を学んだ。次は パフォーマンスCI/CD で、パフォーマンスの継続的な監視と回帰テストの自動化を学ぼう。

推定読了時間: 40分