訪問者数をRequest Mixへ置き換える
2 vCPU・4GBのサーバーが耐えられる訪問者数は、仕様表だけを見て計算できません。同じ月間訪問者数でも、大半がキャッシュされた公開ページを見るサービスと、ログイン・検索・決済・ファイルアップロードを繰り返すサービスとでは負荷がまったく違います。サーバーの容量は、定めた要求構成のもとで遅延と誤り、資源圧力、待ち行列の基準をすべて守りながら持続的に処理できる最大の負荷、と定義するほうが正確です。Google Cloudの負荷テストの指針も、絶対的な最大処理量一つより、遅延と処理量、資源使用など複数の次元で許容できる閾値を探すよう案内します。[1] Google SREもトラフィックと遅延、誤り、飽和を併せて見るよう促します。[3]
2 vCPUという表記も同じ演算性能を意味しません。あるVMではvCPUがハードウェアスレッドで、別の製品群では物理コアに対応します。共用CPUは同じホストの他のワークロードによって使えるCPUサイクルが変わります。CPUの世代とSMT構成、ストレージの種類と上限、ネットワークの処理量も併せて記さなければなりません。[2]
したがってテストの結果は「2 vCPU・4GB=訪問者N人」ではなく、次の形で残します。ワークロードプロファイル[版]と環境[指紋]で完了処理量[値]を[測定区間]のあいだ維持した。このとき経路別のP95遅延は[値]、誤り率は[値]、最大キューは[値]で、最初の制限信号は[CPU・メモリ・DB・I/O・ネットワーク・外部連携]だった。想定ピークに対する検証済みの余裕は[値]であり、この結果は[キャッシュ状態・データ量・背景作業・Providerの条件]でのみ有効である。
月間訪問者数は負荷の時間分布を示しません。同じ10万回の訪問も、ひと月に均等に散らばることも、数分に集まることもあります。一度の訪問がサーバー要求一件を意味するわけでもありません。サーバーが実際に受ける作業は、たいてい八つに混ざります。CDNやページキャッシュで終わる公開の照会、アプリケーションとDBを両方通るログイン利用者の照会、データ変更とトランザクションが要る書き込み、検索・絞り込み・集計のようにCPUとDBの費用が大きい要求、画像変換とファイルアップロードとレポート生成、外部API呼び出しを待つ要求、キューで非同期に処理される作業、そしてCron・バックアップ・インデックス作成のような背景作業です。[3]
負荷テストでは少なくとも三つの数値を分けなければなりません。Offered RPSが増えるのにCompleted RPSがそれ以上増えないなら、サーバーの手前か内部のどこかで作業が積み上がるか捨てられています。固定した仮想利用者数だけを使う閉ループのテストでは、サーバーが遅くなるほど次の要求の開始も遅れます。そのため実際の処理限界に達しているのに、入力の負荷が自ら減る現象が起きます。目標RPSを検証するときは、応答時間と独立に要求を開始する開ループの到着率モデルを併せて検討しなければなりません。[7]
同時接続者よりConcurrent Workを見ます。ブラウザのタブを開いている1,000人が、サーバーで1,000個の作業を同時に実行するという意味ではありません。逆に利用者が少なくても、遅いDBクエリや外部APIのためにサーバー内部の作業が長く残り、同時作業量が大きくなります。安定した系では、平均の同時作業量Lが完了処理率λと平均滞在時間Wの積に等しいというLittle's Lawで検算します。ただし定常状態に近く平均が有限な区間で使う検算式であり、P95やP99を平均滞在時間の位置に入れてはいけません。[5] 実務では、処理中のHTTP要求、使用中のアプリケーションWorker、DBで実行中のQuery、DB Connection Poolの待機者、メッセージキューに積まれたJob、外部APIの応答を待つ作業を別々に見ます。
- Offered RPS
- 負荷生成器が送ろうとした要求率です。
- Completed RPS
- サーバーが応答を終えた処理量です。
- Successful RPS
- 機能として成功した完了処理量です。
容量を先に定義してからテストする
負荷を上げたあとにグラフを見て「この辺で大丈夫」と判断すると、基準が動き続けます。テストの前にPass/Fail基準を宣言しなければなりません。三つの概念の意味は次のとおりです。
Grafana k6のThresholdも、テストのメトリクスに対するPass/Fail基準として定義されます。文書のP95 200ms、誤り率1%未満のような値は使い方を示す例であって、すべてのサービスの推奨基準ではありません。実際の基準はサービスの利用者の期待と運用目標から定めます。[4]
HeadroomはCPUの余裕率一つではありません。余裕率の計算は、Request Mixとデータ量、キャッシュ状態、コードと依存が同じときにだけ意味があります。必要な余裕率にも汎用の正解はありません。ピーク需要の予測誤差、短いSpikeの大きさと持続時間、増強や自動拡張にかかる時間、バッチ・バックアップ・インデックス作業との重なり、一つのインスタンスや外部連携の障害時に残る容量、サービスが許容する遅延と誤りが、これを決めます。Google Cloudも、最適な資源使用率はアプリケーションごとに違い、系が100%に達する前に性能が悪化すると説明します。[1]
CPU Timeでもう一度検算します。コンテナやsystemdのcgroupを使うなら、cpu.statのusage_usecでテスト区間のCPU Timeを求めます。[8] CPUが主なボトルネックで、要求あたりのCPU費用が負荷によって大きく変わらない区間なら、使えるCPU秒に目標のCPU使用比率を掛け、要求あたりのCPU時間で割った値を補助の検算に使います。2 vCPUは、スケジューリングの条件が十分なとき、毎秒最大およそ2 CPU秒を与える形と考えます。しかし共用CPUとCPU quota、throttling、SMT、単一スレッドのボトルネック、DB・ネットワークの待ちのため、この式が実際の処理量を語るわけではありません。最終の判定はつねに負荷テストの結果で行います。
- 検証済みの持続容量
- 定めたRequest Mixのもとで、指定した区間のあいだ処理量の目標を満たし、遅延と誤りの基準を守り、待ち行列が増え続けず、資源圧力やOOM、異常なThrottlingが起きず、負荷を外した後に正常状態へ戻れる最大の負荷です。
- Capacity Headroom
- 検証済みの持続完了処理量を想定ピークの完了処理量で割り、1を引いた余裕率です。
- 要求あたりCPU時間
- テスト区間のCPU使用時間を完了要求数で割った値で、負荷が上がるときこの値が変わるかを見ます。
本番トラフィックから改善の優先順位へ — 実際のリクエスト構成で負荷をモデル化し、ボトルネックの原因仮説と改善効果を再検証します。
まずサーバーの「環境の指紋」を記録する
他のProviderの2 vCPU・4GBサーバーと比べたり、同じテストを再現したりするには、次の条件も併せて残っていなければなりません。
Google Compute Engineは一部のマシン系列でvCPUがコアに対応しますが、別の系列では既定でコアあたり二つのvCPUを使います。AWSの多くのEC2インスタンスでは、一つのCPUスレッドが一つのvCPUとして表されます。DigitalOceanも、共用CPUと専用CPUのアクセス保証の水準、CPUの世代、NVMe、ネットワーク性能を分けます。したがって2 vCPU・4GBという四つの数字だけで、異なるVMを同等に比べてはいけません。[2]
区分 | 記録する内容 |
|---|---|
| Compute | Provider、Region・Zone、プラン名、vCPU数、CPUのモデル・世代、アーキテクチャ |
| CPUの割り当て | Shared / Dedicated、SMTの有無、vCPUとコアの対応、CPU quota |
| CPUの異常信号 | throttling time、steal time、単一コアへの偏り |
| Memory | 実際に使えるメモリ、Container・cgroupのlimit、Swapの容量と方針 |
| Storage | Local・Block・Network Storage、SSD・NVMe、ボリューム容量、IOPS・Throughputの上限 |
| Network | インスタンスのネットワーク上限、パケット・接続の制限、負荷生成器との経路 |
| Topology | アプリ・DB・キャッシュ・キューが同じサーバーか別のサーバーか |
| Software | OS、Kernel、Runtime、Web Server、DB、Cacheのバージョン |
| Process Model | Worker・Thread・Processの数、Connection PoolとQueueの上限 |
| Data | データ量、インデックス量、値の分布、テストアカウント数 |
| Cache | Cold・Warmの別、TTL、事前の暖機方法 |
| Build | Commit、Image Digest、設定のバージョン、Feature Flag |
| Dependencies | 外部API、メッセージング、ストレージ、認証サービスとMockの有無 |
| Load Generator | ツールとバージョン、所在、自身のCPU・メモリ・ネットワークの仕様 |
必ず併せて測る値
Google SREの四つの信号から始めつつ、容量の判定にはその原因を分ける内部の指標がさらに要ります。成功した要求と失敗した要求の遅延も分けなければなりません。[3]
P50は中央値で、P95は全観測値のうち95%がその値以下という意味です。複数のインスタンスや区間を合わせる必要があるなら、計測の方式とHistogramのbucket設計も併せて検討します。[9]
LinuxではCPU・メモリ・I/Oの競合で作業が止まった時間をPSIで確認します。cgroup v2はCPUの使用時間とthrottling、全体のメモリ使用量、OOMのイベント、読み書きのバイトとI/Oの回数を公開します。ワークロードのcgroupの経路でcpu.stat、memory.current、memory.stat、memory.events、io.statを読み、/proc/pressureのcpu・memory・ioも併せて見ます。[6]
memory.currentはcgroupが使う全体のメモリであって、ワーキングセットを計算してくれる値ではありません。持続負荷で安定する使用量とrefault、major fault、Swap、PSI、OOMのイベントを併せて見て、運用上のワーキングセットを推定します。PostgreSQLならnumbackends、blks_read、blks_hit、I/Oの時間、active time、wait eventを使います。[10]他のDBMSでは同じ問いに答える対応指標を選びます。Redisをキャッシュに使うならkeyspace_hits、keyspace_misses、evicted_keysを記し、全体のhit ratioだけを見ず、テストの段階ごとのmissとevictionの増加も確認します。[11]
測定値 | 必ず記録する値 | 判定に使う問い |
|---|---|---|
| Request Mix | 経路・作業ごとの比重、読み書き、認証の有無、Payload、キャッシュ状態、DB・外部呼び出しの数 | 実運用のトラフィックと同じ費用分布か |
| Requests/sec | Offered、Started、Completed、Successful RPSを経路別に記録 | 入力を上げたとき完了処理量も増え続けるか |
| Concurrent Work | In-flight Request、Active Worker、DB Active Query、Pool Waiter、Queue Depth | 処理中の作業が安定するか、積み上がり続けるか |
| CPU Utilization | Host・cgroup・Process・コア別の使用率、user/system、steal、throttling | CPUが実際に忙しいか、一つのコアやquotaで詰まっているか |
| CPU Time | 区間のCPU秒、要求・作業あたりのCPU ms | 処理量が増えると単位作業のCPU費用が変わるか |
| Memory Working Set | 暖機後の安定区間のcgroup使用量・RSS・Heap・Page Cache・Peak・Refault | 必要なメモリが平衡に達するか、増え続けるか |
| Swap / OOM | Swap in/out、major fault、reclaim、memory.eventsのhigh・max・oom・oom_kill | メモリ不足をSwapの遅延やOOMで払っているか |
| DB Query | QPS・TPS、経路別のQuery数、Query P50・P95、Slow Query、Lock・Wait Event | アプリよりDBが先に飽和するか |
| DB I/O | Read・Write IOPS、bytes、latency、fsync、temp write | ディスク処理量よりI/O待ちが先に増えるか |
| DB Connection | Active・Idle・Waiting、最大接続、Poolの使用率と待ち時間 | 接続の上限やPoolの待ちが要求のキューを作るか |
| Cache Hit | CDN・Reverse Proxy・Application・Redis・DB Bufferごとのhit・miss、eviction | テストがキャッシュ一層だけを測っていないか |
| Network | In・Out bytes、packets、新規接続率、接続の誤り・再送、応答サイズ | CPUが余っていてもネットワークや接続処理で詰まるか |
| Queue Depth | Web・App Worker Queue、DB Pool Wait、Message Queue Lag、Oldest Age | キューが一定水準で安定するか、時間とともに増えるか |
| P50 Latency | 経路別の成功・失敗要求の中央値 | 通常の要求の体験が保たれているか |
| P95 Latency | 経路別の成功・失敗要求の95パーセンタイル | 遅い上位の要求が許容基準を超えるか |
| P99 Latency | 裾の長さが重要な経路で十分な標本により測定 | まれな遅延が決済・認証・保存のような重要作業を脅かすか |
| Error Rate | 5xx、Timeout、Connection Error、Reject、機能の失敗、誤った結果 | 速い失敗が平均遅延を低く見せていないか |
| Saturation | CPU・Memory・I/OのPSI、throttling、queue、lock、pool wait | 使用率100%の前に実際の作業停止が起きるか |
| Headroom | 想定ピーク、検証済みの持続容量、最初の基準違反点、反復のばらつき | ピークと変動、復旧に必要な余裕が残っているか |
Benchmark Protocol
第一に、テストが答えるべき問いから書きます。「このサーバーは何人まで可能か」は悪い目標です。「運用のピークと同じRequest Mixで完了処理量[目標]を維持しながら、経路別の遅延・誤り・キュー・資源圧力の基準を満たすか」が良い目標です。確かめたいのが平常時のピークか、瞬間のSpikeか、長時間の持続負荷かも分けます。
第二に、Pass/Failと中断の条件を先に定めます。負荷を送る前に、経路別のP50・P95・必要ならP99の目標、機能の誤りとシステムの誤りの許容基準、完了処理量の目標、許容するQueue DepthとPool Wait、CPUのthrottlingと資源圧力の基準、Swap・OOMの禁止条件、DBのConnection・Query・I/Oの基準、テストの中断条件、負荷を外した後の復旧基準を確定します。サービスごとの目標がなければ暫定の運用基準をまず作り、それを業界標準のように表現しません。
第三に、環境を固定して指紋を保存します。アプリケーションのBuildと設定、Workerの数、DB・キャッシュのバージョン、データ量、VMのプランとCPUのモデルを記します。テスト中にAuto Updateや配備、バックアップ、データ移行が走らないよう統制します。運用でバックアップやバッチがピークの時間と実際に重なるなら、別の重なりシナリオで改めてテストします。
第四に、実際のRequest Mixを再現します。運用のログや分析資料から経路・作業ごとの比重を求めます。個人情報とCredentialは取り除き、テストデータが一つ二つのキャッシュキーに集中しないよう分布を再現します。運用の資料がなければ製品の流れから仮説のプロファイルを作り、結果にsynthetic workloadと明記します。
第五に、ColdとWarmを分けます。キャッシュが空の状態と暖機された状態を一つの結果に平均しません。Cold start、Warm steady state、Cache evictionの後、配備直後、再起動直後のうち、実際の運用リスクに関わるプロファイルだけを選び、それぞれの結果を残します。
第六に、負荷生成器がボトルネックでないかを確認します。生成器のCPUとメモリ、ネットワーク、開いたファイル数、要求の欠落を併せて見ます。生成器が飽和すると、SUTではなくテスト機材の限界を測ることになります。k6の大規模テストの指針は、生成器のCPUが完全に飽和すると結果が劣化しうると警告し、CPU使用率を80%以内に保つ例を挙げます。これはテスト対象サーバーの推奨CPU閾値ではなく、負荷生成器を検証する値です。[12]
第七に、Idle BaselineとSmoke Testを行います。負荷がないときのCPUとメモリ、DB、キューを記します。続いて機能の成功と計測の欠落を確認できる程度の小さな負荷を送ります。Smokeの段階で機能の誤りや観測の欠落があれば、容量テストへ進みません。
第八に、負荷を段階的に上げ、各段階を保ちます。目標のRPSや作業率を小さな段階から上げます。各段階は瞬間のピーク値だけを取って終えず、完了処理量が安定するか、P95が上がり続けるか、ワーキングセットが平衡に達するか、キューが一定の水準で安定するか、DB・外部連携の遅延が積み上がるかが見えるだけ保ちます。目標RPSを検証するときは開ループの到着率モデルを、固定した同時セッションを検証するときは閉ループのモデルを使います。二つの結果を同じ意味に解釈しません。[4]
第九に、最初の基準違反点を記します。サーバーが完全に止まるまで待つ必要はありません。経路別の遅延基準の違反、誤り率の基準の違反、完了処理量の停滞、Queueの持続的な増加、CPUのthrottlingやPSIの増加、Memory reclaim・Swap・OOMの危険、DB Pool・Lock・I/Oの待ちの増加、Cache hitの急落とevictionの増加、外部連携のtimeoutのうち、一つが最初に持続して現れた地点を記します。この地点のすぐ下で、すべての基準を満たした最後の段階を検証済みの持続容量の候補とします。
第十に、統制されたOverloadの挙動を確認します。非運用の環境で安全な中断条件を設け、容量を超えたとき系がどう失敗するかを見ます。すべての要求が一緒に遅くなるか、一部の要求を明示的に拒否するか、Timeoutが積み上がるか、Queueがメモリを食うか、負荷を下げた後に回復するかです。Google Cloudは過負荷のとき、すべての要求を遅くするより一部の要求を拒否して残りの性能を守るLoad Sheddingを勧めます。ただし実際に適用する方針は、サービスの業務特性と再試行の安全性を置いて設計しなければなりません。[1]
第十一に、SoakとRecoveryを確認します。想定ピークの水準で十分に持続し、メモリのリーク、Connectionのリーク、Queue backlogの増加、キャッシュのeviction、DBのtemp file・WAL・Checkpointの影響、ログとディスクの増加、周期的なGCとBatchの干渉のような時間依存の問題を探します。負荷を外した後は、キューが定めた時間内に空くか、遅延と誤りがBaselineの水準へ戻るか、メモリが安定した区間へ戻るか、ConnectionとWorkerが正常化するか、OOMやプロセスの再起動がなかったかを確認します。
第十二に、同じ条件で反復します。一度の最良の結果を選びません。同じ条件で繰り返し、中央値と実行間の範囲を残します。共用CPUのVMで反復のばらつきが大きいなら、平均だけを示さず、最低・中央・最高の実行とCPU steal、throttling、ストレージの遅延を併せて確認します。
Capacity Test Worksheet
下の様式の空欄は実際の測定値で埋めます。ワークシートは五つのブロックに分かれます。
BのMixの合計は、選んだプロファイルの中で100%にならなければなりません。Normal Peak、Write-heavy、Cold Cache、Batch Overlapのようにプロファイルが違えば、別の版として管理します。
DはD-1の処理量・遅延・安定性とD-2の資源・ボトルネックに分かれます。下記Field別空欄を埋めます。両様式ともBaseline、Warm-up、L1、L2、L3、Overload、Recoveryの七段階です。
Eは一枚で終えます。Test IDとWorkload Profileの版、Application Build、環境の指紋、想定ピークの需要、検証済みの持続完了処理量と成功処理量、P50・P95・P99、誤り率、最大キュー、CPUの使用率と要求あたりのCPU時間、メモリのワーキングセットの推定、SwapとOOM、DBのQueryとI/OとConnection、Cacheのhitとeviction、Network、PSIと飽和、最初の基準違反、有力なボトルネック、余裕率、復旧の結果、実行間のばらつきを記します。最後に、この結果が有効な条件と再測定が必要な変更を記します。
- A. Test Identity & Environment
- 何を試験したかを特定する識別ブロックです。下記A Fieldへ実環境値を記入します。
- B. Request Mix Profile
- シナリオごとに利用者の作業とRoute、Mixの比率、Arrival Model、Payload、認証、読み書き、キャッシュ状態、要求あたりのDB Query数、外部呼び出しを記すブロックです。
- C. Pass / Fail Criteria
- 処理量と遅延、誤り、CPU、メモリ、DB、キャッシュ、ネットワーク、キュー、復旧、余裕率の基準と測定Window、適用範囲を、負荷を送る前に確定するブロックです。
- D. Stage Result
- 段階ごとにサービス指標と資源・依存の指標を分けて記す二つのブロックです。前者はRPSと遅延、誤り、キューを、後者はCPUとメモリ、DB、I/O、キャッシュ、ネットワーク、PSIと最初の違反を収めます。
- E. Final Capacity Statement
- 検証済みの持続処理量と遅延・誤り・キュー、最初の制限信号、余裕率、そしてこの結果が有効な条件と再測定が必要な変更を一枚に記すブロックです。
- A / 識別 / Test ID
- [記入]
- A / 識別 / 目的・判断する質問
- [記入]
- A / 識別 / 実行日・担当者
- [記入]
- A / SUT / Commit / Image Digest
- [記入]
- A / SUT / 設定・Feature Flag Version
- [記入]
- A / Compute / Provider / Region / Zone / Plan
- [記入]
- A / Compute / vCPU / RAM
- [記入]
- A / Compute / CPUモデル・世代・Architecture
- [記入]
- A / Compute / Shared / Dedicated / SMT / Core Mapping
- [記入]
- A / Limits / cgroup・Container CPU quota
- [記入]
- A / Limits / Memory limit / Swap / PID・File limit
- [記入]
- A / Storage / Storage種類・容量・IOPS・Throughput上限
- [記入]
- A / Network / Instance上限・試験経路
- [記入]
- A / Software / OS / Kernel / Runtime / Web Server
- [記入]
- A / Process / Worker・Thread・Queue設定
- [記入]
- A / Database / 所在・Version・容量・Connection Pool
- [記入]
- A / Cache / 所在・Version・容量・TTL・Eviction
- [記入]
- A / Data / Record・Indexのサイズと分布
- [記入]
- A / Dependencies / 外部API・Storage・認証・Mock範囲
- [記入]
- A / Generator / ツール・Version・仕様・所在
- [記入]
- A / Telemetry / Metric・Log・Trace Dashboard
- [記入]
- A / Safety / 実行Window・中止条件・復旧担当者
- [記入]
- B / [S-01]
- ユーザー作業: [記入] · Route·Protocol: [記入] · Mix %: [記入] · Arrival Model: [記入] · Payload: [記入] · Auth: [記入] · Read/Write: [記入] · Cache State: [記入] · DB Query/Request: [記入] · External Call: [記入] · 備考: [記入]
- B / [S-02]
- ユーザー作業: [記入] · Route·Protocol: [記入] · Mix %: [記入] · Arrival Model: [記入] · Payload: [記入] · Auth: [記入] · Read/Write: [記入] · Cache State: [記入] · DB Query/Request: [記入] · External Call: [記入] · 備考: [記入]
- B / [S-03]
- ユーザー作業: [記入] · Route·Protocol: [記入] · Mix %: [記入] · Arrival Model: [記入] · Payload: [記入] · Auth: [記入] · Read/Write: [記入] · Cache State: [記入] · DB Query/Request: [記入] · External Call: [記入] · 備考: [記入]
- D-1 / Baseline
- Offered RPS: [記入] · Completed RPS: [記入] · Successful RPS: [記入] · Concurrent Work: [記入] · P50: [記入] · P95: [記入] · P99: [記入] · Error Rate: [記入] · Queue Depth: [記入] · Stable: [記入]
- D-1 / Warm-up
- Offered RPS: [記入] · Completed RPS: [記入] · Successful RPS: [記入] · Concurrent Work: [記入] · P50: [記入] · P95: [記入] · P99: [記入] · Error Rate: [記入] · Queue Depth: [記入] · Stable: [記入]
- D-1 / L1
- Offered RPS: [記入] · Completed RPS: [記入] · Successful RPS: [記入] · Concurrent Work: [記入] · P50: [記入] · P95: [記入] · P99: [記入] · Error Rate: [記入] · Queue Depth: [記入] · Stable: [記入]
- D-1 / L2
- Offered RPS: [記入] · Completed RPS: [記入] · Successful RPS: [記入] · Concurrent Work: [記入] · P50: [記入] · P95: [記入] · P99: [記入] · Error Rate: [記入] · Queue Depth: [記入] · Stable: [記入]
- D-1 / L3
- Offered RPS: [記入] · Completed RPS: [記入] · Successful RPS: [記入] · Concurrent Work: [記入] · P50: [記入] · P95: [記入] · P99: [記入] · Error Rate: [記入] · Queue Depth: [記入] · Stable: [記入]
- D-1 / Overload
- Offered RPS: [記入] · Completed RPS: [記入] · Successful RPS: [記入] · Concurrent Work: [記入] · P50: [記入] · P95: [記入] · P99: [記入] · Error Rate: [記入] · Queue Depth: [記入] · Stable: [記入]
- D-1 / Recovery
- Offered RPS: [記入] · Completed RPS: [記入] · Successful RPS: [記入] · Concurrent Work: [記入] · P50: [記入] · P95: [記入] · P99: [記入] · Error Rate: [記入] · Queue Depth: [記入] · Stable: [記入]
- D-2 / Baseline
- CPU %: [記入] · CPU ms/req: [記入] · Throttle·Steal: [記入] · Working Set: [記入] · Swap·OOM: [記入] · DB QPS·P95: [記入] · DB Conn·Wait: [記入] · IOPS·Latency: [記入] · Cache Hit·Evict: [記入] · Network: [記入] · PSI: [記入] · 最初の違反: [記入]
- D-2 / Warm-up
- CPU %: [記入] · CPU ms/req: [記入] · Throttle·Steal: [記入] · Working Set: [記入] · Swap·OOM: [記入] · DB QPS·P95: [記入] · DB Conn·Wait: [記入] · IOPS·Latency: [記入] · Cache Hit·Evict: [記入] · Network: [記入] · PSI: [記入] · 最初の違反: [記入]
- D-2 / L1
- CPU %: [記入] · CPU ms/req: [記入] · Throttle·Steal: [記入] · Working Set: [記入] · Swap·OOM: [記入] · DB QPS·P95: [記入] · DB Conn·Wait: [記入] · IOPS·Latency: [記入] · Cache Hit·Evict: [記入] · Network: [記入] · PSI: [記入] · 最初の違反: [記入]
- D-2 / L2
- CPU %: [記入] · CPU ms/req: [記入] · Throttle·Steal: [記入] · Working Set: [記入] · Swap·OOM: [記入] · DB QPS·P95: [記入] · DB Conn·Wait: [記入] · IOPS·Latency: [記入] · Cache Hit·Evict: [記入] · Network: [記入] · PSI: [記入] · 最初の違反: [記入]
- D-2 / L3
- CPU %: [記入] · CPU ms/req: [記入] · Throttle·Steal: [記入] · Working Set: [記入] · Swap·OOM: [記入] · DB QPS·P95: [記入] · DB Conn·Wait: [記入] · IOPS·Latency: [記入] · Cache Hit·Evict: [記入] · Network: [記入] · PSI: [記入] · 最初の違反: [記入]
- D-2 / Overload
- CPU %: [記入] · CPU ms/req: [記入] · Throttle·Steal: [記入] · Working Set: [記入] · Swap·OOM: [記入] · DB QPS·P95: [記入] · DB Conn·Wait: [記入] · IOPS·Latency: [記入] · Cache Hit·Evict: [記入] · Network: [記入] · PSI: [記入] · 最初の違反: [記入]
- D-2 / Recovery
- CPU %: [記入] · CPU ms/req: [記入] · Throttle·Steal: [記入] · Working Set: [記入] · Swap·OOM: [記入] · DB QPS·P95: [記入] · DB Conn·Wait: [記入] · IOPS·Latency: [記入] · Cache Hit·Evict: [記入] · Network: [記入] · PSI: [記入] · 最初の違反: [記入]
領域 | Metric | 基準 | 測定Window | 適用範囲 |
|---|---|---|---|---|
| Throughput | Completed / Successful RPS | 記入 | 記入 | 全体・経路別 |
| Latency | P50 | 記入 | 記入 | 経路別 |
| Latency | P95 | 記入 | 記入 | 経路別 |
| Latency | P99 | 必要な経路のみ記入 | 記入 | 経路別 |
| Error | システム誤り率 | 記入 | 記入 | 全体・経路別 |
| Error | 機能の失敗率 | 記入 | 記入 | 中核の作業 |
| CPU | Utilization / PSI / Throttling | 記入 | 記入 | Host・cgroup |
| CPU | CPU ms/request | 記入 | 記入 | 全体・経路別 |
| Memory | Working-set estimate / PSI | 記入 | 記入 | Host・cgroup |
| Memory | Swap / OOM | 記入 | 記入 | Host・cgroup |
| DB | Query P95 / Connection Wait | 記入 | 記入 | DB・Pool |
| DB | IOPS / I/O latency / Lock | 記入 | 記入 | DB・Storage |
| Cache | Hit / Miss / Eviction | 記入 | 記入 | 層別 |
| Network | Throughput / Error / Retransmit | 記入 | 記入 | App・DBの経路 |
| Queue | Depth / Oldest Age / Pool Wait | 記入 | 記入 | Queue別 |
| Recovery | Baselineへの復帰時間 | 記入 | 負荷終了後 | 全体 |
| Headroom | 想定Peakに対する余裕率 | 記入 | 最終判定 | Workload Profile |
サービス構成から運用基準まで — ネットワークとサーバーを設計し、デプロイ経路、アクセス権限、バックアップ基準を整えます。
Result Interpretation Table
下の表のボトルネックは確定した原因ではなく、次の検証のための仮説です。複数の資源が同時に飽和することもあります。
Linux PSIはCPU・メモリ・I/Oの競合で実際の作業が止まった時間を示すため、単純な使用率と飽和を分けるのに有用です。PostgreSQLの接続・I/O・wait eventや、Redisのhit・miss・evictionも、アプリサーバーの外のボトルネックを分けるのに使います。[6]
観測パターン | 優先仮説 | 次に確認すること | 避けるべき結論 |
|---|---|---|---|
| Offered RPSは増えるがCompleted RPSが止まり、Queueが増え続ける | 持続処理の限界に到達 | Worker・DB Pool・Message Queueのどこで待つか | 誤りが少ないのでまだ余裕がある |
| CPU・CPU PSI・throttlingが増え、CPU Time/requestは比較的一定 | Computeの飽和 | コア別使用率、単一スレッド、quota、steal | CPUの平均だけ見てDBとQueueを除く |
| 全体のCPUは低いが一つのコアだけ飽和し遅延が増える | 単一スレッド・Lock・直列区間 | Runtime profile、lock wait、event loop lag | vCPU数を増やせば線形に改善する |
| ワーキングセットが増え続け、GC・refault・Swap・Memory PSIも増える | メモリのリークまたは不足 | Heap、Page Cache、Connection・Bufferのリーク | RAM増設だけでリークを解決した |
| App CPUは低いがDB Query P95・Pool Wait・Lock・I/Oが増える | DBのボトルネック | Top SQL、実行計画、connection、wait event | Appインスタンスを増やせば解決する |
| Cache Hitが下がりDB QPS・I/Oが同時に増える | キャッシュのchurn・キー分布・暖機の問題 | 層別のmiss、TTL、eviction、test data | DBが遅いとだけ結論する |
| P50は安定なのにP95・P99だけ急に増える | 裾の競合 | GC、lock、connection wait、外部API、遅いQuery | 平均応答時間だけで合格 |
| 誤り率が増えるのに平均遅延はむしろ下がる | 速い失敗・拒否・接続の誤り | 成功と失敗の遅延を分ける、状態コード、機能の成功 | 遅延が改善したと判断 |
| CPU・DBは余るがNetworkの処理量・接続の誤りが上限に近づく | ネットワーク・接続処理のボトルネック | Packet、retransmit、connection rate、payload | vCPU不足と断定 |
| Appを増やしても総処理量がほとんど増えない | 共用のDB・Cache・Queue・外部依存のボトルネック | 各下位システムのsaturation | さらにAppの複製を足し続ける |
| 同じイメージと負荷なのに実行ごとの性能差が大きい | Shared CPU・ストレージ・ネットワークの変動 | CPU steal、throttling、ディスク遅延、Host class | 最良の一回をサーバー性能として公表 |
| CPU使用率は高いが遅延・誤り・Queue・PSIは安定 | 現在の負荷は処理中だが余裕の検討が要る | Spike・Recovery・反復のばらつき | 高いCPUだけで即座に不合格と判定 |
| 負荷終了後にQueue・メモリ・Connectionが正常化しない | 復旧の失敗・リーク・再試行の暴走 | Queue drain、retry、connection lifecycle | 負荷区間のP95だけ見て合格 |
Scale-up / Scale-out Trigger Template
Scale-upとScale-outはCPUのグラフ一つで決めません。三つのうちどれが優先候補になるかは、最初のボトルネックが何かに懸かっています。
判断は記録として残します。Trigger Recordには決定IDと測定日、担当者、Workload Profileの版、Application Build、環境の指紋を記します。続いて想定ピークのOffered・Completedの処理率とRequest Mix、検証済み容量の処理率と持続時間、反復回数、実行間のばらつきを記します。Headroomには計算式と結果、そしてその余裕率が必要な理由を、予測誤差・Spikeの大きさ・拡張の所要時間・背景作業の重なり・障害時の残余容量として記します。
最初の違反基準には指標と閾値、観測値、Window、シナリオを記します。ボトルネックの分類はCPU・メモリ・DB・ストレージ・キャッシュ・ネットワーク・キュー・依存のうち一つを選び、裏づける証拠と反する証拠を併せて記します。Scale-upとScale-outのトリガーには条件と候補の措置、期待する効果、無効化の条件、再測定の要否を記します。Scale-outのトリガーには、負荷分散とヘルスチェック、状態とセッションの扱い、下位システムの余裕、配備とロールバックが検証済みであることを前提として付けます。最後にロールバックの条件と、変更後の再検証の計画を記します。
- Scale-up
- その候補になる条件: 必要なメモリのワーキングセットが現在のインスタンスの実用上限を超えるが、リークではないとき。単一インスタンスのCPU・I/O性能が明確な最初のボトルネックで、上位等級で改善の余地があるとき。状態やローカルデータのため即座に水平分散しにくいとき。共用CPUの変動が問題で、専用CPUや別の性能等級へ移すべきとき
- Scale-out
- その候補になる条件: 個々のインスタンスのボトルネックが再現し、要求を複数のインスタンスへ独立に分けられるとき。セッション・ファイル・作業の状態が外部化されているか一貫して共有されるとき。Load BalancerとHealth Checkが実負荷で検証済みのとき。DB・Cache・Queue・外部依存に追加のApp負荷を受ける余裕があるとき。配備や障害で一部のインスタンスが抜けても目標処理量を保つ必要があるとき
- 先に最適化・構造の修正
- その候補になる条件: Slow Query、Lock、Connection Poolの待ちが最初のボトルネックのとき。Cache Hitの崩壊やevictionが原因のとき。メモリやConnectionのリークがあるとき。無制限のQueueと再試行の暴走があるとき。外部APIのrate limitやtimeoutに当たるとき。単一のグローバルLockや直列処理の区間があるとき。負荷生成器自体が飽和しているとき
結論
2 vCPU・4GBのサーバーは、あるサービスには十分で、別のサービスには最初から足りません。その差を作るのは月間訪問者数ではなく、要求の費用と分布です。
良い容量の判定には九つが併せて入ります。どの要求をどの比率で送ったか、Offered・Completed・Successful RPSがそれぞれいくつだったか、同時に処理または待機した作業がどれだけあったか、経路別のP50・P95・必要ならP99が基準を守ったか、CPUの使用率だけでなく要求あたりのCPU Timeとthrottlingがどうだったか、メモリのワーキングセットとSwap・OOM・Pressureが安定していたか、DB・Cache・Storage・Network・Queueのどこが先に飽和したか、想定ピークの後にも必要なHeadroomが残ったか、負荷が消えた後に正常状態へ戻ったかです。
最後の一文は「何人まで可能だ」ではなく、こう書きます。このサーバーはこのワークロードプロファイルと環境でこの処理量まで検証されており、最初の制限資源はこれで、想定ピークに対してこれだけの余裕がある。コードとデータ、要求の構成、キャッシュの方針、Provider、CPUの等級、ストレージやネットワークが変われば、その一文も測り直さなければなりません。



