背景
SQSとLambdaの設定項目に再試行の設定値が存在せず、どういう仕組みで再試行しているのかが気になり今回検証を実施する。
検証
対象のSQS⇒Lambdaの構成のSQSにメッセージをコンソール上から流してみます。
流すメッセージはLambddaが期待した内容ではないため例外が発生するメッセージとなります。
SQSの設定とメッセージを流した際のLambda起動時のメッセージの内容です。
■ CloudWatch Logsの起動メッセージ1個目
{
"Records": [
{
"messageId": "c7c5c3f6-e6d1-4d68-81aa-748d97b1d256",
"receiptHandle":"",
"body": "a",
"attributes": {
"ApproximateReceiveCount": "1",
"SentTimestamp": "",
"SenderId": "",
"ApproximateFirstReceiveTimestamp": ""
},
"messageAttributes": {},
"md5OfBody": "",
"eventSource": "aws:sqs",
"eventSourceARN": "",
"awsRegion": ""
}
]
}
■ CloudWatch Logsの起動メッセージ2個目
{
"Records": [
{
"messageId": "",
"receiptHandle": "",
"body": "a",
"attributes": {
"ApproximateReceiveCount": "2",
"SentTimestamp": "",
"SenderId": "",
"ApproximateFirstReceiveTimestamp": ""
},
"messageAttributes": {},
"md5OfBody": "",
"eventSource": "aws:sqs",
"eventSourceARN": "",
"awsRegion": ""
}
]
}
起動メッセージからApproximateReceiveCountが再試行するごとにカウントアップされています。
また、今回の実行数が2回ということから、下記のようなサイクルになっていると思われます。
初回起動 ➡ Lambda失敗 ➡ 可視性タイムアウト(30秒経過) ➡ Lambda起動(2回目) ➡ Lambda失敗 ➡ 可視性タイムアウト(30秒経過) ➡ メッセージ削除(保存期間1分経過のため)
実際、保存期間を2分に変更したら、4回実行されるようになりました。
また、可視性タイムアウトを1分にし、保存期間を2分にするとLambdaの実行すうは2回となりました。
検証結果
SQS → Lambda の再試行は、SQS 側の制御によって行われることが分かりました。具体的には、Lambda 関数がエラーを返すと、メッセージは削除されずに 可視性タイムアウト(Visibility Timeout) が発生し、その後に再び Lambda に配信されます。
この再試行は、SQS の 保存期間(Retention Period) を過ぎるか、DLQ を設定していた場合は最大受信回数(maxReceiveCount)を超えるまで 継続されます。
したがって、Lambda の再試行回数は直接設定できませんが、以下の項目で間接的に制御できます:
- 可視性タイムアウト(Visibility Timeout)
- 保存期間(Message Retention Period)
- 最大受信回数(maxReceiveCount)と DLQ の設定
これにより、SQS における再試行の回数・タイミングはある程度コントロール可能です。
