社内で初めてAmazon SQSを導入した際に考慮した点
この記事はポート株式会社 サービス開発部 Advent Calendar 2024の13日目の記事です。
はじめに
SRE1年目のharaです。
業務でAmazon SQSを導入する機会があったのでその際に考慮したことを共有します。
今回初めて導入しましたので、間違っていることがありましたら教えていただけますと幸いです。
背景
導入に至った背景は下記になります。
- 社内では複数の新卒向けの就職支援サービスを運用しており、相互に連携している部分がある
- 今回、相互連携している部分で、片方のサービスが落ちていたので、連携データの欠損が発生してしまった
- チーム内でポストモーテムした結果、今回はサービス感の依存度が高いことが原因だったため、キューイングすることで解消しようという結論になった
弊社ではインフラ環境にAWSを使用しているため、今回はSQSを導入することになりました。
そもそもSQSとは?
SQSは一言で説明するとフルマネージド型のキューイングサービスです。
SQSにメッセージをキューイングすることで、ソフトウェアコンポーネント間でメッセージを送信・受信などすることができアプリケーションの信頼性とスケールの向上に役立ちます。
考慮した部分
キューの種類
SQSはキューが2種類存在します。
- Standard queues
- FIFO queues
それぞれの特徴は以下です。
- Standard queues
- 送信した順でメッセージがエンキューされる。ベストエフォートなので送信した順でエンキューされない可能性はある。
- 各メッセージの配信は最低1回配信される。リトライなどで重複して配信される可能性はある。
- FIFO queues
- 送信した順でメッセージがエンキューされる
- 各メッセージの配信は1回のみ
- コンテンツベースで重複排除することができる
Amazon SQS queue types - Amazon Simple Queue Service
今回はメッセージが重複してエンキューされることを防ぐ、かつ、メッセージの配信は1回のみにしたかったのでFIFO queuesを使用することにしました。
可視性タイムアウト
可視性タイムアウトとは?
可視性タイムアウトはコンシューマーが処理を実行している際に他のコンシューマからメッセージが参照されないようにするための設定です。これはAWS公式ドキュメントでは下記のように記載されています。
When you receive a message from an Amazon SQS queue, it remains in the queue but becomes temporarily invisible to other consumers. This invisibility is controlled by the visibility timeout, which prevents other consumers from processing the same message while you're working on it.
Amazon SQS visibility timeout - Amazon Simple Queue Service
また、下記記事によるとコンシューマがLambdaの場合の可視性タイムアウトはLambdaのtimeout * 6倍を設定した方がいいようです。今回はLambdaのtimeout時間は1分で設定していたので可視性タイムアウトは6分に設定しました。
To allow your function time to process each batch of records, set the source queue's visibility timeout to at least six times the timeout that you configure on your function.
Configuring an Amazon SQS queue to trigger an AWS Lambda function - Amazon Simple Queue Service
可視性タイムアウト < Lambdaのtimeout の場合はLambdaがSQSのメッセージを削除することができず、メッセージの保持期間が切れるまでずっとLambdaが実行され続ける事例がありました。
AWS Lambdaが何度も繰り返し実行され請求が1000倍になった話
また、メッセージ削除に関しては下記記事に記載がありました。コンシューマーがメッセージを受け取った場合に作成されるreceipt handleをメッセージ削除時に送信する必要があるのですが、receipt handleはメッセージ受信毎に発行される、かつ、可視性タイムアウトを過ぎたら有効期限が切れてしまうため、Lambdaが実行され続ける事象が発生するようです。
Troubleshoot Amazon SQS API errors - Amazon Simple Queue Service
メッセージ保持期間
メッセージ保持期間はデフォルトの4日間にしました。(これはもっと短くてもいいかも?)
メッセージ保持期間が短過ぎると、コンシューマーの処理中にメッセージが削除されてしまうことがあるのでその辺りは考慮する必要があります。
ジョブが指定回数以上受信された場合のハンドリング
弊社で使用しているSidekiqなどのキューイングサービスでは、Jobの実行が特定の回数を超えたらdead jobとして扱っています。
同様に、SQSでもメッセージが特定の回数以上受信された場合はDLQにメッセージを移動させる様にしました。これによってメッセージが呼ばれ続けることを防ぐ、かつ、処理できないメッセージを個別で対応することができます。
AWSでもDLQの作成を推奨していたので基本的にDLQを作成した方が良さそうです。
Amazon SQS visibility timeout - Amazon Simple Queue Service
また、DLQに移動した時に開発者が気付けないと保持期間が過ぎてメッセージが消えてしまうことがあると思うのでDLQにメッセージがエンキューされたら通知する様にしました。DLQのApproximateNumberOfMessagesVisible
のメトリクスを監視することで通知部分を作成することができました。
Amazon SNS dead-letter queues - Amazon Simple Notification Service
ちなみにFIFOキューの場合はDLQにメッセージが移動した際に、エンキュー時のタイムスタンプがリセットされる様でした。
Using dead-letter queues in Amazon SQS - Amazon Simple Queue Service
同時実行数
同時実行数はLambdaでも指定することはできますが今回はイベントソースマッピングの機能を使い同時実行数を指定しました。
今回はSQSにエンキューされるメッセージが毎日300~700件程だったので、同時実行数は50に設定しました。イベントソースマッピングの同時実行数 > Lambdaの同時実行数にするとLambdaがスロットリングを起こすのでLambdaの同時実行数も考慮した上で、イベントソースマッピングの同時実行数を決めると良さそうです。
また、FIFOキューは異なるメッセージグループIDに対して並行してLambdaインスタンスが立ち上がるので、メッセージをSQSにエンキューする時は注意する必要があります。
Amazon SQS FIFO キューと Lambda 同時実行動作 - Amazon Simple Queue Service
まとめ
今回初めてSQSを触る、かつ、まだ弊社ではSQSを導入した事例がなくかなり苦戦しました。今後同じように初めてSQSを導入する方の参考になれば幸いです!
Discussion