Amazon SQS 消息消失了

Woo*_*ess 0 amazon-sqs amazon-web-services dead-letter boto3

我有一个 Amazon SQS 队列和一个死信队列。

我的 python 程序从 SQS 队列获取一条消息,然后,如果它引发异常,它会将消息发送到死信队列。

现在我有一个程序可以检查死信队列是否仍然可以处理这些消息。如果是,它将被发送回主 SQS 队列。你看,我在这里期望的是在我的测试中出现各种无限循环,但显然,该消息在 2 次尝试后消失。为什么会这样?

当我在消息中添加一个额外的字段(这是随机值)时,它会以某种方式执行我的期望(来回发送的无限循环)。SQS 中是否有一种机制可以阻止我在消息相同时执行的操作?

def handle_retrieved_messages(self):
    if not self._messages:
        return None

    for message in self._messages:
        try:
            logger.info(
                "Processing Dead Letter message: {}".format(
                    message.get("Body")
                )
            )
            message_body = self._convert_json_to_dict(message.get("Body"))
            reprocessed = self._process_message(
                message_body, None, message_body
            )
        except Exception as e:
            logger.exception(
                "Failed to process the following SQS message:\n"
                "Message Body: {}\n"
                "Error: {}".format(message.get("Body", "<empty body>"), e)
            )
            # Send to error queue
            self._delete_message(message)
            self._sqs_sender.send_message(message_body)
        else:
            self._delete_message(message)
            if not reprocessed:
                # Send to error queue
                self._sqs_sender.send_message(message_body)
Run Code Online (Sandbox Code Playgroud)

self._process_message 将检查 message_body 是否将重新处理标志设置为 true。如果为真,则将其发送回主队列。

现在我将消息的内容制作成错误,所以每次在主队列中处理它时,它都会变成死信。然后我希望这会继续循环,但 SQS 看起来有一种机制可以阻止这种情况发生(这很好)。

问题是那是什么设置?

Joh*_*ein 7

Amazon SQS 队列的正常工作方式是:

  • 消息被发送到队列
  • 应用程序调用ReceiveMessage()队列以接收一条消息(或多条消息)。这会增加消息的接收计数
  • 这会将消息置于不可见状态。这意味着该消息仍在队列中,但如果另一个应用程序尝试从队列接收消息,则该消息不可见
  • 应用程序处理完消息后,将调用DeleteMessage(),提供消息的消息句柄。这将从队列中删除消息
  • 但是,如果应用程序没有在中删除该邮件不可见超时时间,则消息队列再次出现。这是在应用程序崩溃的情况下完成的。消息不会丢失,而是被放回到队列中,以便另一个(或相同的)应用程序可以再次处理它。
  • 如果消息超过不可见超时期限并且其接收计数现在超过最大接收设置,则不会将其放回队列中。相反,它被放置在死信队列 (DLQ) 上

因此,正常流程是,在收到的消息超过(在您的情况下)尝试接收 10 次后,Amazon SQS 会将消息移动到 DLQ将消息移动到死信队列不是您的应用程序的工作!

如果您想自己处理所有“死信”处理(例如,移动到不同的队列),请关闭队列本身的 DLQ 功能。这可能会导致您的消息消失或转到错误的位置。

顺便说一句,删除消息时,您需要提供MessageHandle消息的 ,而不是消息本身。