ポーリング処理廃止によるイベント駆動アーキテクチャへの移行¶
チェック¶
- [ ] 本文を確認した
- [ ] 概要を確認した
- [ ] タグを確認した
- [ ]
inbox/直下へ移行した
概要¶
予約検索のクライアント polling を廃止し、Pub/Sub、イベント伝播サービス、Firestore の realtime sync、Cloud Tasks による throttling を組み合わせたイベント駆動構成へ移行した事例。 既存構成では 30 秒間隔 polling、1 回あたり 9 API call により、予約検索 API が約 2,000 req/sec になっていた。 移行後は対象 API の秒間 request が約 50% 減り、DB cost も約 30% 削減された。
本文¶
既存アーキテクチャでは、各 client が 30 秒間隔で polling していた。 1 回あたりの API call は 9 回。 予約検索 API で 2,000 req/sec 程度の負荷が発生し、高負荷、scalability への懸念、非効率な resource 利用が課題になっていた。
polling の本質的な問題は、データ変更があってもなくても定期的に request が発生すること。 変更があったときだけ server から client に通知できれば、無駄な request を減らせる。
server push の選択肢として、WebSocket、Server-Sent Events、gRPC Server Streaming が比較されている。 これらは realtime 性や双方向通信、型安全性などの利点がある一方、connection 管理が複雑で、Pod に connection が固定されるため scaling が難しい。 別 Pod に届いた event を、接続中 client を持つ Pod へ転送する仕組みが必要になる。
新アーキテクチャでは、予約サービスが event を発火し、Pub/Sub に message を配信する。 イベント伝播サービスが購読し、Firestore の薬局別 document を更新する。 frontend は自分に関係する薬局 document を監視し、変更を realtime に検知する。 変更検知後に予約取得 API から予約 data を取得する。
Firestore を選んだ理由は、realtime sync が標準装備で SDK だけで接続管理を任せられること、client 数増加に対して infra 側の対応が少ないこと、薬局ごとの document 分離で不要 data を受け取らないこと、既存の Google Cloud 環境との親和性。
短時間に大量 event が発生すると、client が都度 API を呼んでしまう。 これに対して Cloud Tasks を使った throttling を導入し、一定時間内の複数 event を 1 回の通知にまとめた。
要点¶
- Polling は変更有無に関係なく request が発生するため、負荷と DB cost が増えやすい。
- WebSocket / SSE / gRPC streaming は強力だが、connection 管理と scaling が難しい。
- Firestore realtime sync を notification channel として使う設計が有効だった。
- Cloud Tasks で event をまとめることで API request の集中を抑えた。
- 結果として API request は約 50%、DB cost は約 30% 削減。