MENU

SQSで処理に失敗したらどうなるか、「戻る→再挑戦→DLQ」で整理した

SQSで処理に失敗したらどうなるか、「戻る→再挑戦→DLQ」で整理したことを説明する画像

おはようございます、YASUです。

DVAの模擬試験で、SQSの問題がどうにも苦手でした。標準とFIFOの違いは前に整理しましたが、「メッセージの処理に失敗したら、どうなるのか」が、整理できていなかったからだと気づきました。今日は、そこをシンプルにまとめます。

目次

結論

処理に失敗したメッセージは、すぐには消えず、可視性タイムアウトが過ぎるとキューに戻って、再び処理されます。何度か失敗すると、デッドレターキュー(DLQ)に移されます。この「戻る→再挑戦→DLQ」という流れを押さえると、SQSの問題が整理しやすくなりました。

失敗した時の流れ(LambdaでSQSを処理する場合)

1. LambdaがSQSからメッセージを受け取る(メッセージは他から見えなくなる)
2. 処理が成功したら、メッセージが削除される
3. 失敗(エラー、スロットリング、応答なし)したら、可視性タイムアウトのあとキューに戻る
4. 戻ったメッセージを、もう一度受け取って、処理する
5. 失敗が続いて、maxReceiveCountの回数に達すると、DLQに送られる

ポイント1:可視性タイムアウトは、関数のタイムアウトの6倍以上

前に整理した可視性タイムアウトは、受け取ったメッセージを、他から隠しておく時間でした。LambdaとSQSを組み合わせる場合は、ソースキューの可視性タイムアウトを、関数のタイムアウトの少なくとも6倍にするよう、AWSのドキュメントで案内されています。余分な時間があることで、Lambdaがスロットリングされた時にも、再試行できるためです。

ポイント2:バッチで失敗すると、全部戻る

LambdaはSQSのメッセージを、まとめて(バッチで)受け取ります。デフォルトでは、バッチの処理中にエラーが起きると、そのバッチの中のメッセージが、すべてキューに戻ります。成功していたメッセージまで、もう一度処理されることになります。

これを避けるのが、部分的なバッチレスポンスです。イベントソースマッピングで有効にしておくと、失敗したメッセージだけがキューに戻るようにできます。

ポイント3:DLQは、ソースキュー側に設定する

DLQは、何度処理しても失敗するメッセージの、退避場所です。設定は、ソースキューの再処理ポリシーで行い、そこでmaxReceiveCount(何回まで受け取りに失敗したらDLQに送るか)を決めます。AWSのドキュメントでは、maxReceiveCountを少なくとも5にするよう、推奨されています。回数が少なすぎると、一時的なスロットリングだけで、問題のないメッセージまでDLQに送られてしまうためです。

設定する場所は、Lambda関数側ではなく、ソースキュー側です。ここは、試験で取り違えやすいと感じました。

ポイント4:同じメッセージが、何度か処理されても大丈夫にする

失敗して戻ったメッセージは、もう一度処理されます。途中まで処理が進んでいた場合は、同じメッセージが、2回以上処理されることになります。そのため、関数の処理は、何度実行しても結果が変わらない(べき等にする)ことが、ベストプラクティスとされています。

SQSの数字の整理

  • 可視性タイムアウト:初期値は30秒、0秒〜12時間
  • メッセージの保持期間:最短1分、最長14日
  • 配信遅延(DelaySeconds):0〜900秒(15分)
  • メッセージのサイズ:最大256KB
  • ロングポーリングの待ち時間:1〜20秒

まとめ

  • 処理に失敗したメッセージは、可視性タイムアウトのあとキューに戻り、再度処理される
  • LambdaでSQSを処理する場合、可視性タイムアウトは、関数のタイムアウトの6倍以上にする
  • バッチで失敗すると全部戻るが、部分的なバッチレスポンスで、失敗したものだけを戻せる
  • DLQはソースキュー側に設定し、maxReceiveCountは5以上が推奨されている
  • 何度か処理されても大丈夫なよう、処理をべき等にしておく

「戻る→再挑戦→DLQ」という流れで整理すると、SQSの問題の見え方が変わりました。それでは、また明日!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次