Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
cocone TECH TALK Vol.6 - リアルタイム対戦xバックエンドアーキテクチャ
Search
cocone
May 08, 2023
Technology
720
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
cocone TECH TALK Vol.6 - リアルタイム対戦xバックエンドアーキテクチャ
cocone
May 08, 2023
More Decks by cocone
See All by cocone
Cocone_Research_Center_2025.pdf
cocone
0
350
20240301_cocone_EMゆるミートアップvol6_LT資料
cocone
0
950
2024_cocone-wellbeing
cocone
0
5.2k
2023夏季合同企業説明会ココネ
cocone
0
410
cocone TECH TALK Vol.6 - ココネグループのブロックチェーン MOOI Network とのバックエンド連携
cocone
0
660
cocone TECH TALK Vol.6 - Kotlin バックエンドアーキテクチャ of アバターサービス
cocone
0
650
cocone corporation(JPN)/Handbook2022
cocone
1
31k
cocone Tech Talk vol.5 - Unity Dotsを使ってみた
cocone
0
2.6k
cocone corporation(JPN)/Letter to Planner
cocone
0
590
Other Decks in Technology
See All in Technology
【Aiming】共通基盤なのに「共通化しない」課金・認証基盤「LINK」が選び取ったシングルテナント戦略と運用の秘訣
saikeda
0
180
AI-DLC実践録_フルサイクル開発への挑戦
miyuc
0
410
LLM Internals: 언어 모델의 계보와 알고리즘 진화 (2023~2026)
inureyes
PRO
1
910
2026-08-15 JAWS-UG 茨城 #16 Secrets ManagerにおけるSecret値の管理(Terraformの場合) / Secrets Manager Secrets
masasuzu
0
590
小粒でもパワフルなJS Runtime Antjsについて
comamoca
0
120
巨大気象データと戦う ― サロゲートモデル学習を高速化する圧縮技術
gpuunite_official
0
260
Android skills に学ぶ
kokiko
0
170
Data Hubグループ 紹介資料
sansan33
PRO
0
3.2k
Kiro Crew で始める マルチエージェント開発
miu_crescent
PRO
0
170
アクセスキーが漏れた日にやるべきこと- 無効化の先にある本当の対応
kazzpapa3
0
300
tamachi.go 誕生の裏側
rymiyamoto
1
200
Kiro Crew入門 - 常駐エージェントの仕組みと使いどころ / Intro to Kiro Crew
k_adachi_01
1
890
Featured
See All Featured
Claude Code のすすめ
schroneko
67
230k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.5k
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2.1k
Agile that works and the tools we love
rasmusluckow
331
22k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
800
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
73
41k
Building AI with AI
inesmontani
PRO
1
1.2k
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
660
Bootstrapping a Software Product
garrettdimon
PRO
306
120k
Designing for Performance
lara
611
70k
Testing 201, or: Great Expectations
jmmastey
46
8.2k
Transcript
リアルタイム対戦 × バックエンドアーキテクチャ RYO TOMARU
自己紹介 職歴 ゲーム系企業でクライアント /サーバーを主軸に しつつ、配信サービスのフロントエンド実装など も経験。 趣味 個人ゲーム開発、ドット絵、最近引退気味です が光の戦士。最近はGolangとFlutterが好き。 戸丸
良 / RYO TOMARU
本日の内容 • どのような技術を用いて「リアルタイム対戦」を実現したか • 通信フローについてのご紹介 • 苦労したポイント ※詳細なインフラ構成については今回の範囲外となります ...。
目次 1. リアルタイム通信をどの技術で実現するか 2. 今回採用した技術 3. 苦労したポイント 4. まとめ
リアルタイム通信をど の技術で実現するか
多彩な選択肢 最近では、ゲームエンジン側でもサポートが進むなど、開発がしやすい環境となってきてい る。 • 純粋なSocketを用いて構築する • Unity+MLAPI/Mirror/DOTSNET … • Unity
+ Photon/モノビットエンジン/MagicOnion • gRPC Bidirectional Streaming RPC • WebSocketやDatagram … etc …
選択肢が多い上に、一つ一つが難しい
多彩な選択肢 「リアルタイム通信対戦がしたい」だけであれば、どの手段でも実現は可能。 ここに「サービス・ゲームデザインとしてはどうか 」「運用保守の面でどうか」「UXとしてどう か」など、様々な要素を加えて選択していく必要がある。 (難しい・・・) 今回は担当プロダクトにおいて、どのような選択をしたのか、苦労話と合わせてご紹介しま す。
今回採用した技術
gRPCを利用 • 他の機能(API)はgRPCで実装していたため、同一の運用で対応したかった • Unary RPC ◦ Request/Response ◦ 一般的なAPI
• Client Streaming RPC ◦ Clientから任意にデータ送信が可能 ◦ ファイルアプロードなど • Server Streaming RPC ◦ Serverから任意にデータ送信可能 ◦ 通知など • Bidirectional Streaming RPC ◦ 双方向通信 ◦ 相互に任意のタイミングでデータ送信が可能
初期に採用したのは・・・ • 初期(モック)時点では、ゲームデザインが完全に FIXしていなかった • 単純に双方向を選択しておけば大抵なんとかなるよね、から選択 • 慣れていた gRPC Bidirectional
Streaming RPC
gRPC Bidirectional Streaming • 俗に言う双方向通信 • クライアント、サーバー相互に任意のタイミングでデータ送信が行える • oneofを使用し、一つのstreamで複数のコマンドを定義 message
Notify { // どれか1つの情報がくるので、 switchなどで処理を振り分ける oneof event { ChatInfo chat_info = 1; Actor join_actor = 2; … } } service StreamingService { rpc StartNotify(...) returns (stream Notify) {} … }
順調に実装は進んでいったが・・・
実装自体は進んだが、次第に様々な問題が発生 複雑化するコード Client/Server間のやり取りの増加 操作に対して必ず結果が必要 テストの複雑化 増えるoneof 開発コスト増加 send/recvそれぞれのgoroutineを 管理する必要 このメソッドってクライアントに何か投
げるんだっけ・・・? 増え続けるoneof 増え続けるoneof 増え続けるoneof
pickup 増え続けるoneof • Request/ResponseをC/Sのmessageへ追加する • 関係性が非常に難解 message ClientNotify { oneof
event { Say say = 1; Foo foo = 2; Bar bar = 3; Echo echo = 4; … } message Say {...} … } message ServerNotify { oneof event { SayResult say_result = 1; FooResult foo_result = 2; BarResult bar_result = 3; EchoResult echo_result = 4; … } message SayResult {...} … }
まだ間に合う・・・はず! (そもそもゲームデザイン的にあっていないのでは? )
最終的な着地点 • gRPC + Unary RPC + Server Streaming RPC
• 各種操作については、Unary RPC(Request/Response)へ変更 • 自身の操作などはServer Streaming RPCを利用して通知 • より詳細な情報が必要であれば Unary RPCで取得 gRPC + Unary RPC + Server Streaming RPC 意外とすんなりいけるはず
最終的な着地点 • gRPC + Unary RPC + Server Streaming RPC
• 各種操作については、Unary RPC(Request/Response)へ変更 • 自身の操作などはServer Streaming RPCを利用して通知 • より詳細な情報が必要であれば Unary RPCで取得 gRPC + Unary RPC + Server Streaming RPC 全部書き直した
gRPC + Unary RPC + Server Streaming RPC
Redis PubSubを利用
結果としてどうなったか • 基本的にUnary RPCを利用するため、フローがシンプルになった ◦ いつも通りの実装、テスト手法が通用した • Request/ReponseがIDLにて明示的に定義されるため、読みやすい ◦ この操作きたら何を返すんだっけ・・・が無くなった
• Unaryは操作、Streamingはサーバーからの通知と役割を切り分けられた ◦ CRUDとNotifyを切り離せたので、可読性が上がった
苦労したポイント
苦労したポイント 再接続時の復帰処理 復帰時の進行状況に応じて状態を再現する必要があった。 また切断中は自動行動を行うため、タイミングによっては進行不能になるなど、 リリース直前まで頭を悩ませられた。 細かいエッジケース対応 〜の時に〜をするとバグる、という様な話が初期は特に多かった。 最終的にはBOTを作成し、自動的にバトルを繰り返す仕組みでカバーした。 ローンチ後、大きな問題は起きていないので、良い結果が出せた。 参考:
https://qiita.com/maruc/items/2393647be5caa32623e3
苦労したポイント PubSubに悩まされた go-redisを使用していたが、コネクション数が多大になったり、 ConnectionPoolとPubSubの接続状態連携が行われていないなど ...。 最終的にはある程度自前でコントロールを行った。 負荷対策 システム上、最新のデータを取得するケースが多く、 Primaryアクセスが頻発。 キャッシュアサイドパターンを用いることで、負荷軽減を行った。
(整合性を担保する必要があるので、可能であれば避けたい所ではあった)
pickup go-redis pubsub • 1購読=1コネクションが貼られる • アクティブが1万人いたら1万コネクション ◦ パフォーマンスが著しく低下 ◦
ElasctiCacheの上限にもかかる • 最終的にAPでコネクションを自前プールするよう実装 • 一つのコネクションで複数サブスクライブできるように変更 • 内部的に各Sessionのgo:channelへpush ◦ ch <- event
まとめ
まとめ • 当たり前ですが「ゲームデザインにあった」技術選定、設計が重要。 • 表面上動くものはすぐに作れる時代ではあるが、その先が深い。 ◦ このタイミングで切断されたら・・・ ◦ 地下鉄で瞬断したら・・・ ◦
バイナリが改造されたら・・・ etc • 「どのようにテストを行うか」も初期段階で考えておくと良い。 • 開発中はクライアント担当とずっと「うーん・・・」と唸ることになる。 • ・・・とはいえ、開発自体は楽しい!
ご静聴ありがとうございました