【问题标题】:AWS SQS triggered lambda suddenly stalling and not deleting messagesAWS SQS 触发 lambda 突然停止并且不删除消息
【发布时间】:2021-03-26 18:09:18
【问题描述】:

我有一个 lambda python 函数函数,它连接到批量大小为 1 的 SQS 队列触发器。SQS 消息包含 S3 上的文件位置,以及一些元数据值。

当消息可用时,该函数从消息中引用的 S3 上的文件中读取一些元数据,创建一个包含更多元数据的 YAML 文件,然后将其转储到 S3 并引用 RDS 数据库中的元数据文件。

在我将大量消息提交到队列 (~1.7k) 后,最初一切似乎都很顺利,可用的消息数量正在下降,而 lambda 执行量却在增加。

但一段时间后,执行时间会显着增加,直至函数超时(超时设置为 90 秒)。我在日志中看不到任何错误,并且执行仍然成功(如果它们没有超时)。

所有这些都可以在监控中看到:

在这里,在 lambda 监控中,您可以看到持续时间的突然增加,同时并发执行的下降和错误的突然出现(最坏的情况是有两个错误,60 %s 的成功率)。您看到的差距是我禁用和启用触发器希望进行更改。

这是同期的 SQS 监控:

你可以看到可见的消息数量稳定在 192 条,收到的消息数量是 5 条。更让我困惑的是,即使执行成功,删除的消息数量也下降到 0。

我真的不明白为什么现在会出现这个问题,我一直在使用这个配置,没有问题和更改。

当从 S3 读取超时时,SQS 触发器配置会阻塞队列吗?有什么线索吗?

谢谢!

编辑:

RDS 集群指标:

【问题讨论】:

  • 可能是您的 RDS 跟不上连接或写入数量的增加。您检查过 RDS 指标吗?
  • 您可以尝试排除法排除故障。如果可能,注释掉与 RDS 相关的代码,并检查这是否会改变行为。如果没有太大变化,可能注释掉一些 S3 对象处理部分,等等。
  • 如果 lambda 的超时时间大于 1 分钟,那么 1 分钟的可见性超时当然不是一个好主意。队列的可见性超时应该是 lambda 超时的(5 或 6)倍。目前 lambda 收到一条消息,可能需要 > 1 分钟,然后尝试删除该消息,但根据 SQS,lambda 不再“拥有”该消息并且无法删除它。
  • 我同意 Marcin 的观点,将内容注释掉,在各种地方添加日志语句 - 您需要找出导致超时的原因。除了这些,我们真的无能为力,因为我们不知道 lambda 究竟做了什么。
  • 我可以将其添加为答案,是的。但请注意,现在执行时间标准化这一事实进一步表明,当收到大量消息时,RDS 或 S3 之类的东西会减慢您的速度。您应该进一步调查该点和/或在队列上添加并发限制。拥有这类批量消息会导致麻烦是很常见的,因为即使 AWS 也需要根据请求进行扩展,并且基本上即时峰值不会给出例如S3 有足够的时间进行扩展。

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


【解决方案1】:

如果 lambda 成功处理消息,但 SQS 队列没有删除任何消息,这很可能表明队列可见性超时和 lambda 超时不匹配。您应该确保获取消息的 lambda 服务有足够的时间来完成消息并告诉 SQS 删除消息。如果 lambda 需要 70 秒,但队列只有 60 秒的可见性超时,这意味着 lambda 服务的 DeleteMessage 请求将被静默拒绝,消息将保留在队列中,稍后将再次重新处理,可能会产生完全相同的结果。

第一个注意事项:如果您为 lambda 设置了并发限制,则队列的可见性超时不仅应等于 lambda 超时,而且应为 lambda 超时的倍数,即 lambda 超时的 5 或 6 倍。原因是 lambda 服务可能会获取消息,尝试调用 lambda,但 lambda 会限制它,然后 lambda 服务会等待(lambda 超时)重试消息。在 lambda 服务不会将消息返回到队列的所有过程中,它会将其保存在内存中,不会延长可见性超时或类似的事情。在消息被实际丢弃/返回到 SQS 之前,它会重试几次(5 或 6 次)。您应该可以通过创建一个超时为例如的 lambda 来尝试这一点。 10 秒,让它简单地休眠/等待 9 秒,并发限制为 1,然后将 1000 条消息放入队列。

第二点:这种突然的批量操作可能会导致各种不正常发生的限制问题,无论是您自己的其他下游服务,还是 AWS 的服务。例如。如果您的 lambda 执行 assume-role 调用或从具有 500 个请求的 S3 检索一些配置对象,那么消息在队列中的那一刻通常会给您带来麻烦。底层数据库可能会变得缓慢/无响应,缓冲所有传入的请求等。
该问题的一个简单解决方案是通过设置并发限制来限制 lambda。此时,请确保队列具有适当的可见性超时,如上一节所述。并且为了确保您收到请求实际增加的警报,请确保您查看队列的ApproximateAgeOfOldestMessage 指标,以便在积压增加时收到警报。

第三个注意事项:如果 lambda 仅在大量请求进入时行为异常,一个潜在原因是 lambda 中的内存泄漏。由于 lambda 的执行上下文在不同的调用之间重用,内存泄漏也存在于不同的调用中。如果进入的请求很少,您可能总是会得到一个新的执行上下文,这意味着 lambda 每次都从新内存开始,但是如果执行上下文中有很多请求肯定会被重用,这可能会导致泄漏变得如此之大由于垃圾收集启动,lambda 基本上会冻结。lambda 中的 /tmp 目录也是如此。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-28
    • 2020-07-17
    • 2020-07-10
    • 2022-01-06
    • 2020-05-17
    • 2019-10-17
    • 2021-03-22
    • 2021-12-07
    相关资源
    最近更新 更多