我有一个 aws lambda 函数。它将使用 SQS 触发。 lambda 时间为 15 分钟,SQS 队列可见时间为 16 分钟。当 lambda 即将超时时,我将在同一个队列中放入一个延续键并结束 lambda 的当前实例。 lambda 的新实例将使用 SQS 消息从它停止的位置开始。一切都工作正常,直到 lambda 第 16 次向 SQS 发送消息(执行)。
SQS 队列显示消息正在传输中,但 lambda 没有接收消息。 10 次重试后,消息将被推送到 DLQ。此外,不存在并发问题。我的 lambda 在执行 15 次后没有选择 SQS 消息的原因是什么?
我使用 lambda 和 SQS 已有 4 年多了,但从未遇到过这样的事情。不知道我错过了什么。
编辑: SQS 中的消息保留时间为 4 天。 您可以执行以下操作来重现此问题。创建一个名为 test-sqs 的 sqs,可见性时间为 30 秒,并将其作为触发器添加到新的 lambda(lambda 超时为 20 秒)。同时添加一个dlq到sqs队列中。以下是 lambda 代码。
import json
import boto3
import time
from datetime import datetime
sqsClient = boto3.client('sqs')
SQS_URL = "https://sqs.ap-south-1.amazonaws.com/YOUR_ACCOUNT_NUMBER/test-sqs"
def lambda_handler(event, context):
if ("Records" in event) and (len(event["Records"]) > 0):
print("Trigger through SQS.")
for record in event["Records"]:
event = json.loads(record["body"])
else:
print("Triggered manually.")
print(event)
start_time = datetime.utcnow()
print("start", start_time)
time.sleep(1)
segment_number = 1
if "segment_number" in event:
segment_number = event["segment_number"]
if segment_number <= 20:
segment_number += 1
payload = {
"segment_number" : segment_number
}
sqsClient.send_message(QueueUrl = SQS_URL, MessageBody=json.dumps(payload))
else:
print("COMPLETED")
print("end", datetime.utcnow())
SQS和Lambda具有递归检测机制。如果它识别出消息正在进入无限循环,那么它会停止执行。截至目前,该案已于第16次处决时停止。这就是您的 Lambda 仅运行 15 次的原因。
当失败时,它将超出其最大接收计数并将消息添加到DLQ。它发出
RecursiveInvocationsDropped
Cloudwatch 指标。
有关更多信息,请参阅此处的文章:https://aws.amazon.com/blogs/compute/detecting-and-stopping-recursive-loops-in-aws-lambda-functions/
它解释: