Mirrativ Tech Blog

株式会社ミラティブの開発者(バックエンド,iOS,Android,Unity,機械学習,インフラ, etc.)によるブログです

【Go/GCP】ライブゲーム「あてっこ!ぷにまるず」を支えるバックエンド技術

バックエンドエンジニアの makino です。本日は、先日リリースしたライブゲーム「あてっこ!ぷにまるず」のバックエンド技術について紹介します。

ライブゲーム「あてっこ!ぷにまるず」について

ライブゲームとは、Mirrativアプリ上で遊べるゲームであり、配信中のゲームに視聴者が介入できることが特徴です。
「あてっこ!ぷにまるず」では、配信中に視聴者を招待して一緒にGvGバトルを楽しむことができます。

Mirrativのライブゲームは、MirrativアプリのWebView上でWebGLで動作します。クライアント側の技術については以下の記事で紹介されているので、ぜひこちらの記事もご覧ください。 tech.mirrativ.stream

tech.mirrativ.stream

ライブゲームにおけるバックエンドサーバの役割

ライブゲームのバックエンドサーバは、ゲームデータの管理を行いつつ、Mirrativが提供するライブゲームAPI (OpenID Connect) を介して、ユーザー情報取得やユーザー招待、コメント投稿などを行います 。
また、Mirrativサーバからコメント投稿やギフトが贈られたイベントをWebhook経由で受け取り、ゲームクライアントにリアルタイムに反映を行います。

上記のようにライブゲームAPIを介することで、他のゲーム開発会社様もMirrativ上でライブゲームを提供することができるようになっています。

バックエンドのシステム構成

「あてっこ!ぷにまるず」のバックエンド開発では、言語はGo、クラウド環境はGCPを採用しています。
開発期間が短く、人数も少数でしたが、GCPのマネージドサービスを積極的に活用することで、効率よく開発を進めることができました。

以下、いくつかのトピックに分けて今回のシステムについて紹介します。

バックエンドサーバの実行環境

バックエンドサーバの実行環境としてはCloud Runを利用しています。当初はCloud Profilerサポートする実行環境として Cloud Run が明記されていなかったため、App Engineの利用を検討しましたが、動作確認をしてみたところCloud RunでもCloud Profilerを動かすことができたため、より柔軟な環境を選択できるCloudRunを採用することにしました。
非同期処理に関しては、Cloud Tasks経由で CloudRun Jobsを利用しています。

クライアントへのリアルタイム同期

前述の通り、Mirrativサーバからコメント投稿やギフトが贈られたイベントをゲームクライアントにリアルタイムに同期する必要があります。当初はWebSocketサーバを立てて同期することも検討しましたが、開発/運用コストをより少なくするためにFirestoreを採用しました。リアルタイム同期の用途としてFirestoreを利用するのは初めての試みでしたが、導入が容易で遅延も少なく、今後もぜひ活用していきたいと思いました。
ちなみに、クライアントSDKに関して、WebGLビルドの場合はjslibを使うためC#側でブリッジスクリプトを書く必要があるとのことです。

チームマッチング

「あてっこ!ぷにまるず」ではメインの対戦機能においてPhoton Fusionを利用していますが、GvGのようなチームマッチングをサポートする機能がないようだった*1ので、ゲームサーバ側でチームマッチング機能を実装しました。
「あんさんぶるスターズ!!Music」さんの事例を参考にして、RedisのList型を用いてマッチングを実現しています。
あんさんぶるスターズ!!Musicのマルチプレイ機能「みんなでライブ」のマッチング実装 - Qiita

データベース

データベースは使い慣れたMySQLを扱いたかったため、Cloud SQLを利用しています。
リードレプリカを複数用意した際にいい感じにリクエストを分散させたかったため、以下の記事を参考にしてCloud DNSでReader Endpointの実装を行いました。
Cloud SQL に Reader Endpoint 的なものを作ってみる | by Jin Naraoka | google-cloud-jp | Medium

CI/CD

CIはPR作成/更新時にCloud Build上でテストが実行されます。
また、デプロイ時はgitのタグ作成をトリガーにして、Cloud Build上でコンテナイメージの作成、データベースのマイグレーション、マスタデータのロード、Cloud Runへのデプロイが行われます。
ちなみに、リリース前の負荷試験ではk6を使ってCloud Build上から負荷をかけました。このあたりの詳細はまた別の記事で紹介できればと思っております。 k6.io

エラー監視

Error Reportingを使ってSlackに通知するようにしています。

Goのエラー生成時にスタックトーレスを付与するためにpkg/errorsパッケージを利用しているのですが、pkg/errorsが生成するスタックのフォーマットはError Reporting側でパースできない*2ため、下記のissueで言及されているパッチを当ててError Reporting上でもスタック情報を参照できるようにしました。 github.com

分析

Big Queryから連携クエリを利用して、Cloud SQL上のデータベースにクエリを叩けるようにしています。
また、Cloud LoggingのLog Anlytics機能を有効にして、Big Queryからログに対してクエリを実行できるようにしました。
コンソール上で設定を行うだけですぐに分析環境を用意することができたので、大変便利でした。

まとめ

今回のライブゲームは少人数で短期間の開発でしたが、GCPのマネージドサービスを活用して、スピード感を持って開発を進めることができました。
新規にゲームやサービスのバックエンド開発をする際に、この記事がお役に立てば幸いです。

We are hiring!

ミラティブでは、ライブゲームという新しい挑戦に向けてスピード感を持って開発を推進するエンジニアを募集しています!

mirrativ.co.jp

speakerdeck.com

mirrativ.notion.site

*1:Photon PUNではマッチメイキングのスロット予約をする機能で実現できそうです

*2:https://golang.org/pkg/runtime/debug/#Stackと同じフォーマットの必要があります