【发布时间】:2021-02-16 21:30:38
【问题描述】:
我在 lambda 中设置了一个 sqs 触发器
batch size : 3
batch window : 300 seconds
concurrency: 1
SQS 队列设置为
visiblity timeout: 3 minutes
这里的想法是一次处理 3 个文件。
这就是 lambda 代码的样子
def lambda_handler(event, context):
maximum_jobs = 3
sqs_client = boto3.client(
'sqs'
)
for i in range(len(event["Records"])):
msg_string = event["Records"][i]["body"]
if get_active_executions() < maximum_jobs:
start_execution()
receipt_handle = event["Records"][i]["receiptHandle"]
delete_sqs_message(sqs_client, "myqueue", receipt_handle)
else:
print(f"Already {maximum_jobs} jobs running")
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}
为了测试成功场景,我将 6 个条目推入队列。
- 立即处理前 3 条消息,并从队列中删除前 3 条消息。
- 其他 3 个在飞行模式下等待(因为我已将并发设置为 1,批量设置为 3)
- 可见性超时 3 分钟后,剩余 3 条消息返回队列,触发器拾取剩余 3 个文件。剩下的 3 个也被删除了。
- 所有 6 个文件均已成功处理。
现在,我用 9 个文件测试了相同的代码
- 立即处理前 3 个(例如 file1、file2、file3)
- 第二批(3 分钟后)被触发(比如 file4、file5、file6)。然而当时,第一批正在运行。我可以看到日志 - “已经有 3 个作业正在运行”。因此,它没有得到进程。根据代码,我也没有删除它。
- 现在,第三批已触发(例如 file7、file8、file9)。此时,第一批执行已经结束,因此所有 3 个都已成功处理并从队列中删除。
我期待在 3 分钟内再次触发批处理(文件 4、文件 5、文件 6)。然而,这并没有发生。我注意到队列是空的。
如果事件被触发并且没有手动删除,消息是否会从队列中消失?预期的行为是什么。我在代码中遗漏了什么吗?
【问题讨论】:
-
start_execution()发生了什么?您是否在 Lambda 函数之外触发了另一个任务?如果是这样,你需要等待吗?听起来有点像getActiveExecutions()正在检查某个外部任务是否正在运行,并且此任务花费的时间比预期的要长,因此您看到此Already 3 jobs running是因为您没有等待第一批任务完成。 -
另一个问题:如果 SQS 使用一条或多条消息触发您的 Lambda,并且您的 Lambda 函数没有抛出错误,SQS 将自动从队列中删除消息。 IE。您无需在代码中删除它们,它会自动完成。另请参阅:docs.aws.amazon.com/lambda/latest/dg/with-sqs.html:
When your function successfully processes a batch, Lambda deletes its messages from the queue -
哦!!。第二批没有抛出错误。因此消息被 lambda 从队列中删除。我应该如何处理这种情况?我希望他们回到队列中。我是否需要重新插入或在 lambda 中抛出错误,以便它不会从队列中删除。
-
不确定您的用例和处理顺序的效果,但在这里抛出异常很好,但可能并不理想,因为您会重复抛出异常,直到您的任务完成 -> 不必要的成本我的意见。也许你找到了更好的方法?
标签: amazon-web-services aws-lambda amazon-sqs