Slide 1

Slide 1 text

コロプラの リアルタイム通信基盤 2022/03/17

Slide 2

Slide 2 text

自己紹介 ● R.Y. ○ 最近ニックネームが欲しくなってきた ● 2020年4月 新卒入社 ● 技術基盤本部 第2バックエンドエンジニア部 prizmチーム 2

Slide 3

Slide 3 text

前提: コロプラでよくあるリアルタイム通信 ● 部屋を作りその中でプレイヤー同士で対戦や協力などをするゲーム ○ MMO のように一つの大きなワールドを管理するようなゲームではない Room A Room B Room C こんなイメージ 3

Slide 4

Slide 4 text

リアルタイム通信を実現するために ● 最初はそれぞれのプロジェクトで独自に実装していた ○ WebSocket を利用したものや C++ によるサーバー実装など多様 ● リアルタイム通信を扱うプロジェクトが増えたことなどを理由に prizm の前身となるリアルタイム通信のフレームワークを作成 ○ Node.js 製 ● メンテナンス性や並行性などの理由から Go でリアルタイム通信の フレームワークを作り直すことにして現在に至る 4

Slide 5

Slide 5 text

prizm に求められた要求事項 ● TCP と UDP の両方を使える ○ 入室時のユーザー情報やゲームの結果の同期など TCP が欲しい場面も存在 ● サーバー側にロジックを書ける ● GKE 上で動作する ● チームで開発されている ○ ドキュメント・サポートが手厚い 5

Slide 6

Slide 6 text

prizm とは ● コロプラで開発している対人や協力などリアルタイム性のある ゲームのためのフレームワーク ○ サーバー(Go): いわゆるリアルタイムサーバーを作るためのフレームワーク ○ クライアント(Unity, C#): リアルタイムサーバーと通信するクライアントの基盤ライブラリ ● 部屋内でのメッセージのやり取りをすることを想定しているシンプルな作り ○ 物理演算などはしない ● 開発・運用で便利な機能や特定のインフラ環境への対応は コア機能からは外している ○ 例えば Kubernetes 環境を前提にするとローカル環境の構築が面倒 6

Slide 7

Slide 7 text

prizm のコア機能 prizm Server
 クライアント
 Message
 Message
 Message
 Message
 Message
 Message
 Message
 クライアント・サーバー間でメッ セージを送り合う 7

Slide 8

Slide 8 text

prizm のコア機能 prizm Server
 func OnChatMessage(...) { BroadcastChatMessage(...) } Message受信時の処理を サーバー側に実装 8

Slide 9

Slide 9 text

prizm のコア機能 ● メッセージ送信 ○ クライアント→サーバー ○ サーバー→クライアント ● メッセージ受信時の処理をサーバーに実装 9

Slide 10

Slide 10 text

prizm の特徴 ● コード生成 ● モック環境 ● 可観測性 ● Kubernetes インフラ ● サポート体制 ● その他方針・考えていることなど 10

Slide 11

Slide 11 text

prizm の特徴 ● コード生成 ● モック環境 ● 可観測性 ● Kubernetes インフラ ● サポート体制 ● その他方針・考えていることなど 11

Slide 12

Slide 12 text

コード生成 ● クライアント・サーバーの開発を効率化するため CLI ツールによるコード生成を多用 ○ プロジェクト全体の生成 ○ メッセージ定義の生成 ○ リレーメッセージの生成 12

Slide 13

Slide 13 text

プロジェクト生成 ● CLI ツールでプロジェクトの雛形を作成 $ prizm new ... 13

Slide 14

Slide 14 text

プロジェクト生成 ● CLI ツールでプロジェクトの雛形を作成 $ prizm new ... ロギング用のパッケージや テスト用の bot なども生成 14

Slide 15

Slide 15 text

メッセージ定義とコード生成 ● .proto ファイルをもとに C# / Go のコードを自動生成 ○ メッセージ構造の定義 ○ メッセージ送信やメッセージ受信時のハンドラの実装に必要なスタブコード syntax = "proto3"; service GameService { rpc SendMessage() ... } message TestMessage { string body = 1; } GameService.cs gameservice.go 15

Slide 16

Slide 16 text

メッセージ定義とコード生成 ● .proto ファイルをもとに C# / Go のコードを自動生成 ○ メッセージ構造の定義 ○ 送受信に必要なスタブコード $ mkdir -p pkg/proto $ prizm generate Generating proto/prizm.proto Generating pkg/proto/message.go Generating pkg/proto/chatservice.go Generating pkg/proto/chatservice_client.go ... 16

Slide 17

Slide 17 text

リレーメッセージの生成 ● 部屋全体にそのままメッセージを転送(リレー)するメッセージの生成 ● サーバー側にロジックが不要な場合の実装コストを減らせる ○ 前述したようなやり方だとメッセージを増やすたびにサーバーの再ビルドが必要だった ○ リレーメッセージを使えば クライアントのみの変更 でメッセージを追加できる ChatMessage
 ChatMessage
 17

Slide 18

Slide 18 text

リレーメッセージの生成 ● コード生成用の .proto ファイルにリレー専用の書き方をする syntax = "proto3"; service InGameService { option(bind_relay) = xxx; } message RelayMessage { Move move = 1; Chat chat = 2; } message Move { … } message Chat { … } Chat.Relay.cs chat_relay.go 18

Slide 19

Slide 19 text

prizm の特徴 ● コード生成 ● モック環境 ● 可観測性 ● Kubernetes インフラ ● サポート体制 ● その他方針・考えていることなど 19

Slide 20

Slide 20 text

prizm のモック環境 ● クライアントエンジニアのみでマルチプレイを作りたい!という 要求をもとに常設のモック用サーバーを用意 ○ ゲーム開発初期のモックを開発する段階を意識 ○ Photon Cloud のような感覚で使える ● モック環境では前述のリレーメッセージを利用 ○ リレーメッセージの「クライアントのみの変更でメッセージを追加できる」特性を利用 ○ 開発が進んで専用の prizm サーバーを立てたときにも クライアント側の実装をそのまま使える 20

Slide 21

Slide 21 text

prizm のモック環境 prizm mock server prizmチーム
 ゲーム開発チーム
 ① モック準備依頼
 21

Slide 22

Slide 22 text

prizm のモック環境 prizm mock server prizmチーム
 ゲーム開発チーム
 ① モック準備依頼
 ② namespace追加
 22

Slide 23

Slide 23 text

prizm のモック環境 prizm mock server prizmチーム
 ゲーム開発チーム
 ① モック準備依頼
 ② namespace追加
 ③ 利用
 23

Slide 24

Slide 24 text

prizm の特徴 ● コード生成 ● モック環境 ● 可観測性 ● Kubernetes インフラ ● サポート体制 ● その他方針・考えていることなど 24

Slide 25

Slide 25 text

prizm の可観測性 ● 実装のミスやパフォーマンスの問題を気づきやすくするため、 以下の方法で指標を公開 ○ Prometheus exporter(メトリクス) ○ Opencensus Tracing(分散トレース) ○ pprof / Cloud Profiler(プロファイラ) ● 1月に prizm に Cloud Profiler という GCP が提供しているプロファイラを 導入したときの話を発表しているので良かったらそちらも見てください 25

Slide 26

Slide 26 text

prizm の可観測性 26

Slide 27

Slide 27 text

prizm の特徴 ● コード生成 ● モック環境 ● 可観測性 ● Kubernetes インフラ ● サポート体制 ● その他方針・考えていることなど 27

Slide 28

Slide 28 text

prizm の動作環境 ● ローカル環境 ○ Go でビルド可能な環境であれば OK ○ Windows, Mac, Linux, … ● dev, stg, 本番環境 ○ Kubernetes や Agones を活用できるようにしている ■ Agones: Kubernetes 上でゲームのリアルタイム通信のような ステートフルなサーバーを管理できるようにしてくれる OSS ○ 次の発表でここらへんを詳しく発表してもらいます 28

Slide 29

Slide 29 text

Kubernetes 環境での prizm ● prizm と Agones SDK との間で必要なやりとりを prizm 開発チームでライブラリ化 prizm server
 Agones
 sidecar
 Agones SDKとの やりとりをライブラリ化 29

Slide 30

Slide 30 text

クラウド環境でのログ出力 ● ターミナル上では プレーンテキストで出力 ○ 目で追いやすいように している ● クラウド環境では JSON で出力 ○ GCP Cloud Logging で 処理しやすくしている 30

Slide 31

Slide 31 text

prizm の特徴 ● コード生成 ● モック環境 ● 可観測性 ● Kubernetes インフラ ● サポート体制 ● その他方針・考えていることなど 31

Slide 32

Slide 32 text

prizm のサポート体制 ● prizm の開発や prizm を用いたゲーム開発をサポートするチームを編成 ● prizm や prizm を用いたゲーム開発をサポートするために 2種類のドキュメントを整備 ○ ゲーム開発ガイド(ゲーム開発者向け) ○ 内部仕様ドキュメント(ライブラリ開発者向け) ● また、 prizm を利用したゲーム開発のイメージを掴んでもらうための サンプルを用意 ○ ターン制のゲーム(リバーシ) ○ マッチングの骨組み 32

Slide 33

Slide 33 text

prizm のサポート体制 ● ゲーム開発ガイド(ゲーム開発者向け) 33

Slide 34

Slide 34 text

prizm のサポート体制 ● 内部仕様ドキュメント(ライブラリ開発者向け) 34

Slide 35

Slide 35 text

prizm の特徴 ● コード生成 ● モック環境 ● 可観測性 ● Kubernetes インフラ ● サポート体制 ● その他方針・考えていることなど 35

Slide 36

Slide 36 text

複数のプレイヤーを prizm へ接続させる ● マルチプレイを提供するためにはサーバーやルームを用意するだけでは だめで、用意したルームに他のプレイヤーが入れるようにする必要がある ● これを実現するためには以下のものが必要 ○ 存在するサーバー / 部屋を見つける機能( Service Discovery?) ○ プレイヤーを適切な部屋に紐付ける機能(マッチング) ● prizm 自体にはこれらの機能を載せず、 API サーバーなどで実装するようにしている ○ prizm の機能をシンプルにするため 36

Slide 37

Slide 37 text

新しく部屋を作ったとき prizm-server API Server (PHP) Database 等の部屋情報を DBに保存 37

Slide 38

Slide 38 text

既存の部屋に参加するとき prizm-server API Server (PHP) マルチの部屋に参加した い 部屋番号: 12345 Database 38

Slide 39

Slide 39 text

既存の部屋に参加するとき prizm-server API Server (PHP) マルチの部屋に参加した い 部屋番号: 12345 Database 部屋番号: 12345 の部屋データ(IP:Port) を取得 39

Slide 40

Slide 40 text

既存の部屋に参加するとき prizm-server API Server (PHP) のprizm へ接続 Database 部屋番号: 12345 の部屋データ(IP:Port) を取得 40

Slide 41

Slide 41 text

設計方針 ● 自前実装はなるべく避け、広く使われている実装があればそれを使う ○ JWT(認証) ○ TLS(暗号化) ○ Prometheus(メトリクス) ● パフォーマンスよりも使いやすさを重視 ○ パフォーマンスを軽視しているわけではないです ■ 使い勝手の悪くなるパフォーマンスチューニングはしない、といった感じ ○ コード以外の面でも使いやすさを追求 ■ ドキュメントやサポートを充実させて間違った使い方を防ぐ ■ プロファイリングを充実させて実装ミスに素早く気付けるようにする 41

Slide 42

Slide 42 text

設計方針 ● テストをちゃんとやる ○ テスト内で実際に TCP / UDP サーバーを立てて通信してみる ○ パケットの損失や遅延、順序入れ替えをシミュレートする ○ C# クライアントと Go サーバーでの結合テストもする ○ make test ですべてのテストが実行されるし、 CI でもテストが回る ⇒新機能追加時・リファクタリング時の安心感につながる! 42

Slide 43

Slide 43 text

現状の課題 ● 依存ライブラリの追従 ○ Kubernetes 関連は動きが早いのでついていくのが大変 ● 異常系を考慮した設計の共有 ○ 切断などからの復帰やサーバー障害への考慮など ○ ゲームの仕様によってやりたいことが変わってくるのでライブラリ化が難しい ● コロプラのメイン言語(PHP)と異なる言語での開発 ○ ゲーム開発チームへのレクチャー・サポートが必要 ○ ドキュメントを頑張って書く、積極的にサポートしにいく ● 運用が始まったばかり ○ 実際に運用していく中で知見を貯めていく、課題を解決していく 43

Slide 44

Slide 44 text

まとめ ● コロプラ内製のリアルタイム通信基盤 prizm を紹介 ○ 合わせてコード生成やクラウド環境への対応など開発・運用に必要なものも紹介 ● 優れた設計・パフォーマンスよりも使う側にとっての分かりやすさを重視 ○ 最終的なゴールはゲームを作って良いものにしていくこと ● 技術力だけでなく使い手側の気持ちになることが大事 ○ ドキュメント ○ サポート体制 44