【问题标题】:Splittling SQS Lambda batch into partial success/partial failure将 SQS Lambda 批处理拆分为部分成功/部分失败
【发布时间】:2019-10-07 14:33:43
【问题描述】:

AWS SQS -> Lambda 集成允许您批量处理传入消息,您可以在其中配置可以在单个批次中接收的最大数量。如果在处理过程中抛出异常,表示失败,所有消息都不会从传入队列中删除,并且可以在可见性超时过去后由另一个 lambda 提取进行处理。

出于性能原因,是否有任何方法可以保持批处理,但允许批处理中的一些消息成功(并从入站队列中删除)并且只保留一些未删除的批处理?

【问题讨论】:

    标签: aws-lambda amazon-sqs


    【解决方案1】:

    一种选择是手动将失败的消息发送回队列,然后向 SQS 回复成功消息,这样就不会出现重复消息。

    您可以设置失败计数,这样如果所有消息都失败,您可以简单地为所有消息返回失败状态,否则如果失败计数 Lambda 事件)然后您可以单独将失败的消息发送回队列,然后回复成功消息。

    此外,为避免任何可能的无限重试循环,请在将事件发送回队列之前为事件添加一个属性,例如“重试”计数,并在“重试”大于 X 时删除该事件。

    【讨论】:

    • 谢谢,我就是这么想的
    • 请参阅@cdzar 答案以避免此解决方案导致的潜在无限重新排队。
    【解决方案2】:

    手动将失败的消息重新排入队列的问题在于,您可能会陷入无限循环,其中这些项目永远失败并重新排入队列并再次失败。由于它们被重新发送到队列,因此每次重试计数都会重置,这意味着它们永远不会失败进入死信队列。您也失去了可见性超时的好处。这也不利于监控,因为除非您手动检查日志,否则您永远无法知道自己是否处于错误状态。

    更好的方法是手动删除 成功的 项,然后抛出异常以使批处理的其余部分失败。成功的项目将从队列中删除,所有实际失败的项目将达到其正常的visibility timeout 句点并保留其receive count 值,您将能够实际使用和监控死信队列。这也比其他方法总体上更少的工作。

    注意事项

    • 仅在部分批处理失败时才覆盖默认行为。如果所有项目都成功了,让默认行为顺其自然
    • 由于您正在跟踪每个队列项的故障,因此您需要在每个异常进入时捕获并记录它们,以便稍后查看发生了什么

    【讨论】:

    • 您是否要从 lambda 中手动删除它们?我的理解是,即使你删除它们,如果你抛出一个异常,一旦可见性超时过去,整个批次就会再次可用
    • 是的,我的 lambda 中的代码正在删除 部分 成功的一批工作项中的成功项。当在 lambda 中引发异常时,AWS 实际上不会对批处理中的项目执行任何操作。它只是让他们坐在那里,直到他们的可见性超时到期。然后它们要么被 lambda 的某个实例再次拾取,要么在适当的情况下被移动到 DLQ。因此,如果您从队列中删除成功的项目,然后抛出异常以表示部分批处理失败,AWS 不会将成功的项目放回队列中。它并不真正了解他们。
    • FIFO 队列是否如此?我在我的许多队列中使用相同的逻辑没有问题。我最近开始使用一个FIFO队列,即使我手动删除成功的项目,也会重新交付整个批次。
    • @Chris 我还没有使用 FIFO 队列所以我不知道。您是否能够找到记录在案的原因?
    【解决方案3】:

    我最近遇到了这个问题,在不编写任何代码的情况下处理这个问题的最佳方法是使用 EventSourceMapping 的 FunctionResponseTypes 属性。使用它,我们只需要传递失败的消息 ID 列表,事件源将处理删除成功的消息。 请结帐Using SQS and Lambda

    用于为 lambda 配置 Eventsource 的 Cloudformation 模板

    "FunctionEventSourceMapping": {
      "Type": "AWS::Lambda::EventSourceMapping",
      "Properties": {
        "BatchSize": "100",
        "Enabled": "True",
        "EventSourceArn": {"Fn::GetAtt":  ["SQSQueue", "Arn"]},
        "FunctionName": "FunctionName",
        "MaximumBatchingWindowInSeconds": "100",
        "FunctionResponseTypes": ["ReportBatchItemFailures"] # This is important
      }
    }
    

    使用上述配置配置事件源后,它应该如下所示

    然后我们只需要从我们的 lambda 中返回下面提到的格式的响应

    {"batchItemFailures": [{"itemIdentifier": "85f26da9-fceb-4252-9560-243376081199"}]}
    

    在 batchIntemFailures 列表中提供失败消息 Id 的列表 如果您的 lambda 运行时环境在 python 中,请以上述格式返回基于 java 的运行时的 dict,您可以使用 aws-lambda-java-event

    示例 Python 代码

    这种方法的优点是

    1. 您无需添加任何代码即可手动从 SQS 队列中删除消息
    2. 您不必仅仅为了从队列中删除消息而包含任何第三方库或 boto,这将帮助您减少最终工件的大小。
    3. 保持简单的愚蠢

    附带说明,请确保您的 lambda 具有获取和删除消息所需的 sqs 权限。

    谢谢

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-20
      • 2022-01-09
      • 1970-01-01
      • 1970-01-01
      • 2013-03-29
      • 2014-08-11
      • 2016-02-01
      • 1970-01-01
      相关资源
      最近更新 更多