規模の見積もりとは桁を合わせる仕事だ
一言でいうと
容量の見積もりの目的は、正確な数字ではなく、桁を合わせることです。インスタンスが3台必要なのか30台必要なのかで分かれれば、設計全体が変わります。
なぜ必要なのか
システム設計は、4つの段階で進みます。要件の明確化 → 規模の見積もり → 高レベルの設計 → 詳細な設計(ボトルネックの把握と解決)。2つ目の段階を飛ばすと、残りがすべて空想になります。
簡単な例を見てみましょう。書き込みが1日1億件なら、QPSは約1,160です(1億 ÷ 86,400)。読み取りがその10倍なら、QPSは約11,600です。5年分の1,800億件にレコードあたり500バイトを掛けると、約90TBです。この3つの数字が出れば、「単一のインスタンスで足りるか」「シャーディングが必要か」「キャッシュなしで可能か」のような質問に、根拠をもって答えられます。
どう動くのか
測定から台数に至る道には、2つの安全装置があります。
1つ目はヘッドルームです。測定された最大スループットをそのまま使ってはいけません。安全スループットは、測定値の70%ほどに取ります。残りの30%は、トラフィックの変動、デプロイ中のインスタンス減少、予想外の遅いリクエストのための余地です。インスタンスあたり190 RPSを測定したなら、安全スループットは133 RPSです。
2つ目は切り上げです。目標300 RPSを133で割ると2.25台になりますが、2台では足りないので3台です。容量計算で小数点以下を切り捨てた瞬間、計画は失敗します。
プールのサイジングでも、同じ考え方が必要です。インスタンス1つの推奨プールサイズを60と決めたなら、必ずフリート単位で掛け算してみます。インスタンス40台 × 60 = 2,400接続なのに、データベースのmax_connectionsが200なら、各インスタンスの計算はすべて正しかったのに、システムはデプロイ直後に死にます。ローカル最適がグローバル最適ではない、典型的な事例です。
現場での姿
容量ドキュメントで最もよくある欠陥は、条件がないことです。「うちのサービスは1秒あたり500件を処理する」という文には、同時実行数も、p95も、エラー率も、測定時点もありません。同じサービスが、同時実行数2ではp95 20msで500 RPSを出し、同時実行数50ではp95 900msで520 RPSを出すなら、2つ目の数字は容量ではなく、すでに飽和した状態の観測値です。
そのため、容量は常にSLAと一緒に書く必要があります。「p95 200ms以下、エラー0の条件で、インスタンスあたり133 RPS」のように書けば、次の人が同じ基準で再現できます。
負荷テストの4つの種類
名前を区別すると、何を測るのかがはっきりします。
| 種類 | 何をするか | 何がわかるか |
|---|---|---|
| 負荷(load) | 予想されるトラフィックを維持します | 目標の負荷でのレイテンシ・エラー率 |
| ストレス(stress) | 負荷を上げ続けます | 崩れる地点と崩れ方 |
| スパイク(spike) | 突然10倍にします | 自動スケーリングが追いつくか |
| 耐久性(soak) | 普段の負荷で数時間続けます | メモリリーク、接続リーク、ディスクの満杯 |
ストレステストの価値は、限界の数値ではなく、崩れ方です。上品に拒否するのか(429)、すべてが遅くなるのか、それとも死ぬのかが、設計の品質を示します。「1秒あたり5,000リクエストまでいけます」よりも、「5,000を超えると429を返し、4,800に戻れば回復します」のほうが、はるかに役に立つ文です。
耐久性テストを抜かすと、1時間後に現れる問題を見逃します。コネクションプールが漏れること、ファイルディスクリプターがたまること、GCがだんだん長くなることは、5分のテストでは見えません。
クローズドループとオープンループ
負荷ツールがリクエストを作る方式が2つあり、結果がまったく変わります。
폐 루프(closed): 가상 사용자 N 명이 응답을 받아야 다음 요청을 보낸다
→ 서버가 느려지면 부하도 저절로 줄어든다
개 루프(open): 초당 N 건을 서버 상태와 무관하게 보낸다
→ 서버가 느려지면 요청이 쌓인다. 현실에 가깝다
このコードブロックの韓国語の文は、クローズドループでは仮想ユーザーN人が応答を受け取って初めて次のリクエストを送るので、サーバーが遅くなると負荷も自然に減り、オープンループでは、サーバーの状態に関係なく1秒あたりN件を送るので、サーバーが遅くなるとリクエストがたまって現実に近い、という意味です。
実際のユーザーはオープンループに近いものです。サーバーが遅いからといって、人々がリクエストを減らさないからです。クローズドループだけでテストすると、「仮想ユーザー100人でレイテンシ200ms」のような良い数字が出ますが、実際にはその地点ですでに崩れています。
k6はconstant-arrival-rate、GatlingはconstantUsersPerSecで、オープンループを作ります。自動スケーリングをテストするなら、必ずオープンループである必要があります。
コーディネーテッドオミッション(coordinated omission)
クローズドループのツールの、より微妙な問題です。応答が遅れると、そのあいだに送れなかったリクエストがそもそも測定に入らないので、p99が実際よりはるかに良く出ます。
서버가 10초 멈췄다
폐 루프: 그동안 요청을 안 보냄 → 느린 요청 1건만 기록 → p99 정상
현실: 그동안 요청이 계속 옴 → 수천 건이 10초를 기다림 → p99 폭발
このコードブロックの韓国語の文は、サーバーが10秒止まったとき、クローズドループではその間リクエストを送らず、遅いリクエスト1件だけが記録されてp99は正常に見えるが、現実ではその間もリクエストが来続けて数千件が10秒待たされ、p99が爆発する、という意味です。
これを補正するツール(--latency-correction、HdrHistogramベース)を使うか、オープンループでテストします。p99が疑わしいほど良ければ、まずこれを疑います。
現場での判断の順序
- 目標のトラフィックを決めます(ピーク基準で、平均ではありません)。
- インスタンス1つの安全スループットを、SLAの条件で測定します。
- ヘッドルームを反映して、70%に下げます。
- 割り算をして、切り上げます。
- 共有リソース(DBコネクション、キャッシュ、キュー)の上限と、掛け算で再び検算します。
次の確認で見ること
このモジュールは、ラボなしで、概念と計算を確認するクイズで締めくくります。前の3つのモジュールで作ったベースライン・ラダー・ボトルネックのレポートの数字を、平均QPS、ピークの倍率、ヘッドルームを反映した安全スループット、そして必要なインスタンス数へと変える過程を、検算します。