はじめに
どうもこんばんは!ゆうだいです!
Streamerioアドベントカレンダー三日目ということで今日も元気に記事を書いていきます!
まず最初にですが、Streamerioってなに?という方は一日目の記事をご覧ください!
Streamerioってどんなゲーム?
また興味を持ってくれた方はこちらも見ていただけると嬉しいです!
同時接続300人に耐える技術!フロント編!
さて、では始めていきます。
筆者は記事を書き慣れていないので読みづらい部分も度々あるかと思われます。
気になる点があれば、コメントやフィードバックをいただけると嬉しいです。
また今回工夫点と書き紹介している内容ですが、経験のあるエンジニアの方なら当たり前だよと感じる内容かもしれません。お手柔らかにみていただけると幸いです。
同時接続300人に耐える技術!サーバー編!#1
昨日書いた二日目の記事に書いたことですが、同時接続300人といっても1.5秒間フロントで貯めて送るという形式を取っているので秒間リクエスト数は200/sまで落ちます。
ではその200/sを支え、ゲームまでリクエストを送っているサーバーの構成について今日は話そうと思っています。
システム構成図はこちらです。
サーバーのデプロイにはCloud Runを使用しています。
サーバーはHTTPサーバとWebSocketサーバをわけているのですがそれの連携にPub/Subを使用しています。
また来るイベントすべてをUnityに送りつけると描画の問題で重くなり動かなくなるので、視聴者全体で何回押されたらイベントが発生するというしきい値を持たせているのですがそこのカウントはRedisが行っているという感じです。
DBはsupabaseを使用、これはイベントを記録し、最終のゲームクリア時のサマリを作るために使っています。(全部Redisでよくねとはちょっと思ってるのでまた変えると思います。)
Cloud Run周りの話
正直構成図を載せた時点で自分は満足しているのですが、もう少し解説をしたほうがいいなとも思うので書いていきます。
まずHTTPとWebSocketサーバーをわけている理由ですが、Cloud Runの便利さに頼っているからわけているという感じです。
これじゃ言葉が足りなすぎるのでちゃんと書きます。
まずCloud Runの説明です。
書くのが面倒になったのでAIが書きます。
「Cloud Runはコンテナをサーバーレスで実行するGoogle Cloudのフルマネージドサービスです。」
以下省略
何ができるかCloud Runは、Dockerなどのコンテナ化したアプリを、インフラ管理なしでデプロイ・自動スケール・課金まで面倒を見てくれるサービスです。HTTPリクエスト駆動で起動し、トラフィックに応じてゼロから高速にスケールします。言語やフレームワークは自由で、Web API、バックグラウンド処理、イベント駆動ジョブに向いています。
特徴
-
フルマネージド: VMやクラスタ管理不要。リビジョン単位でロールバック可能。
-
起動が速い: リクエストに合わせて自動スケール、アイドル時はゼロスケールでコスト最小化。
-
柔軟なデプロイ: gcloud run deploy やGitHub連携でCI/CD。複数リビジョンのトラフィック分割で段階的リリース。
-
セキュリティ: IAMで認証必須の内部エンドポイント、VPC接続、Secret Manager連携。
-
課金: 実行中のCPU・メモリ・リクエスト・ネットワーク使用量に対して従量課金。
使いどころ
-
小〜中規模のREST/GraphQL APIやWebhook受けアプリ
-
バッチ・イベント処理(Pub/Sub、Cloud Schedulerとの連携)
-
スパイクがあるワークロード、予測しづらいトラフィック
Cloud Run Jobs
長時間のバッチや非HTTP処理はCloud Run Jobsで実行できます。コンテナをジョブとして起動し、成功/失敗の管理、再試行、スケジューリングが可能です。
似たサービスとの違い
-
App Engine: ランタイム固定が多いのに対し、Cloud Runはコンテナで自由度が高い。
-
Cloud Functions: 関数単位で軽量だが、Cloud Runはアプリ全体の制御や依存関係を含めやすい。
-
GKE: Kubernetesの細かい制御が要る場合はGKE、運用簡素化ならCloud Run。
はじめ方(概要)
-
アプリをコンテナ化してDockerfileを用意。
-
コンテナをContainer Registry/Artifact Registryへプッシュ。
-
gcloud run deployでリージョン・メモリ・CPU・同時接続などを指定し公開。
-
必要に応じて認証設定、環境変数、VPC接続、ドメインマッピングを設定。
必要なら、具体的なDockerfile例やデプロイ手順を示します。
重要なのはこれです。
Cloud Runは、Dockerなどのコンテナ化したアプリを、インフラ管理なしでデプロイ・自動スケール・課金まで面倒を見てくれるサービスです。HTTPリクエスト駆動で起動し、トラフィックに応じてゼロから高速にスケールします。
自動スケールしてくれるというところです。
今回リクエストがたくさん飛んでくるということで、CloudRunは立っているインスタンスの数をリクエストの耐えるために自動で増やしてくれます。
とても便利です。この子に大部分を支えてもらっているといっても過言ではありません。
ただ少し問題があり、それがスケーリングを前提にするなら基本的にステートレスにしなければならないということです。
元々2か月前のハッカソンで発表を行った際はこのあたりに気が回っておらず、HTTPとWebSocketサーバを同じサーバで処理を行っていました。
HTTPからのリクエストをカウントして一定数を超えたら同じサーバー内で接続されているWebSocketの接続を使ってUnityに命令を送るといった感じです。
ただもしサーバーが増えた場合、たくさん来るリクエストがある程度分新しく増えたサーバーにリクエストが回り処理されることになります。
そのときに、そのサーバーにWebSocket接続がなければUnityに送る方法がなくリクエストが死ぬことになります。
つまりスケーリングを前提とするならこのWebSocketとの接続という状態があるというのが問題点でした。
そこでCloudRunにするならここ切り分けないといけないよねという話になり、サーバー間の連携に使うことができるらしいPub/Subに手を出しこのような構成になりました。
おかげで沢山のリクエストが来てもしっかりと受け止め処理できるようになったという感じです。
まとめ
さて、本日はここまでとなります。
大体サーバー側の話はこれ以上することがないので明日は「同時接続300人に耐える技術!サーバー編!#2」とありますが、現状の構成の問題点とそれの解決のために考えていることなどがかけたらなと考えています。
また何か今回の内容で気になった部分があればコメントいただけると嬉しいです!
それではとても寒くなってきているので体調にお気をつけください!
