※資料内の参照リンクを選択し閲覧する場合は、ダウンロードをお願いいたします
\積極的に技術発信を行なっております/ ▽ Twitter/COLOPL_Tech https://twitter.com/colopl_tech
▽ connpassページ http://colopl.connpass.com
▽ COLOPL Tech Blog http://blog.colopl.dev
コロプラのリアルタイム通信基盤2022/03/17
View Slide
自己紹介● R.Y.○ 最近ニックネームが欲しくなってきた● 2020年4月 新卒入社● 技術基盤本部 第2バックエンドエンジニア部 prizmチーム2
前提: コロプラでよくあるリアルタイム通信● 部屋を作りその中でプレイヤー同士で対戦や協力などをするゲーム○ MMO のように一つの大きなワールドを管理するようなゲームではないRoom A Room B Room Cこんなイメージ3
リアルタイム通信を実現するために● 最初はそれぞれのプロジェクトで独自に実装していた○ WebSocket を利用したものや C++ によるサーバー実装など多様● リアルタイム通信を扱うプロジェクトが増えたことなどを理由にprizm の前身となるリアルタイム通信のフレームワークを作成○ Node.js 製● メンテナンス性や並行性などの理由から Go でリアルタイム通信のフレームワークを作り直すことにして現在に至る4
prizm に求められた要求事項● TCP と UDP の両方を使える○ 入室時のユーザー情報やゲームの結果の同期など TCP が欲しい場面も存在● サーバー側にロジックを書ける● GKE 上で動作する● チームで開発されている○ ドキュメント・サポートが手厚い5
prizm とは● コロプラで開発している対人や協力などリアルタイム性のあるゲームのためのフレームワーク○ サーバー(Go): いわゆるリアルタイムサーバーを作るためのフレームワーク○ クライアント(Unity, C#): リアルタイムサーバーと通信するクライアントの基盤ライブラリ● 部屋内でのメッセージのやり取りをすることを想定しているシンプルな作り○ 物理演算などはしない● 開発・運用で便利な機能や特定のインフラ環境への対応はコア機能からは外している○ 例えば Kubernetes 環境を前提にするとローカル環境の構築が面倒6
prizm のコア機能prizm Server クライアント Message Message Message Message Message Message Message クライアント・サーバー間でメッセージを送り合う7
prizm のコア機能prizm Server func OnChatMessage(...) {BroadcastChatMessage(...)}Message受信時の処理をサーバー側に実装8
prizm のコア機能● メッセージ送信○ クライアント→サーバー○ サーバー→クライアント● メッセージ受信時の処理をサーバーに実装9
prizm の特徴● コード生成● モック環境● 可観測性● Kubernetes インフラ● サポート体制● その他方針・考えていることなど10
prizm の特徴● コード生成● モック環境● 可観測性● Kubernetes インフラ● サポート体制● その他方針・考えていることなど11
コード生成● クライアント・サーバーの開発を効率化するためCLI ツールによるコード生成を多用○ プロジェクト全体の生成○ メッセージ定義の生成○ リレーメッセージの生成12
プロジェクト生成● CLI ツールでプロジェクトの雛形を作成$ prizm new ...13
プロジェクト生成● CLI ツールでプロジェクトの雛形を作成$ prizm new ...ロギング用のパッケージやテスト用の bot なども生成14
メッセージ定義とコード生成● .proto ファイルをもとに C# / Go のコードを自動生成○ メッセージ構造の定義○ メッセージ送信やメッセージ受信時のハンドラの実装に必要なスタブコードsyntax = "proto3";service GameService {rpc SendMessage() ...}message TestMessage {string body = 1;}GameService.csgameservice.go15
メッセージ定義とコード生成● .proto ファイルをもとに C# / Go のコードを自動生成○ メッセージ構造の定義○ 送受信に必要なスタブコード$ mkdir -p pkg/proto$ prizm generateGenerating proto/prizm.protoGenerating pkg/proto/message.goGenerating pkg/proto/chatservice.goGenerating pkg/proto/chatservice_client.go...16
リレーメッセージの生成● 部屋全体にそのままメッセージを転送(リレー)するメッセージの生成● サーバー側にロジックが不要な場合の実装コストを減らせる○ 前述したようなやり方だとメッセージを増やすたびにサーバーの再ビルドが必要だった○ リレーメッセージを使えば クライアントのみの変更 でメッセージを追加できるChatMessage ChatMessage 17
リレーメッセージの生成● コード生成用の .proto ファイルにリレー専用の書き方をするsyntax = "proto3";service InGameService {option(bind_relay) = xxx;}message RelayMessage {Move move = 1;Chat chat = 2;}message Move { … }message Chat { … }Chat.Relay.cschat_relay.go18
prizm の特徴● コード生成● モック環境● 可観測性● Kubernetes インフラ● サポート体制● その他方針・考えていることなど19
prizm のモック環境● クライアントエンジニアのみでマルチプレイを作りたい!という要求をもとに常設のモック用サーバーを用意○ ゲーム開発初期のモックを開発する段階を意識○ Photon Cloud のような感覚で使える● モック環境では前述のリレーメッセージを利用○ リレーメッセージの「クライアントのみの変更でメッセージを追加できる」特性を利用○ 開発が進んで専用の prizm サーバーを立てたときにもクライアント側の実装をそのまま使える20
prizm のモック環境prizm mockserverprizmチーム ゲーム開発チーム ① モック準備依頼 21
prizm のモック環境prizm mockserverprizmチーム ゲーム開発チーム ① モック準備依頼 ② namespace追加 22
prizm のモック環境prizm mockserverprizmチーム ゲーム開発チーム ① モック準備依頼 ② namespace追加 ③ 利用 23
prizm の特徴● コード生成● モック環境● 可観測性● Kubernetes インフラ● サポート体制● その他方針・考えていることなど24
prizm の可観測性● 実装のミスやパフォーマンスの問題を気づきやすくするため、以下の方法で指標を公開○ Prometheus exporter(メトリクス)○ Opencensus Tracing(分散トレース)○ pprof / Cloud Profiler(プロファイラ)● 1月に prizm に Cloud Profiler という GCP が提供しているプロファイラを導入したときの話を発表しているので良かったらそちらも見てください25
prizm の可観測性26
prizm の特徴● コード生成● モック環境● 可観測性● Kubernetes インフラ● サポート体制● その他方針・考えていることなど27
prizm の動作環境● ローカル環境○ Go でビルド可能な環境であれば OK○ Windows, Mac, Linux, …● dev, stg, 本番環境○ Kubernetes や Agones を活用できるようにしている■ Agones: Kubernetes 上でゲームのリアルタイム通信のようなステートフルなサーバーを管理できるようにしてくれる OSS○ 次の発表でここらへんを詳しく発表してもらいます28
Kubernetes 環境での prizm● prizm と Agones SDK との間で必要なやりとりをprizm 開発チームでライブラリ化prizm server Agones sidecar Agones SDKとのやりとりをライブラリ化29
クラウド環境でのログ出力● ターミナル上ではプレーンテキストで出力○ 目で追いやすいようにしている● クラウド環境ではJSON で出力○ GCP Cloud Logging で処理しやすくしている30
prizm の特徴● コード生成● モック環境● 可観測性● Kubernetes インフラ● サポート体制● その他方針・考えていることなど31
prizm のサポート体制● prizm の開発や prizm を用いたゲーム開発をサポートするチームを編成● prizm や prizm を用いたゲーム開発をサポートするために2種類のドキュメントを整備○ ゲーム開発ガイド(ゲーム開発者向け)○ 内部仕様ドキュメント(ライブラリ開発者向け)● また、 prizm を利用したゲーム開発のイメージを掴んでもらうためのサンプルを用意○ ターン制のゲーム(リバーシ)○ マッチングの骨組み32
prizm のサポート体制● ゲーム開発ガイド(ゲーム開発者向け)33
prizm のサポート体制● 内部仕様ドキュメント(ライブラリ開発者向け)34
prizm の特徴● コード生成● モック環境● 可観測性● Kubernetes インフラ● サポート体制● その他方針・考えていることなど35
複数のプレイヤーを prizm へ接続させる● マルチプレイを提供するためにはサーバーやルームを用意するだけではだめで、用意したルームに他のプレイヤーが入れるようにする必要がある● これを実現するためには以下のものが必要○ 存在するサーバー / 部屋を見つける機能( Service Discovery?)○ プレイヤーを適切な部屋に紐付ける機能(マッチング)● prizm 自体にはこれらの機能を載せず、API サーバーなどで実装するようにしている○ prizm の機能をシンプルにするため36
新しく部屋を作ったときprizm-serverAPI Server (PHP)Database 等の部屋情報をDBに保存37
既存の部屋に参加するときprizm-serverAPI Server(PHP)マルチの部屋に参加したい部屋番号: 12345Database38
既存の部屋に参加するときprizm-serverAPI Server(PHP)マルチの部屋に参加したい部屋番号: 12345Database 部屋番号: 12345の部屋データ(IP:Port)を取得39
既存の部屋に参加するときprizm-serverAPI Server(PHP) のprizm へ接続Database 部屋番号: 12345の部屋データ(IP:Port)を取得40
設計方針● 自前実装はなるべく避け、広く使われている実装があればそれを使う○ JWT(認証)○ TLS(暗号化)○ Prometheus(メトリクス)● パフォーマンスよりも使いやすさを重視○ パフォーマンスを軽視しているわけではないです■ 使い勝手の悪くなるパフォーマンスチューニングはしない、といった感じ○ コード以外の面でも使いやすさを追求■ ドキュメントやサポートを充実させて間違った使い方を防ぐ■ プロファイリングを充実させて実装ミスに素早く気付けるようにする41
設計方針● テストをちゃんとやる○ テスト内で実際に TCP / UDP サーバーを立てて通信してみる○ パケットの損失や遅延、順序入れ替えをシミュレートする○ C# クライアントと Go サーバーでの結合テストもする○ make test ですべてのテストが実行されるし、 CI でもテストが回る⇒新機能追加時・リファクタリング時の安心感につながる!42
現状の課題● 依存ライブラリの追従○ Kubernetes 関連は動きが早いのでついていくのが大変● 異常系を考慮した設計の共有○ 切断などからの復帰やサーバー障害への考慮など○ ゲームの仕様によってやりたいことが変わってくるのでライブラリ化が難しい● コロプラのメイン言語(PHP)と異なる言語での開発○ ゲーム開発チームへのレクチャー・サポートが必要○ ドキュメントを頑張って書く、積極的にサポートしにいく● 運用が始まったばかり○ 実際に運用していく中で知見を貯めていく、課題を解決していく43
まとめ● コロプラ内製のリアルタイム通信基盤 prizm を紹介○ 合わせてコード生成やクラウド環境への対応など開発・運用に必要なものも紹介● 優れた設計・パフォーマンスよりも使う側にとっての分かりやすさを重視○ 最終的なゴールはゲームを作って良いものにしていくこと● 技術力だけでなく使い手側の気持ちになることが大事○ ドキュメント○ サポート体制44