AWS Lambda-批量处理消息

时间:2019-02-08 15:59:43

标签: node.js amazon-web-services aws-lambda amazon-sqs

我在想什么,我真的找不到关于它的信息。也许不是要走的路,但是,我只想知道。

这是关于Lambda分批工作的。我知道我可以设置Lambda来使用批处理消息。在我的Lambda函数中,我迭代每条消息,如果一条消息失败,则Lambda存在。然后循环再次开始。

我想知道稍微不同的方法 假设我有3条消息: A B C 。我也分批服用。现在,如果消息B失败(例如API调用失败),我将消息B返回给SQS,并继续处理消息C。

有可能吗?如果是,这是一个好方法吗?因为我看到我需要在Lambda中实现一些额外的复杂性,所以不需要。

谢谢

5 个答案:

答案 0 :(得分:3)

有一篇很棒的文章here。与您相关的部分是...

  • 使用batchSize为1,以便消息自行成功或失败。
  • 确保您的处理是幂等的,因此重新处理消息不会造成危害,而不会产生额外的处理费用。
  • 在功能代码中处理错误,可能是通过捕获错误并将消息发送到死信队列进行进一步处理。
  • 成功处理消息后,在函数中手动调用DeleteMessage API。

最后一个要点是我如何处理相同的问题。与其立即返回错误,不如存储它们或注意已发生错误,而是继续处理批处理中的其余消息,而不是立即返回错误。在处理结束时,返回或引发错误,以使SQS-> lambda触发器知道不删除失败的消息。您的lambda处理程序将删除所有成功的消息。

sqs = boto3.client('sqs')

def handler(event, context):
    failed = False

    for msg in event['Records']:
        try:
            # Do something with the message.
            handle_message(msg)
        except Exception:
            # Ok it failed, but allow the loop to finish.
            logger.exception('Failed to handle message')
            failed = True
        else:
            # The message was handled successfully. We can delete it now.
            sqs.delete_message(
                QueueUrl=<queue_url>,
                ReceiptHandle=msg['receiptHandle'],
            )

    # It doesn't matter what the error is. You just want to raise here
    # to ensure the trigger doesn't delete any of the failed messages.
    if failed:
        raise RuntimeError('Failed to process one or more messages')

def handle_msg(msg):
    ...

答案 1 :(得分:2)

截至2019年11月,AWS has introduced的概念是函数错误Bisect,以及最大重试次数。如果您的函数是幂等的,则可以使用它。

在这种方法中,即使批处理中的一项失败,也应该从函数中引发错误。 AWS将批次分为两部分,然后重试。现在,该批次的一半应该成功通过。对于另一半,此过程将继续进行,直到隔离不良记录为止。

答案 2 :(得分:1)

就像所有架构决策一样,这取决于您的目标以及您为更复杂而愿意进行的交易。使用SQS将使您能够按顺序处理消息,以便重试不会阻止其他消息。复杂性是否值得,取决于您担心邮件被阻止的原因。

我建议阅读有关Lambda retry behavior和死信队列的信息。

答案 3 :(得分:1)

如果您只想重试一批邮件中失败的邮件,则完全可以,但是会增加一些复杂性。

实现此目的的一种可能方法是遍历事件列表(例如[eventA,eventB,eventC]),对于每次执行,如果事件失败,则追加到失败事件列表中。然后,使用一个最终案例检查失败事件列表中是否包含任何内容,如果有,则手动将消息发送回SQS(使用SQS sendMessageBatch)。 / p>

但是,您应该注意,由于您是手动将事件插入回去,因此这会将事件置于队列的末尾。

如果任何事情都可以解决您遇到的问题而没有太多复杂性,那么任何事情都可以成为“好方法”,在这种情况下,必须重新执行成功的事件绝对是您可以通过这种方式解决的问题。

答案 4 :(得分:1)

对于Node.js,请检出https://www.npmjs.com/package/@middy/sqs-partial-batch-failure

const middy = require('@middy/core')
const sqsBatch = require('@middy/sqs-partial-batch-failure')

const originalHandler = (event, context, cb) => {
  const recordPromises = event.Records.map(async (record, index) => { /* Custom message processing logic */ })
  return Promise.allSettled(recordPromises)
}

const handler = middy(originalHandler)
  .use(sqsBatch())

查看https://medium.com/@brettandrews/handling-sqs-partial-batch-failures-in-aws-lambda-d9d6940a17aa了解更多详细信息。