Upgrade to Pro — share decks privately, control downloads, hide ads and more …

アナザーエデンにおける非同期オートセーブを用いた通信待ちストレスのないゲーム体験の実現

gree_tech
September 06, 2017

 アナザーエデンにおける非同期オートセーブを用いた通信待ちストレスのないゲーム体験の実現

CEDEC 2017 にて発表された資料です
http://cedec.cesa.or.jp/2017/session/ENG/s58e0fb2eb6330/

gree_tech

September 06, 2017
Tweet

More Decks by gree_tech

Other Decks in Technology

Transcript

  1. ⾃⼰紹介 • ⻄⽥ 綾佑 (ニシダ リョウスケ) • グリー株式会社 Wright Flyer

    Studios事業本部 • エンジニア • @hosi_mo 2014年 東京⼤学⼤学院 情報理⼯学系研究科修了 同年 グリー株式会社 ⼊社 Wright Flyer StudiosにてLINEタワーライジングの開発を経て、アナザーエデンの開発を担当。 アナザーエデンでは、StateMachineを導⼊したゲームループとイベントハンドラの設計、 UIフレームワークの整備、サウンド基盤、ネットワーク基盤、データストア、アセット管理、オートセーブ周りを 主に担当していました。
  2. ⾃⼰紹介 • 鈴⽊ 清⼈ (スズキ キヨト) • グリー株式会社 • Wright

    Flyer Studios事業本部 • リードエンジニア 2001年 横浜国⽴⼤学 ⼯学部 電⼦情報⼯学科卒業 2013年 グリー株式会社 ⼊社 グリーが⼤規模なサーバ負荷にどうやって対処しているのかを⾒たいと思って⼊社したら、な ぜか⾃ら負荷を作り出すための活動をすることに BIシステム、「天と⼤地と⼥神の魔法」のサーバアプリ開発を経て、「アナザーエデン」の各 種パイプラインの下回り全般を担当
  3. スマホゲーム vs コンシューマゲーム スマホ コンシューマ ゲームサイクル ホーム -> ゲーム ゲーム

    -> 設定 運⽤形態 サービス パッケージ 更新頻度 ⾼ 低 1プレイ時間 5分から10分 数⼗分 データ通信頻度 ⾼ 低 ダウンロード 分割か逐次 ⼀括 ユーザデータ サーバ ローカル
  4. アナザーエデンの場合 スマホ コンシューマ アナザーエデン ゲームサイクル ホーム -> ゲーム ゲーム ->

    設定 ゲーム -> 設定 運⽤形態 サービス パッケージ サービス 更新頻度 ⾼ 低 中 1プレイ時間 5分から10分 数⼗分 数⼗分 データ通信頻度 ⾼ 低 ⾼ (Background) ダウンロード 分割か逐次 ⼀括 選択性 ユーザデータ サーバ ローカル ハイブリッド
  5. 「クライアント > サーバ」とは? • ⼤きなコードベース • データ設計の主体 • クライアント単体で動作 •

    開発⼈員の⼤部分を投⼊ • ⼩さなコードベース • クライアントのスキーマをミラー • ミラーストレージに過ぎない • イベントフック主体 • 少⼈数で⼿間をかけずにメンテ
  6. • いつ中断しても途中からやり直せる • 割り込みの多いスマフォでも納得感のある挙動を オートセーブ : アプローチ • プレイヤーの没⼊感を邪魔しない •

    ネットワーク環境に依存しない キューイングとバックグラウンド通信の組み合わせ ステートマシンによるオートセーブ制御
  7. • いつ中断しても途中からやり直せる • 割り込みの多いスマフォでも納得感のある挙動を オートセーブ : アプローチ • プレイヤーの没⼊感を邪魔しない •

    ネットワーク環境に依存しない キューイングとバックグラウンド通信の組み合わせ ステートマシンによるオートセーブ制御
  8. • いつ中断しても途中からやり直せる • 割り込みの多いスマフォでも納得感のある挙動を オートセーブ : アプローチ • プレイヤーの没⼊感を邪魔しない •

    ネットワーク環境に依存しない キューイングとバックグラウンド通信の組み合わせ ステートマシンによるセーブポイント制御
  9. GameServer クライアントからサーバへの同期④ AutoSave! msgpack Push diff Background }Size = 100

    Request Queue Diff リクエストごとローカルDBに保存 たくさんリクエストくる スケーラビリテイだいじ msgpack msgpack msgpack msgpack
  10. GameServer クライアントからサーバへの同期④ AutoSave! msgpack Push diff Background }Size = 100

    Request Queue Diff リクエストごとローカルDBに保存 たくさんリクエストくる スケーラビリテイだいじ msgpack msgpack msgpack msgpack ⾮同期の通信と競合してしまう
  11. OperationBuilderの流れ : 図 diff API Call 抽選 OperationBuilder DB 変更

    AutoSave 出会い実⾏ 命令削除 完了報告
  12. • サーバ • クライアントから完了報告が来るまでは、処理が終わっていな いものとみなす • 終わったときちんと⾔ってくるまで、何度も命令を送りなおす • クライアント側 •

    処理完了をかならず差分と⼀緒に保存する • ⼆回実⾏するのを防ぐ • ⼆回実⾏してもいいが、実⾏前の状態に巻き戻してからだ OperationBuilderのキモ
  13. • Googleが公開しているOSSである • InfluxDBのような、⼤規模なサー バサイド⽤のストレージの基礎技 術になっている • ローカルのファイル構成は、SQLite のような単⼀ファイルではなく、 複数のファイルから構成されてい

    る標準的なDBMSの構成である クライアントサイドDB LevelDB • ソートされた主キー • シンプルなGetter/Setter • スキャンアクセス⽤のブルームフィルタ • コンパクトなC++実装 • 毎回ソースからビルドしている • クエリ単体としてはThread Safe • 複数レコードの⼀括変更⽤のbatchコ マンドの提供 マルチプラットフォーム対応のシンプルで信頼性の⾼いKVS
  14. • ⾼いスケーラビリティ • 2つの主キーによる「近傍の」データへ のアクセス可能性 • 基本はデータサイズではなくスループッ トによる従量課⾦制 • ⾼くもないけど、安くもない

    • フルJSONサポート • ネストされたオブジェクト • Document Store としての側⾯も サーバサイドDB DynamoDB • 主キー以外はスキーマレスだが⽐較的強い型付け • 強い⼀貫性の部分的なサポート • 低い応答性能 • 最速でもミリ秒オーダーのレイテンシ • これは最近出たDAXによってかなり改善され るらしい • ストリーミングによる各種処理系へのデータレプ リケーション • 更新ログをLambda+Kinesisを経由してS3, Redshift等に流せる AWSが提供するManagedなKVS
  15. • レイテンシは問題ではない • どうせバックグラウンドでダラダラ 送る • サーバサイドはイベントフック程度 • 通常のブロッキングコールAPI主体 の設計の場合はクリティカルに

    • 全差分をログシステムに流せる • データの復旧や補正もログから取得 して、パッチを作る • わりと⼿動でやっている アナザーエデンにとってのDynamoDB • シンプルなKVSというだけではさすがに困る • 主キー(ユーザID)にかかわる全デー タスキャンがある程度の速度で動いて欲 しい • 他のパターンは要らない • 要るときはそこだけ別のDBを使う • 使⽤頻度は⾼くないものの半永続的に管理し ていくべきデータがある • トークン系 • データサイズに依存しない仕様が前提に なる
  16. アナザーエデンにとってのDynamoDB • スケールアウトの可否はクリティカルである • クライアント > サーバのため、データ流量をあらかじめ、サーバサイ ドで設計できない • 不可能ではないが、しずらいし、ゲームデザインにおける⾃由度が

    下がり、本末転倒になる • 最終的にどんなゲームに落ち着き、どのくらいのトラフィックが発⽣す るのかわからないが、どんなであれ、それなりのパフォーマンスで動く ことを保障することが⼤事 • 正直いって作ってるときは、どのくらい売れるかどうかもわからん し、それ(売れる確率)も含めて育てていくのがプロダクト開発
  17. 読み込みが⾼速なバイナリシリアライズフォーマット バイナリシリアライザ FlatBuffers • Cocos2d-xで標準的に採⽤ • 強い型付け • ネスト可能 •

    Enumサポート • DSLはデータ構造の記述専⽤ • CとGoのStructの中間くらい • 各項⽬に対して任意のAttribute を付与できる(独⾃拡張可能) • アクセスはオフセットを管理し、 ポインタをずらすだけ • 読み込みはほぼゼロコスト • 書き出しは⽐較的苦⼿ • 新しいデータを間に差し 込むと、後ろを全部ズラ して、インデックスを更 新しないといけない
  18. • 300万DL突破 • リセマラはわりと少なくて2割程度かな、という印象(ちゃんと調べてない) • プレイ時間 • 通しでクリアするのに40-60時間くらい • LevelDBのデータサイズ:

    最⼤1MB程度 • DynamoDBのPartition数: 約128くらい (UserData 概算) • これまでサーバ障害でのサービス停⽌は4回(くらい) • DynamoDBのキャパシティ管理のオペミス x3: 15分-30分 • Redisのマスターノードダウン時の⾃動FailOverの失敗 x1: 1時間 • バグはそれなりにいっぱい(時間の都合で省略) アナザーエデンの規模感
  19. • キャパシティ設定のスケジューリング(独⾃実装) • 前⽇までの消費値を⾒て翌⽇の設定を⾃動で決定(賢い) • なにかイベントがあるときは指定値に設定 • ⼀気に下げすぎないように下限値を指定(絶対値 or ⽐率)

    • オートスケーリング • CloudWatch Alarm + Lambdaで実装 • 条件は最近⼊った本家のものとほぼ同じ(60%を超えたら、1.5倍に) • 微調整が効くので、いまだにこちら側で運⽤している • スロットル(詰まり)監視 • DynamoDBは局所的(Partitionごと)に詰まることがある • ただ、普通はリトライするので、あまり実際の障害と連動しているわけではない DynamoDB運⽤のためにしていること
  20. • ようするにオートセーブ機構はGoogle Firebase Realtime Databaseや AWS Cognitoなどのマネージドサービスの独⾃実装版と⾔えます • 異なるのは以下の3点でしょう •

    FlatBuffersを⽤いることでSchemaをきちんと定義し、中規模のソフト ウェア開発においてコストやリスクを低減している • スケールアウトするDBを利⽤し、特性を把握しつつ運⽤することで、 運営のリスクを低減している • チート対策においては、オートセーブ機構の⼀部として各種の対処をビ ルトインすることで、ゲーム特有のセキュリティの問題に対処している まとめ(鈴⽊)
  21. • 何も考えずに全ての通信をブロッキング通信にしてませんか? • [good] 適切に制御することでバックグラウンドに寄せられるものは多い • [!] ゲームデザインあってこその通信モデルではある • 反省

    : データが壊れた場合の修復がスマートではなかった • [bad] データを2系統で持っておくなどすべきだった • [!] 遠隔で補正するシステムを作っていたため、⼿を動かせば救える まとめ(⻄⽥)