Cloud Pub/Subで考慮したこと
この記事は、Magic Moment Advent Calendar 2023 14日目の記事です。
Magic Moment の@kntowdです。
先日とある非同期処理を含む機能を、Cloud Pub/Subを利用して開発することになりました。Cloud Pub/Subについて調べる前の私は、TopicとSubscriptionを作成すれば良いと思っていたのですが、調べてみると考慮しなくてはいけないことが多くあることに気づきました。紆余曲折があり結局Cloud Pub/Subを使わなくなってしまったのですが、頑張って調べた内容が日の目を浴びないのは悲しいので、本記事では個人的に重要だと思ったトピックをいくつか紹介したいと思います。Cloud Pub/Subの構成コンポーネントやメッセージのライフサイクルなどはこちらのドキュメントをご確認ください。
Cloud Pub/Subを使って実現したかったこと
Cloud Pub/Subを使って実現したかったことはざっくりと以下のような機能です。Subscriberでの処理に数分の時間がかかる想定だったので、ユーザを待たせないようにCloud Pub/Subを利用して、時間のかかる処理を非同期で行なっています。また、考慮ポイントとして非同期の処理にはメール送信処理が含まれているので、1つのメッセージに対して複数回Subscriberの処理が実行されないように注意する必要がありました。
記事で紹介する内容
今回の記事では以下のトピックについて説明していきます
- messageをPullするAPI
- At least once
- 流量制御
messageをPullするAPI
SubscriberがメッセージをPullするためのAPIには、Pull APIとStreaming Pull APIの2つがあります。Pull APIは定期的にPub/Subサービスにリクエストを送ってメッセージを取得します。
Streaming Pull APIはgRPCのストリーミング接続を使用して、リアルタイムでメッセージを受信しているので、Pull APIよりも遅延が少なくメッセージの受信ができます。
今回のユースケースでは、なるべく遅延なく処理の完了をユーザに通知したかったので、streaming pullを採用するのが良いかと思いました。
At least once
Cloud Pub/Subはat-least-once(最低でも1回)なメッセージの配信で、全てのメッセージは最低でも1回配送されます。つまり、1つのメッセージの配信が複数回行われてしまう可能性があります。今回のSubscriberの処理にはメール送信をする処理が含まれているので絶対に重複して処理が実行されないようにする必要がありました。
Subscriberでexactly-once(一度限り)のオプションを有効にすることで、クラウドリージョン内でメッセージを1回限りの配信にできます。2022年12月よりGAになったオプションになります。(いつも助けてくれるエンジニアのMiyakeさんがオプションの存在を教えてくれました!)
ただ、exactly-onceの設定を有効にすれば絶対にメッセージの再配信が行われないというわけではなく、確認応答期限が切れるとメッセージが再配信されてしまうので、Subscriber側の処理に合わせて適切な確認応答期限を設定する必要があります。また、PushのSubscriptionにはexactly-onceな配信が対応していない点にも注意が必要です。
流量制御
今回のユースケースでは一度のメッセージでそれなりに負荷のかかる処理を行うので、Subscriberが過負荷にならないように同時に処理するメッセージ数に制限をかける必要がありました。
Streaming Pull APIのオプションであるmaxOutstandingMessagesの値を設定することによって同時に処理するメッセージ数を制限できます。確認応答または否定応答されていないメッセージがmaxOutstandingMessagesで設定した数以上ある場合、Cloud Pub/Subはそれ以上のメッセージの送信を停止するような挙動になります。設定値を0以下にした場合は、メッセージ数に制限がなくなります。
Subscriberの負荷や許容されるレイテンシーを加味して設定値を決める必要があります。APIに対するリクエスト数は日々変化するので、継続的な監視と設定値の調整が必要です。
まとめ
Cloud Pub/Subについて調べてみると色々と気をつけないといけない部分が多く、入念に調べて使わないとバグに繋がりかねないという印象を受けました。また、今後Cloud Pub/Subを利用した機能をリリースした後には、Subscriberのパフォーマンス、メッセージの滞留数や滞留時間を見てCloud Pub/Subの設定値を変えるなどの対応が必要になってくると感じました。
今回の記事ではCloud Pub/Subで非同期処理を実現するにあたり考慮すべき点をいくつか挙げてみました。少しでもどなたかの参考になれば幸いです!
明日のアドベントカレンダーは Otsukaさんのgoroutine leakを解消したい!です。お楽しみに!!
最後に
弊社 Magic Moment では、フロントエンド・バックエンドにかかわらず全方位的にエンジニアを募集中です! Magic Moment に少しでも興味を持っていただけたら是非エントリーください!
Discussion