[2021-07-10追記]
本記事はSQS標準キューについての記述である。
SQS FIFOキューの場合は、Lambdaの最大並列実行数はMessage Groupの数となる。
Total concurrency is equal to or less than the number of unique MessageGroupIds in the SQS FIFO queue.
https://aws.amazon.com/jp/blogs/compute/new-for-aws-lambda-sqs-fifo-as-an-event-source/
[2021-07-22追記]
SQS FIFOキューはexactly onceの配信を保証しているが、Lambda関数は2回以上起動されても問題ないことが求められる。
However, it does not guarantee only once delivery when used as a Lambda trigger. If only once delivery is important in your serverless application, it’s recommended to make your function idempotent.
https://aws.amazon.com/jp/blogs/compute/new-for-aws-lambda-sqs-fifo-as-an-event-source/
[2024-05-02追記]
アップデートにより、イベントソースマッピングで最大同時実行数(max concurrency)を設定できるようになった。これならスロットリングが発生せず扱いやすい。しかしなぜか設定可能な値は2〜1000となっており、1には設定できない。いつもながらAWSは痒いところに手が届かず手間ばかりかかって使いづらい。
https://www.skyarch.net/blog/lambda%E6%96%B0%E6%A9%9F%E8%83%BD-amazon-sqs%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%AB%E3%82%88%E3%82%8B%E5%90%8C%E6%99%82%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%97%E3%81%AE/
LambdaのトリガーとしてSQSを指定できるのでやってみた。
実験してみた結果
- キューにメッセージが入るとほぼ瞬時にLambdaが実行される
- Lambda 関数を同期的に呼び出します
- Lambdaが実行されると、メッセージは自動的にキューから削除される。自分で削除する必要はない。
- メッセージのbodyはLambdaのeventに入ってくるので、自分でReceiveMessageする必要がない。
- エラーが起きた場合
- デッドレターキューが無い場合は、メッセージの保持期限が切れるまでリトライされる
- リトライ回数はAmazon SQS がメッセージを保持する秒数(MessageRetentionPeriod)で決まる
- リトライ間隔は可視性タイムアウト(
VisibilityTimeout
)で決まる
- デッドレターキューがある場合は、自分で決めた最大受信回数だけリトライされ、その後デッドレターキューに入る
- 可視性タイムアウトを5分、最大受信回数を1回にした場合、Lambdaが1回呼び出された後5分経過してからデッドレターキューに入った
- デッドレターキューが無い場合は、メッセージの保持期限が切れるまでリトライされる
- Lambda関数に同時実行数が設定してある場合は、ちゃんとその数を保ったまま、すべてのメッセージが順次処理される
- 同時実行数を制限しつつ、適度なリトライ回数を設定するのが難しい
- 同時実行数はちゃんと設定できるのだが、それにひっかかった場合すぐにリトライが行われ、キューの「最大受信数」(1つのメッセージを何回リトライ受信することを許すか)にひっかかってすぐにデッドレターキューに入ってしまうらしい
- 可視性タイムアウトは30秒にしていたが、30秒も待たずにすぐリトライが行われていた
- 結論として、LambdaのトリガーとしてSQSを指定するのは、Lambdaの同時実行数を気にする場合は使いづらいと思った
- 基本的にSQSの標準キューは順番も保証せず、1つのメッセージが2回以上配信されることもあるのでLambda関数には冪等性が必要になる
- https://docs.aws.amazon.com/ja_jp/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html
- FIFOキューなら順番も保証され、1つのメッセージが配信されるのはちょうど1回であることが保証される
- [2021-01-15追記]可視性タイムアウトを0秒、Lambdaで3秒かかるように設定したら1つのメッセージが2回以上配信されるかと思ったが、予想と異なり1回しか配信されなかった。
- (通常、可視性タイムアウトは、アプリケーションがキューのメッセージを処理して削除するまでの最大所要時間に設定します。)
参考
キューから読み取るイベントソースマッピングについては、ソースキューの再試行ポリシーおよび可視性タイムアウトを設定することで、失敗したイベントの送信先と再試行の間の時間の長さを決定します。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/retries-on-errors.html