aws lambda函数为单个事件多次触发
Posted
技术标签:
【中文标题】aws lambda函数为单个事件多次触发【英文标题】:aws lambda function triggering multiple times for a single event 【发布时间】:2015-11-10 21:30:02 【问题描述】:我正在使用 aws lambda 函数将存储桶中上传的 wav 文件转换为 mp3 格式,然后将文件移动到另一个存储桶。它工作正常。但是触发有问题。当我上传小 wav 文件时,lambda 函数被调用一次。但是当我上传一个大尺寸的wav文件时,这个功能会被多次触发。
我google了这个问题,发现它是无状态的,所以会被多次调用(不确定这个触发器是多次上传还是同一次上传)。
https://aws.amazon.com/lambda/faqs/
有没有什么方法可以为单次上传调用一次该函数?
【问题讨论】:
“不确定这个触发器是用于多次上传还是同一次上传” ...看起来这不应该是你应该首先解决的问题吗?无国籍与它无关。检查实际的事件内容,创建您在 S3 事件中接收到的内容的日志并将其存储以供查看,并且解释应该变得显而易见。最有可能的是,您最初用于上传对象的行为所执行的 S3 操作比您意识到的要多。 您需要用更具体的信息来扩展这个问题。理想情况下是代码示例。 听起来上传被分成几部分。您需要创建一个事件,指定该事件仅在s3:ObjectCreated:CompleteMultiPartUpload
上执行,this tutorial 显示了如何做到这一点,只需将 s3:ObjectCreated:*
替换为 s3:ObjectCreated:CompleteMultiPartUpload
。
【参考方案1】:
短版: 尝试在 lambda 函数配置中增加超时设置。
加长版:
我猜你在这里遇到了正在超时的 lambda 函数。
S3 事件本质上是异步的,侦听 S3 事件的 lambda 函数在该事件被拒绝之前至少重试 3 次。您提到您的 lambda 函数在您进行转换和重新上传的较小大小的上传期间仅执行一次(没有错误)。从您的代码转换和重新上传所需的时间有可能大于您的 lambda 函数的超时设置。
因此,您可能想尝试在 lambda 函数配置中增加超时设置。
顺便说一句,确认您的 lambda 函数被多次调用的一种方法是查看 cloudwatch 日志中的事件 id (67fe6073-e19c-11e5-1111-6bqw43hkbea3) 发生 -
START RequestId: 67jh48x4-abcd-11e5-1111-6bqw43hkbea3 Version: $LATEST
此事件 ID 表示为其调用 lambda 的特定事件,并且对于负责同一 S3 事件的所有 lambda 执行应该相同。
此外,您可以在以下日志行中查找执行时间(持续时间),该日志行标志着一次 lambda 执行结束 -
REPORT RequestId: 67jh48x4-abcd-11e5-1111-6bqw43hkbea3 Duration: 244.10 ms Billed Duration: 300 ms Memory Size: 128 MB Max Memory Used: 20 MB
如果不是一个解决方案,它至少会给你一些空间,让你在正确的方向上进行调试。告诉我进展如何。
【讨论】:
+1 不特定于 S3,对我来说,这也发生在 CloudWatch Lambda 触发器上。除了增加超时之外,是否有其他选项可以防止这种情况发生。 我的每次发射 3 次。它从 dynamoDB 读取并存储在另一个表中。每次 3 个不同的请求 ID 我认为这里的答案表明它并不总是超时:***.com/questions/57286268/… & aws-labs 最近添加了一些开源工具来标准化处理多次执行的问题:awslabs.github.io/aws-lambda-powertools-python/api/utilities/… 【参考方案2】:context
对象包含有关您当前正在处理的请求 ID 的信息。即使同一事件多次触发,此 ID 也不会更改。您可以在每次触发事件时保存此 ID,然后检查您处理的最后一个 ID 是否与当前 ID 不同。
这是我解决此问题的最终代码(带有 MongooseJS 数据库处理程序的 NodeJS):
exports.handler = function(event, context, lambdaCallback)
Events.findOneAndUpdate(
name: 'some-event-name' ,
lastRequestId: context.awsRequestId ).then(function(event)
if(event.lastRequestId == context.awsRequestId)
return;
/* Run the actual job */
...
);
希望这会有所帮助!
【讨论】:
感谢@maxpaj,如果python处理程序有任何类似的选项,请告诉我们。我正在从 lamda 函数请求 .post 到我的应用程序端点。如果响应状态代码需要超过 3 秒。它正在重新使用它,添加提取功能触发器。 我对这个实现有一些问题。我有一次调用 lambda 函数的云监视事件,并注意到它会随机多次运行该函数,但每个函数都有一个与之关联的不同 requestId。 你能检查你的函数是否超时? @skrusetvt @neo73 我检查了我的 CloudWatch 日志,没有抛出任何错误。但是,我确实将超时时间从 15 秒增加到 3 分钟,而且我再也没有看到这种行为了。【参考方案3】:多次执行 Lambda 的任何事件都是由于 AWS document 中指定的 Lambda 重试行为。
您的代码可能会引发异常、超时或内存不足。执行代码的运行时可能会遇到错误并停止。您可能会耗尽并发性并受到限制。
Lambda 中可能存在一些错误,导致调用 Lambda 函数的客户端或服务重试。
使用 CloudWatch 日志查找错误并解决它可以解决问题。
我也遇到了同样的问题,在我的情况下是因为应用程序错误,解决它对我有帮助。
最近 AWS Lambda 有新的属性来改变默认的重试性质。在异步调用设置下将重试次数设置为 0(默认为 2)。
【讨论】:
就我而言,绝对没有错误,我的超时时间是 10 分钟,这远远超过了我的需要。您认为使用finally
可能会导致这种行为吗?
解决应用程序错误通常被认为是一种好的做法。
我的问题是这种情况的一个特殊实例:我从处理程序返回的结果(所以我在函数中做的最后一件事)不可序列化导致异常,因此事件需要重试。 CloudWatch 日志是您的朋友。【参考方案4】:
在 Lambda 配置中查找“异步调用”有一个选项“重试尝试”,它是函数返回错误时重试的最大次数。
这里还可以配置死信队列服务
【讨论】:
我试过这个并设置为 0,但我的 lambda 仍然重试。以上是关于aws lambda函数为单个事件多次触发的主要内容,如果未能解决你的问题,请参考以下文章
AWS Cloudwatch/Lambda - 计划事件触发太频繁
如何从外部 SQS 队列活动触发 AWS Lambda 函数
如何使用AWS Lambda和SNS事件触发Spring Cloud功能的重试