【问题标题】:Re-process DLQ events in Lambda在 Lambda 中重新处理 DLQ 事件
【发布时间】:2020-10-22 04:42:51
【问题描述】:

我有一个配置了 SQS DeadLetterQueue 的 AWS Lambda 函数“A”。当 Lambda 无法处理事件时,它会正确发送到 DLQ。有没有办法重新处理以 DLQ 结束的事件?

我找到了两个解决方案,但它们都有缺点:

  1. 创建一个新的 Lambda 函数“B”,该函数从 SQS 中读取数据,然后将事件一一发送到之前的 Lambda“A”。 -> 这里我要编写新代码并部署一个新函数
  2. 仅当事件到达 SQS 时再次触发 Lambda 'A' -> 这看起来很危险,因为我可能会在循环执行中招致

我理想的解决方案应该是使用 Lambda 'A' 按需重新处理丢弃的事件,而不是从头开始创建新的 Lambda 'B'。有没有办法做到这一点?

【问题讨论】:

  • 目前尚不清楚您是否可以在不引入无限循环的情况下实现自动化。如果给定消息未能处理 N 次并最终出现在 DLQ 上,那么可能有多种原因可能会导致这种情况发生,包括消息的某些内在因素会触发您的 Lambda 函数中的错误。您无法轻松地自动恢复 - 这将需要调试和潜在的代码重新部署,或消息编辑和重新提交。
  • 感谢您的建议!我的用例如下:我有一个调用外部 api 的 Lambda,并且由于限制原因,某些调用可能会失败。我想找到一种方法来按需重新处理这些事件(例如 1 小时后),而无需编写 lambda 来执行此操作。我在 SQS 中有事件,我有 Lambda 来处理它们:我缺少的是按需触发器或类似服务
  • 您可以考虑一个独立的“重试”队列。如果您的 API 调用受到限制,请将底层消息发送到该队列,而不是将其返回到其原始队列。使用 CloudWatch 按小时或其他计划运行新的简单 Lambda。让它使用一些业务逻辑从重试队列中拉出,并将消息发送回原始队列,以进行后续处理。或者该模式的某种变体,也许。或者只是使用 DLQ 作为“重试”队列。
  • 那么看来无论如何我都要写一些自定义代码,至少要重新处理DLQ事件的新的Lambda函数。感谢@jarmod 的建议,定期安排 CloudWatch 似乎是最佳选择,因为我需要其他自定义代码来按需启动 lambda。

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


【解决方案1】:

最后,我没有从 AWS 找到任何解决方案来重新处理 Lambda 函数的 DLQ 事件。然后我创建了自己的自定义 Lambda 函数(我希望这对其他有相同问题的开发人员有所帮助):

import boto3

lamb = boto3.client('lambda')
sqs = boto3.resource('sqs')
queue = sqs.get_queue_by_name(QueueName='my_dlq_name')


def lambda_handler(event, context):
    for _ in range(100):
        messages_to_delete = []
        for message in queue.receive_messages(MaxNumberOfMessages=10):
            payload_bytes_array = bytes(message.body, encoding='utf8')
            # print(payload_bytes_array)
            lamb.invoke(
                FunctionName='my_lambda_name',
                InvocationType="Event",  # Event = Invoke the function asynchronously.
                Payload=payload_bytes_array
            )

            # Add message to delete
            messages_to_delete.append({
                'Id': message.message_id,
                'ReceiptHandle': message.receipt_handle
            })

        # If you don't receive any notifications the messages_to_delete list will be empty
        if len(messages_to_delete) == 0:
            break
        # Delete messages to remove them from SQS queue handle any errors
        else:
            deleted = queue.delete_messages(Entries=messages_to_delete)
            print(deleted)

部分代码灵感来自this post

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-14
  • 1970-01-01
  • 2010-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-04
相关资源
最近更新 更多