こんにちは!今日は,リアルタイムのマッチングアプリを Cloud Run で動かすときの注意点についてお話しさせていただこうと思います.
前提条件
この前提条件のままでCloud Runにデプロイすると何が起きるか
マッチングしているのに,その情報が API から伝わってこなかったりします.
下の図で説明してきます.
この図を見ると,API が二つに増えたことが確認できると思います.Cloud Run はインスタンス(APIサーバー的なやつ)数が自動スケーリングされます.そのため,API が複数で動いている場合があります.これが原因で,マッチングしているのに,その情報が API から伝わってこなかったりします.フローを追いながら説明してきます.
- API1は,rdb をポーリングしてマッチングしてるか確認します.
- マッチングしているので,rdbからデータを削除します.そして,API1とwebSocketコネクションで繋がっているuser1に伝えます.このとき,user2とは,webSocketコネクションで繋がっていないため伝えられません.
- API2は,rdb をポーリングしてマッチングしてるか確認します.この時すでにマッチングした情報はAPI1により削除されているため,API2はマッチングしていないと認識します.
- そのため,API2とwebSocketコネクションで繋がっているuser2には,マッチングしたという情報が伝わりません.
解決方法
これを解決する一つの方法が,redis の pub/sub を使う やり方です.redis の pub/sub は,あるチャンネルにメッセージをpublishしたら,チャンネルを監視しているsubscriberに届くというものです.以下の図で説明します.

まず,API1,API2は redis のチャンネルを subscribe するようにしておきます.
- API1は,rdb をポーリングしてマッチングしてるか確認します.
- API1は,マッチングを確認したので rdbからデータを削除します.そして,redisのチャンネルにマッチングしたuserIDをpublish します.
- API1は,webSocketコネクションで繋がっているuser1に伝えます.このとき,user2とは,webSocketコネクションで繋がっていないため伝えられません.
- redis のチャンネルを subscribe している API2のもとに,マッチングしたuserIDの情報が届きます.
- API2は,webSocketコネクションで繋がっているuser2に マッチングしたという情報を伝えます.
このように行うことで,複数APIサーバーが動いている状態でも,マッチングを実現できます.
まとめ
実はこの問題は以前AWS にデプロイするときに起きていた問題だったのですが,まさか Cloud Run でも同じ現象が起きているとは思わず原因を探るのに苦労しました..
複数リアルタイムのマッチングアプリを Cloud Run で動かすときに参考にしていただければ幸いです.

