【发布时间】:2017-04-05 02:18:10
【问题描述】:
我们将 SQS 队列用于异步消息,并且需要 Lambda 函数对某些队列上的消息进行一些转换和记录。 经过大量研究后,我决定我将使用递归 Lambda 函数,因为消息并不是很关键,并且在两者之间使用 SNS 或 SWF 似乎过于复杂(我希望亚马逊很快会为 SQS 添加一个 Lambda 触发器)。
Lambda 函数的每个请求的最大执行持续时间应该是 300 秒(5 分钟),所以我想反复调用 Lambda,然后将 Cloudwatch 触发器设置为 5 分钟以重新触发Lambda 再运行 5 分钟。
但是 Lambda 只是继续运行(没有 Cloudwatch 触发器)。我昨天测试了它,当它一直超过 300 秒时我感到很惊讶,现在它已经运行了超过 24 小时......
那么,问题是,它为什么一直在运行? 我假设每次调用它 Lambda 都认为它是一个新请求。由于 SQS 长轮询超时为 20 秒,而且我还在超时后调用(如果没有新消息),它会继续作为新请求进行,对吗?
另外,如果我每隔 5 分钟添加一次 Cloudwatch 触发器,我会启动同一个 Lambda 函数的多个实例吗?
(是的,我知道我是按运行时间计费的,但它仍然比 EC2 实例便宜,即使是 24/7 运行)
编辑: 添加显示调用和递归运行的 Cloudwatch 日志:
15:48:22 开始 RequestId:ee3f71df-b001-11e6-a0d6-bffc6057d58c 版本:$LATEST
15:48:42 2016-11-21T15:48:42.188Z ee3f71df-b001-11e6-a0d6-bffc6057d58c 再次调用……又一次……
15:48:42 END RequestId:ee3f71df-b001-11e6-a0d6-bffc6057d58c
15:48:42 报告请求 ID:ee3f71df-b001-11e6-a0d6-bffc6057d58c 持续时间:20115.93 毫秒计费持续时间:20200 毫秒内存大小:128 MB 使用的最大内存:37 MB
15:48:42 开始 RequestId:fa443a44-b001-11e6-bea9-4fe2d7bd8fe7 版本:$LATEST
15:49:02 2016-11-21T15:49:02.386Z fa443a44-b001-11e6-bea9-4fe2d7bd8fe7 一次又一次地打电话...
15:49:02 END RequestId: fa443a44-b001-11e6-bea9-4fe2d7bd8fe7
15:49:02 报告请求 ID:fa443a44-b001-11e6-bea9-4fe2d7bd8fe7 持续时间:20156.93 毫秒计费持续时间:20200 毫秒内存大小:128 MB 使用的最大内存:37 MB
15:49:02 开始 RequestId:0647caad-b002-11e6-adc9-73ebc92281fd 版本:$LATEST
15:49:22 2016-11-21T15:49:22.601Z 0647caad-b002-11e6-adc9-73ebc92281fd 一次又一次地打电话...
15:49:22 END RequestId:0647caad-b002-11e6-adc9-73ebc92281fd
15:49:22 报告请求 ID:0647caad-b002-11e6-adc9-73ebc92281fd 持续时间:20179.49 毫秒计费持续时间:20200 毫秒内存大小:128 MB 使用的最大内存:37 MB
【问题讨论】:
-
你说的递归是什么意思?您的 Lambda 函数是否调用了更多自身实例?听起来您有失控的递归,导致您的函数的许多实例正在运行。
-
是的,它正在调用自己。脚本完成的可能性有 3 种,消息处理成功、处理消息时出错或 SQS 轮询超时 20 秒。在这三个场景中的每一个中,Lambda 在“死亡”之前都会再次调用自己,因此它会在新的请求中重新调用自己,因此它应该同时只是一个实例。
-
如您所见,它为每个“START”获取一个新的 RequestId,因此它永远不会达到 300 秒,因为最大轮询超时仅为 20 秒。我只是想确认我的理论,这样我就不会并行处理多个 Lambda 函数......
-
如果它在每次完成时都调用自己的一个新实例,那么您将始终有一个函数实例在运行。我不知道你为什么对此感到惊讶。向此函数添加 CloudWatch 事件触发器将导致多个实例同时运行,因为您将让函数本身创建新调用以及 CloudWatch 创建新调用。
-
在这种情况下,调用 == 请求。每次调用都是一个新请求,它会创建一个具有新超时的全新 Lambda 函数实例。 (我有点简单化并且忽略了 Lambda 容器的重用,但这与这个问题并不真正相关)
标签: node.js amazon-web-services aws-lambda