Pub/Subを使った非同期処理
株式会社enechain / 遠藤雅彰
テックリード / バックエンドエンジニア
利用機能 | 事業形態 |
---|---|
メッセージング | B to B |
利用機能 | メッセージング |
---|---|
事業形態 | B to B |
アーキテクチャ
.png?disposition=inline)
アーキテクチャの意図・工夫
Pub/Subを活用する際の重要な設計ポイントのひとつが「冪等性の担保」です。Pub/Subではメッセージの重複が発生する可能性があるため、この性質を考慮した設計が必要となります。
例えば、ユーザーデータの更新を伝搬する際、変更点そのものをメッセージに含めて反映させる方法ではなく、「このユーザーに変更があった」という情報のみをメッセージに含め、APIを通じて最新のデータを取得し、それを元に処理を行う設計にすることが効果的です。こうすることで、更新順序やタイミングに依存しない仕組みを構築できます。
導入の背景・解決したかった問題
導入背景
ツール導入前の課題
enechainではmicroservicesアーキテクチャを導入しています。 microserviceとプロダクトアプリケーションが直接API連携を行っている場合にAPIリクエストがエラーとなると、両方のシステムの状態に齟齬が発生する可能性があります。 この齟齬を解消するために、運用によるリカバリ処理などが必要なことが課題となっていました。
どのような状態を目指していたか
一時的なエラーの場合にはシステム的に自動でリカバリされる状態を目指していました。 リカバリ時に手動の対応が必要になると運用コストが高いため、人が介在しなくても良い運用を目標にしていました。
比較検討したサービス
- Cloud Tasks
比較した軸
- マネージドなサービスであること
- サービス同士を疎結合な作りにできること
- 流量制限ができること
選定理由
今回、Pub/Subを採用した理由は、Cloud Tasksと比較して以下の点が要件により適合していたためです。
ファンアウトに対応している :一つのトピックから複数のサブスクライバーがメッセージを受信できるため、効率的に全プロダクトにメッセージが配信できます。
Pull型に対応している:サブスクライバーが必要なタイミングでメッセージを取得するPull型を使用することで、HTTPのエンドポイントを公開しているサービス以外でもメッセージを受け取ることができます。HTTP経由でのオートスケールを有効活用したPush型を扱いたい場合にはPush型で問題ありませんが、今回のケースではリアルタイム性よりもエンドポイントへの負荷をかけたくなかったのと、順列制御を行いたいためこちらが一つの決め手になりました。
Cloud Tasksでもこれらの要件を満たすことは可能ですが自前の実装を行わないといけません。 今回の要件においてはファンアウトの機能が欲しかったため、Pub/Subが最適な選択肢であると判断しました。
導入の成果
改善したかった課題はどれくらい解決されたか
システムとして疎結合なものにできて、サブスクライブするサービスが一時的にAPIに繋がらないような状態になってもパブリッシャー側はその影響を受けないようにすることができました。
どのような成果が得られたか
一時的なエラーが発生してもリトライで復旧できて、サービス間の連携が完全に疎結合化できました。サービスの停止を行った時にお互いの状態を気にしなくて良くなるという効果を得ています。
導入時の苦労・悩み
2021年3月にメッセージスキーマがリリースされるまではメッセージの型がフリーフォーマットであったことによりデータ整合性を保つことがコード依存になってしまい、データ構造を変更するにはパブリッシャーとサブスクライバーでコードの変更を同時に行わなければいけませんでした。
メッセージスキーマの登場により送信されるメッセージのバリデーションが可能になったことでメッセージの構造が保証された状態で受け取れるようになりました。我々はPub/Sub導入時にメッセージスキーマを利用しなかったことで構造が暗黙知になってしまい苦労しました。メッセージスキーマを最初から導入しておけば、各チームへの展開が楽になったと思います。
導入に向けた社内への説明
上長・チームへの説明
具体的なユースケースとして、ユーザの初期化をAPIで行い、失敗した場合にどのようなリカバリになるのかをmiroを使って説明しました、Pub/Subを使った方がシステム的にシンプルになるということを説明しました。
活用方法
よく使う機能
トピックとサブスクリプション:パブリッシャーがメッセージを送信する「トピック」と、トピックからメッセージを受信する「サブスクリプション」を通じて、効率的なメッセージ配信を行います。
Pull型の配信:サブスクライバーが必要に応じてメッセージを取得する配信方式です。
BigQuery連携:データをリアルタイムに近い速度でBigQueryに取り込みます。
ツールの良い点
- エラー時に自動的に再送を行ってくれる
- リトライ間隔の調整ができる
- Push型とPull型が選択できる
- 1つのトピックに発行されたメッセージを複数のサブスクライバーで受け取ることができる
- 一定の回数再送信が失敗したメッセージの宛先がデッドレタートピックに保存することができる
ツールの課題点
- サブスクライブして10分間経ったら自動リトライされてしまう
- メッセージの重複が起きてしまう可能性がある
- Pull型の場合にも10分以上処理に時間がかかってしまうとメッセージの再送による二重実行が起きてしまう可能性がある
- リージョン毎に同時接続数とスループットの上限がある
ツールを検討されている方へ
Pub/Subは疎結合なイベントドリブン型のシステムを構築するための非常に優れたツールです。しかし、その特性を十分に理解した上で、導入が最適かどうかを検討することが重要です。例えば、Ack/Nack(確認応答)のレスポンスに最大で10分の遅延が発生する可能性があることや、メッセージの重複が起こる点は考慮する必要があります。
そのため、長時間にわたる複雑な処理を要する場合には、Pub/Sub以外のツールを選択したほうが効率的な場合があります。一方で、短時間で終了する処理や非同期通信が求められる場面では、Pub/Subは有力な選択肢となります。
また、膨大なログ収集を行うなど大量のメッセージを送信するシステムを構築する場合には最適解ではないことがあるため、Pub/Sub以外のメッセージングサービスも検討する価値があります。
株式会社enechain / 遠藤雅彰
テックリード / バックエンドエンジニア
株式会社enechain / 遠藤雅彰
テックリード / バックエンドエンジニア
レビューしているツール
目次
- アーキテクチャ
- 導入の背景・解決したかった問題
- 活用方法