ソシャゲサーバー開発するとき始めに考慮しておかないと死ぬポイント備忘録

 つれづれなるままに書きます。いわゆるソシャゲみたいな感じで、ステートレスな通信で回すやつです。

スポンサーリンク

目次

事前知識編

 システム開発するプログラマも読んでおいたほうがいい資料とか。

 今時のシステムならまず仕様や運用に反映される。されてなかったらむしろこっちから確認取りに行った方がいい。

JOGAガイドライン

 昔ガチャとかが問題になったときに出てきた協会のガイドライン。

開発環境編

GitHubみたいなPullRequestを出せる環境

 GitだけじゃなくてGitHub。必然的に規模が大きくなるのでプルリク出して進めることになります。

CIまで設定をする

 最初のうちにCircleCIのようなテストの自動実行する仕組みまで揃えてしまっておいたほうが良いです。後からだとそもそも対応できなくなってる可能性があります。

 全体が小さいウチに整えておく必要があります。

自動デプロイを設定する

 開発環境には頻繁にデプロイすることになります。どこかにpushしたらデプロイされるようにしておくと楽です。

言語の選定

 私だとだいたいPHPに慣れてるのでPHPにしてしまいそう。WebサービスであればRubyとかでもいいし、C#大統一理論などもあります。最近はGoでも良いのかも。心の赴くままに決めましょう。

フレームワークの選定

 今時だと何かしらのフレームワークを導入して開発することになります。適度に試してみたり経験のあるものを選択すればよいと思います。

 リクエストからのルーティングとautoload程度であれば自分で書いてもいいかもしれません。(ですが、潰しはあんまり利かなくなります)

ユニットテストとインテグレーションテスト

 テストコードはどんなに時間がなくてもオールグリーンにしておくこと。

 メソッド単位のユニットテストだけじゃなくて、APIを叩いて疑似動作をするインテグレーションテストを用意しておくこと。

テストデータは用意しやすく

 データが用意しづらいとテストを書くこと自体のコストが上がってテストを書くことが苦痛になります。そうなると誰も書かなくなります。

手早く構築できるようにする

 docker-composeなどを使って、ゼロからでも手早く構築できるようにします。upしたらユニットテストが動くところまで用意できるのが良いです。

 これも最初からやっておく必要があります。後になるほど厄介になります。

システム編

リソースのダウンロードシステム

 最近のゲームはリソースダウンロードだけで1GBに迫る勢いになっています。解像度もフルHD程度は普通にあります。インストール直後に一括ダウンロードできる量ではありません。

 都度ダウンロードの仕組みは最初のうちに入れておくと良いです。デバッグが楽になります。

課金システム

 課金周りは慎重に実装する必要がありますが、ストアごとの対応とアプリ側のロジックは分けていく必要があります。後からストアが増えるかもしれません。

有償分と無償分を分ける

 なんとか石みたいなゲーム内通貨を実装する場合、プリペイドカードと同様とみなされ資金決済法に縛られます。ゲーム内で保持している有償分に応じて供託金を支払う必要が出てきます。有償分と無償分のカウントは分ける必要があります。

課金ログは信頼できるシステムに残しておく

 障害対応や補填対応などで、課金ログ使用するときは間違いなくやってきます。

可能なら別システムに

 アカウント管理と課金部分は、どのようなゲームを作っても必要となるところです。別システムにしてしまったほうが会社として取り回しが利くかもしれません。

アカウント管理

端末情報に依存しすぎない

 端末はリセットされるし売り買いもされます。端末のハードウェアに結びつけた認証を行うことは避けるべきです。

 UUIDを生成して認証に使ったり、TwitterやLINEなど他のサービスのアカウントを使うなどしてもよいです。

iCloudなどバックアップとレストアに注意する

 iCloudなどを使用したバックアップとレストアは、アプリの意図しない状態を引きおこしかねません。それらを行っても問題ないことを確認します。

簡単に初期化できるようにしておく

 開発中は何度もアカウントを初期化することになります。簡単にできるようにしておきます。

 リソースデータとアカウントの管理は別にして、それぞれ消せるようにしておきます。

データの受け渡し

リクエストとレスポンスはJSONでまとめて

 レスポンスは膨大になるのでJSONと決めておいた方が楽です。

 リクエストもヘッダ情報としていろいろと送ることになるためJSONが良いです。

パラメータの改ざんチェック

 パラメータは改ざんされます。リクエストおよびレスポンスは改ざんをチェックしておく必要があります。

ロギング

 アプリから出力するログはなるべく残しておきます。ただしサーバーのストレージではなく、別システムに逃がします。

 理由はインフラでも書きますが、数台~数十台のサーバーにあるログを全部確認するような状況を避けるためです。

データベースとキャッシュ

 RDBは使用することになると思います。そのとき負荷分散を考える必要があります。

 マスター/スレーブにしてもクラスタにしても、必要十分ならどちらでもよいです。

シャーディング

 ユーザーデータなどはIDで分割して、複数のデータベースに格納することを考えるかもしれません。

 このときIDだけで決め打ちにしてしまうと、後からシャードを増やしたいときえらいことになります。シャーどの振り分けは別途保持したほうがいいと思います。

リードとライト

 データの利用は圧倒的に読み込みのほうが多いです。ですが全て画一的にキャッシュすると、書き込んだデータと整合性がとれなくて死ぬ場合が出てきます。

 読み取り専用で済むデータ(マスタデータなど)と読み書きが必要なデータ(プレイヤー情報など)を区別して考える必要があります。

 キャッシュの方法はRedisなどのNoSQL、PHPならAPCのようにサーバーごとに行うなどいろいろです。

NoSQLの使いどころ

 速度が速いからとNoSQLばかり使っていると死にます。消えて困るデータ、整合性がとれなくなると困るデータはRDBを使用するようにします。

トランザクション

 RDBのトランザクションは基本的に設定する必要があります。でも設定しすぎるとトランザクションが詰まって死にます。

 データの整合性を多少犠牲にしてもかまわない場面では、トランザクションを使用しないことも選択肢として考えられます。

不要なデータを消さない

 例えば受け取ったギフトや達成したミッションなど、もう必要なくなったデータをDELETEしたくなりますが、論理削除にしておいたほうが良いです。

 障害調査や補填対応で必要になる場合があります。(テーブル容量が心配ならログとしてどこかに逃がし、ゲームDB上から消すのは設計としてありかもしれません。そのあたりは個別の重要度により決定します。個人的には障害対応時に確認するためにRDBにもなるべく残しておくことをお勧めします)

メンテナンス機構

 いろいろな都合でメンテナンスに突入します。

ツールから実行できるようにする

 計画メンテはともかく、緊急メンテはほんとすぐ止めないといけません。

 そのときにツールからボタン一つでできるようにしておかないと、手間取ってる間にひどいことになります。

一部ユーザー/端末は通過できるようにする

 メンテナンス中の確認用に、特定のユーザーや端末を通過できるようにします。

 ネットワークで制限掛けてもいいですが、それだと自由度がないのでプレイヤーIDを指定できるようにするとよいです。

メンテナンス情報とAPIサーバーはできれば分ける

 メンテナンス中は場合によってはAPIサーバーが落ちているかもしれません。

 その際にエラーとなってしまうのはまずいです。

 別にメンテナンスサーバーを用意するとか、どこかにファイルがあるうちはメンテナンスにするとか、APIサーバーが死んでいてもメンテナンスが継続されるようにします。

インフラ編

サーバーは複数台を前提とする

 10台単位で追加と削除を行うような調整をすることになります。複数台でまかなうこと前提にする必要があります。

ログの収集は別システムにする

 数十台のサーバーにあるログを確認して回ることは現実的ではありません。

 また特にクラウド時代だと、APIサーバーのインスタンスを追加しては削除みたいな事をするのでそもそもストレージにログが残りません。

 ログはfluentdで回収してどこかに登録するとか、別システムに片端から送信するようにしておきます。

複数の環境をコントロールする

 開発環境にも種類があります。アプリとサーバーの開発用、QA用、データ作成用、本番用など。

すぐに環境を作れるようにする

 必要なシステムは複数のサーバーで一セットとなります。これをなるべく簡単にまとめて起動できるようにしておいたほうがよいです。

 突発的に環境が必要になったりすることもあります。

環境間でのデータコピーなどを行えるようにする

 データを作成したら、そのままの状態で本番環境にデプロイするような格好です。

アクセスするエンドポイントを分ける

 たとえばバージョンごとにアクセスするプログラムディレクトリを分けるようにします。

 過去の互換性、また戻すことが容易になります。

ゲームシステム編

 ゲーム内容によりますが、だいたい必要になるかもしれないことです。

 キャラの強化やクエストなどはゲームデザイン依存なので、何らかの形で必要になるかもしれませんが汎用的ではないかもしれません。

プレイヤーデータ

 プレイヤー名、スタミナなど。

ログインボーナス

 ログインしたときに報酬を配布する機能です。

 時期によって変更したり、初心者限定だったり、いろいろ条件を設定できるようにしないとどんどん管理するテーブルが増えていく羽目になります。

ミッション

 「○○をクリアしよう!」みたいなやつ。達成システムと達成条件、解放条件がそれぞれ必要か。

 再帰的に達成判定を行うことになるので、これがいろいろなところで足を引っ張って重くなる場合もあるため実装には注意。

 またこちらもデイリーだったりウィークリーだったり初心者限定だったりイベント限定だったりしてどんどん増えていきます。期間と条件でカウンタをリセットできるように考えておくとよいです。

ギフト

 プレイヤーへのアイテム配布システム。補填などでも使います。

 個別に配布するものと、一括で全体に配布するものとが必要になります。

 これも割と重くて、ゲームシステムによっては倉庫代わりにストックされたりするので、そうならないようなゲーム設計が必要になります。

ガチャ

 ガチャや召喚など、抽選で報酬を配布する機能です。

 消費アイテムが石だったり特殊アイテムだったりチケットだったり、また1日1回無料とか期間限定とかいろいろ増えていきます。

 抽選部分についてはガチャだけでなくアイテムドロップなどでも使用するため別に考えます。

フレンド

 他のプレイヤーとつながる感じのやつです。

レイド

 複数のプレイヤーでボスを倒すみたいなやつです。

 減算されるレコードが集中するので注意が必要です。

ギルド

 複数のプレイヤーでグループを作るシステムです。フレンドの拡張みたいな感じ。

 チャットなどもあるかも。

ユーザー同士の交流は注意が必要

 チャットなどでユーザー同士が交流できる場を設ける場合はいろいろと注意が必要です。

 投稿を監視したり単語フィルタを設定したりして、犯罪の温床やトラブルの元にならないようにしないといけなくなります。

確率抽選

 いわゆるガチャで使いますし、その他にもアイテムドロップや強化成功などで使います。

 抽選方法は重み付け、いわゆる優先度の割合で設定できるようにしておくと楽だと思います。

 (参考:Walker's Alias Methodの箱の作り方のわかりやすい説明)

チート対策

パラメータは改ざんされます

 パラメータは改ざんされます。改ざん検知できるようハッシュを付けるなどしておきます。

メモリも改ざんされます

 アプリ側の情報はだいたい改ざんされるものだと思っておいたほうがよいです。

 そのためアイテムドロップやガチャの抽選など、ロジックは基本的にサーバー側で囲い込みます。

 バトルのようにアプリ側の結果を反映させる必要がある場合は、ありえない結果を検知するなどチートの閾値を決めて判断したりします。

通信はHTTPではなくHTTPSにする

 ステートレスな感じでHTTP通信するならHTTPSで行います。今だとAppleとかにHTTPSにさせられるのである意味問題ないです。

運用編

運用を考えた開発をする

 開発しているときはとにかく実装となりがちで、SQLを発行して対応とかサーバーにログインしてコマンドを叩いて対応とかあると思います。

 そのとき限りであればよいのですが、データの参照や修正などは本番運用が始まってからも発生します。

 そのときに毎回SQL発行してたいおうしないといけないとか死にます。1日2日ならいいのですが、1年2年と続けることになると死にます。

 どう作ってどう運用するかまでシミュレートしておくことは必要です。

スタッフの負荷を下げる

 サービスを長続きさせるには、まず関わっている人が幸せで、それを長く続けたいと思える環境でなければ難しいです。

 残業させない、深夜メンテさせない、休日自主待機をさせないなど、スタッフの負荷を下げるようにしないと人が入れ替わるだけでサービスが育たず死にます。

 汎用スキルの高さより、そのサービスに詳しく経験を積んだ人の方が貴重です。サービス特有の仕様や動作、トラブルの経験はぐぐっても出てきません。

 ただこの話は、売り上げだけを考えてるところでは実施されないと思います。「ビジネス > スタッフ」ではなく、「スタッフ > ビジネス」と考えると継続しやすいのではないかと考えています。

ワークフローを整えておく

 対応や報告のワークフロー、どこに情報を集めるかは最初のうちに決めておくと楽です。

 報告漏れや対応忘れがなくなり結果的にコストが下がります。

 「障害発生 -> 調査 -> 報告・対応判断 -> 対応 -> ユーザーへの告知 -> クローズ」までがよくある一連の流れでしょうか。

さいごに

 割と雑に書きました。これが全てとは思っていないです。不十分かもしれないし他の方法が良いかもしれません。

 ガチャゲーって簡単そうで実際そんな複雑じゃないかもしれないけど数百万アカウントを抱えて毎日数万~数十万のユーザーがヘビーに使うシステムです。油断すると死にます。

スポンサーリンク