【问题标题】:SQS batching for Lambda trigger doesn't work as expectedLambda 触发器的 SQS 批处理无法按预期工作
【发布时间】:2021-05-29 12:31:30
【问题描述】:

我有 2 个 Lambda 函数和一个 SQS 队列。 第一个 Lambda 将消息发送到队列。 然后第二个 Lambda 对此队列有一个触发器,批处理大小为 250,批处理窗口为 65 秒。

我预计大约每 65 秒后会以 250 条消息的形式触发第二个 Lambda。在第二个 Lambda 中,我调用了限制为每分钟 250 个 API 调用的第 3 方 API(我每分钟获得 250 个令牌)。

我测试了这个设置,将 32.000 条消息添加到队列中,而第二个 Lambda 没有按预期批量接收消息。起初它执行了 15k 条消息,然后没有足够的令牌,所以它没有处理这些消息。

第 3 方 API 基于令牌桶,每分钟填充率为 250,最大容量为 15.000。由于存储桶的容量,它设法处理了前 15.000 条消息,然后没有足够的容量来处理其余的。

我不明白出了什么问题。

【问题讨论】:

  • 我是否理解正确,在您将 32k 条消息添加到 SQS 队列后,您的 Lambda 函数使用 15k 条消息(一批?)而不是 250 条执行? 存储桶的总容量是多少?是每小时还是您可以使用的总代币数量?
  • 澄清一下:15k 条消息并没有在一次 Lambda 调用中处理,对吧?它应该是 60 左右,根据文档,标准 SQS 的最大批量大小为 10k。
  • 您检查过您的 Concurrent executionsInvocations 的 lambda 指标了吗?
  • @Marcin 调用是41,并发执行是143
  • 是的,所以我认为这证实了@Maurice 的回答。您的函数并行运行,而不是顺序运行。

标签: amazon-web-services aws-lambda amazon-sqs


【解决方案1】:

误解可能与 Lambda 处理扩展的方式有关。 每当有超过单个 Lambda 执行上下文/实例可以处理的事件时,Lambda 只会创建更多执行上下文/实例来处理这些事件。

可能发生的情况是 Lambda 看到队列中有一堆消息,它会尝试尽快处理这些消息。它创建了一个 Lambda 实例来处理第一个事件,然后与 SQS 交谈并要求做更多的工作。当它收到下一批消息时,第一个实例仍然很忙,因此它横向扩展并创建了第二个实例,并行处理第二批,依此类推。

这就是你最终在几分钟内完成代币预算的方式。

您可以通过使用预留并发来限制允许 Lambda 并行执行的函数数量 - 这里是 docs 以供参考。如果您将预留并发设置为 1,则不会进行并行化,并且只允许一个 Lambda 处理消息。

然而,这会让您面临另一个问题。如果单个 Lambda 处理消息的时间少于 60 秒,Lambda 将尽快再次调用另一个批次,您可能会再次超出预算。

此时,一个相对简单的方法是确保您的 lambda 函数始终需要大约 60 秒,方法是在最后添加剩余时间的睡眠。

【讨论】:

  • 嗨。只是想知道有什么比睡 60 秒更好的吗?您最终将为此空闲时间付费。也许有办法避免它?
  • “如果单个 Lambda 处理消息的时间少于 60 秒,Lambda 将尽快用另一批再次调用它,您可能会再次超出预算。”,但由于我已经定义了批处理窗口所以它不应该在 60 秒后选择下一批,即使它在不到 60 秒内处理了上一批?
  • @Marcin - 我想过,但想不出更好的解决方案。如果队列上有一致的负载,那么运行 fargate 容器肯定会比 lambda 便宜。如果有零星的负载,这可能仍然更具成本效益。
  • @nats 这不是这样的。它等待配置的 65 秒或直到 250 条消息可用,以先发生者为准。如果队列中等待的消息超过 250 条,则无法保证它只会每 60 秒调用一次。
  • 哦,好吧!所以这意味着无论哪个条件为真,它都会再次被调用。
猜你喜欢
  • 1970-01-01
  • 2020-06-09
  • 2012-05-19
  • 1970-01-01
  • 2019-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-19
相关资源
最近更新 更多