【问题标题】:Deleting messages from SQS queue after processing处理后从 SQS 队列中删除消息
【发布时间】:2015-04-23 13:26:56
【问题描述】:

我的应用程序为需要某种后台处理的作业向 AWS SQS 队列发送消息。我的处理守护进程接收并处理这样的消息:

$result = $sqsClient->receiveMessage([
    'QueueUrl' => \Myapp\Config::get('sqs.queue'),
    'WaitTimeSeconds' => 20,
    'MaxNumberOfMessages' => 1
]);

if (isset($result['Messages'])) {
    foreach ($result->getPath('Messages/*/Body') as $messageBody) {
        $handler = new \Myapp\Handler();
        $handler->dispatch($messageBody);
    }
}

这很好用,但是我可以从 SQS 控制台看到我的脚本检索到的消息被放入“正在运行的消息”类别中,然后过一段时间它们又被放回“可用消息”中,并且我的脚本最终又把它们捡起来了。

如何从 SQS 队列中删除消息,或者更好地将它们标记为已完成?

【问题讨论】:

    标签: php amazon-web-services amazon-sqs


    【解决方案1】:

    当您收到来自 SQS 队列的消息时,该消息将(默认情况下)在 30 秒后返回到队列。这是为了处理消息处理崩溃并且需要再次处理消息的情况。

    成功处理您的消息后,使用deleteMessage 删除该消息。当您从 receiveMessage 收到邮件时,您需要邮件中的 receiptHandle 值才能删除邮件。

    如果您的消息的典型处理时间可能超过 30 秒,那么您可以配置您的队列以增加“返回队列”时间。这在 SQS 队列配置中称为“默认可见性超时”。

    另请注意,Amazon SQS 的工作方式是:

    1. 与将消息添加到队列的方式相比,消息可能被无序接收
    2. 可能会收到两次消息,因此请让您的消息处理器处理这些情况

    【讨论】:

    【解决方案2】:

    您确实需要在处理完消息后删除它们 - 这将被视为“将它们标记为已完成”;但是,如果下游需要对此“完成”操作采取行动,我将“完成”消息发布到另一个 SQS 队列,然后从传入队列中删除该消息并不少见。这样,另一个进程,无论是现在还是未来,都可以在第一个工作人员完成其工作时采取需要执行的操作,即将这些进程以解耦的方式链接在一起。

    如果下游没有什么需要做的,只需删除它就足够了。

    【讨论】:

    • 在大多数情况下,您确实需要在处理完邮件后将其删除。例如1)如果您只是通过代码从队列中读取,并且您不希望消息在队列中弹出并稍后重新读取,如果您不删除它就会这样做,并且 2)如果您允许批量sqs消息触发lambas,那么您需要删除已成功处理的消息以避免批处理中的每条消息重新触发lambda(您通常只希望失败重新触发lambda)
    猜你喜欢
    • 2021-03-25
    • 1970-01-01
    • 2020-07-10
    • 2020-03-24
    • 2016-04-29
    • 1970-01-01
    • 2018-03-05
    • 2020-02-14
    • 2012-12-31
    相关资源
    最近更新 更多