ソーシャルゲームのキャパシティプランニングの考え方

### 「来月サービスインで絶対ダウンさせたくないけどサーバー何台あったら大丈夫？」
（´-`）.｡oO(何台立てても絶対はねえよ)
と言いたい気持ちをこらえて実際何台いるかを事前に知るには負荷試験が必要です。
そして負荷試験の結果に妥当性を持たせるにはキャパシティプランニングが必要です。

今回は実際に負荷試験に際して行った、
「ピークアクセス時にダウンさせない台数」を見積もる場合のプランニングを紹介します。
ソーシャルゲームのキャパシティプランニングに当っては決まったメソッドはないものの、
一例としてご参考ください。
（´-`）.｡oO(定番メソッドがあったら苦労はなかった)

-----
### Step1. 想定DAUをください！
まずサーバーが何台必要かを求めるために、捌くべきリクエスト数を求めます。

イベント施策、広告効果等から想定最大DAUを見積もります。
これはエンジニアだけでは出せないのでプロデューサーやプランナーに見積もってもらいます。(他力本願)
キャパシティプランニングの基礎値になるため、この値の精度はかなり重要になります。(圧力)
今回は100,000DAUとしておきます。

### Step2. ピーク時負荷はどのくらい？
100,000DAUといっても全員が24時間ずっとゲームをプレイしているわけはありません。
プランニングに際しては時間当たりで平均的に分散するとして、

100,000 / 24 ≒ 4127 (ユーザー/h)

とします。まあ実際は綺麗に分散するわけもなく、ピーク負荷というものを考えなければなりません。
サーバーがダウンするとすればピーク時アクセスに耐えきれなかった時、なので。

夜間22時~25時、時間限定ダンジョン開放などは1日の中でもアクセスが集中しやすい時間帯です。
特に時間限定経験値獲得ダンジョン等はリリース直後にはかなりのユーザーがアクセスします。

（´-`）.｡oO(なのでユーザーIDで区切ってグループ分けして時間をずらして開催したり、ユーザーが鍵アイテムを使って任意時間にプレイできるようにしたり、と負荷を避ける手段がいろいろ取られていますが、長くなる上脱線なので別の機会に)

「かなりの」では何人かわからないので数字にすると、経験則ですが大体DAUの1/4程度で見積もっておけばほぼ安心です。（´-`）.｡oO(※個人の感想です)
なので、DAUが100,000人とするとピーク時AUは

100,000 / 4 = 25,000 (ユーザー/h)

となります。
（´-`;）.｡oO(平常時のことは今回はやらないので4127のことは忘れて)

### Step3. アクセス頻度は測ろう
アクセスしてくる人数はわかりました。次にサーバーリクエスト頻度を求めます。
Step2より、ピーク時ユーザー数25,000人ですが、彼(彼女)らは何も毎秒サーバーリクエストしてくるわけではありません。
（´-`）.｡oO(正体がBotでない限りは！)

通常のゲームプレイにあたってはユーザーは大体決まった手順で操作します。
例としてよくあるRPG系のゲームなら

1. ログイン
2. ホーム画面
3. プレゼント一覧取得
4. プレゼント受け取り
5. クエスト一覧取得
6. クエスト開始
7. クエスト終了

が一般的な流れでしょうか。
各操作にはAPIリクエストが含まれていますから、実際にゲームを1時間ほどプレイしてAPIリクエスト毎にログを残す→集計すれば実際のリクエスト頻度がわかります。
ただライトユーザー、ミドルユーザー、ヘヴィユーザーで各操作の頻度が変わりそうなので万全を期すなら各層のユーザーの行動を想定してプレイして等すればより精度が高まります。

計測した結果、例えばホーム画面は5分に一回の頻度だとすれば、
アクセス頻度は 1/5 = 0.2Req/Min になります。
これが25,000人なので 0.2 * 25,000 = 5000Req/Min
つまりホーム画面APIについては5000Req/Minを捌く性能が必要になります。
これを全APIで求めれば全体として必要なスループットがわかります。
ここでは上記のAPIのみで算出してみます。アクセス頻度を適当に下記のようにして、

| API|アクセス頻度|Req/Min|25,000ユーザー時のReq/Min|
|:----------|-------------:|-----------:|------------:|
| ログイン|60分に1回 |1/60=0.01667|417|
| ホーム|5分に1回 |1/5=0.2|5000|
| プレゼント一覧取得|10分に1回|1/10=0.1|2500|
| プレゼント受け取り|10分に1回|1/10=0.1|2500|
| クエスト一覧取得|5分に1回|1/5=0.2|5000|
| クエスト終了|5分に1回|1/5=0.2|5000|
|合計|||**20417**|

はい、20417RPMがピークを捌くのに必要なスループットと出ました。
あとはこの処理性能を実現できるだけのサーバー台数を用意して負荷試験で確認するだけです。

### Step4. 負荷試験、しよ
最近社内では負荷試験ツールにLocustを使用しています。
https://github.com/locustio/locust
 
- シナリオをPythonで書ける
- マスタ-スレーブ構成でスケールできる
- Webツールが付いているのでブラウザで操作できる

等々が便利です。
また、各APIの実行頻度に重み付けができるのでStep3で求めたアクセス頻度を再現しやすいのもポイントです。
目標スループットを達成する台数になるまでじゃんじゃん負荷をかけていきましょう！
（´-`）ノ.｡oO(イナゴの群れをけしかけるのだ！)

### Step5. 目標達成！でも・・・
目標スループットが達成できた！必要台数もわかった！これでサーバーダウンは怖くない！
その前にちょっと各APIのスループットを確認してみましょう。

| API|負荷試験Req/Min|見積時Req/Min|
|:----------|-------------:|-------------:|
| ログイン|500|417|
| ホーム|2500|5000|
| プレゼント一覧取得|3000|2500|
| プレゼント受け取り|3000|2500|
| クエスト一覧取得|8000|5000|
| クエスト終了|2400|5000|
|合計|**21400**|**20417**|
全体のスループットとしては見事目標達成しています。
ただ、ホーム画面は見積5000に対して2500、クエスト終了は見積5000に対して2400です。
つまりこれらAPIでは見積りのリクエスト数の半分しか捌けていません。
これがめったに叩かれないAPIなら多少目を瞑っても問題ありませんがホームやクエスト終了はプレイするユーザーのほぼ全てが頻繁にアクセスする機能です。
（´-`#）.｡oO(まともにプレイできないじゃないか！)

このように全体として達成できていても重要なAPIで目標を下回った場合、
サーバーダウンまで行かなくともユーザーからの不満が大量に届くことになります。

この場合の対策は2つ

- ホームとクエスト終了が目標スループットを達成できるまでサーバー台数を増やす
- それぞれのAPIのパフォーマンスチューニングを行う。

です。時間なければ前者を、あれば後者を選択することになるでしょう。
（´-`）b.｡oO(お金で解決も立派な手段ですぞ)
ただしスループットが低いということは処理が遅いということなのでロジックの見直しや
チューニングを行った方がいいのは確かです。

---
以上になります。キャパシティプランニング〜負荷試験はリリース直前にやると大変なので早め早めに余裕をもってやりましょう。