完成所有其他工作后重新使用nack' ed消息

时间:2014-08-11 20:27:30

标签: php rabbitmq php-amqplib

我实施RabbitMQ在另一台服务器上执行一些图像编辑操作。虽然,在源映像同步之前,请求可能会不时地到达该服务器 - 在这种情况下,我希望在队列中弹回消息并在所有其他操作完成后处理它。

但是,使用重新提交位设置调用basic.nack会使我的队列立即重新接收该消息 - 在任何可以实际完成的操作之前。

目前我觉得我被迫实施一些逻辑,只是将原始邮件重新提交给交易所,但我想避免这种情况。两者都是因为同一条消息可能已在另一台服务器上成功处理(使用它自己的队列),并且因为我认为这是一个很常见的模式,所以必须有更好的方法。

(哦,我在消费者和服务器代码中使用php-amqplib)

谢谢!

更新:我使用死信交换解决了我的问题,如zaq178miami所建议

我目前的解决方案:

  • 在原始队列$dead_letter_exchange
  • 上声明死信交换$worker
  • 声明恢复交换$recovery_exchange
  • 声明一个队列$dead_queuex-message-ttl为5秒,x-dead-letter-exchange设置为$recovery_exchange
  • $dead_letter_queue绑定到$dead_letter_exchange
  • 并将$worker绑定到$recovery_exchange
  • $dead_letter_exchange$recovery_exchange是生成的名称,基于我消费的交换和$worker的价值

让每个收到nack的消息在五秒钟后重新返回到该特定队列(服务器)上的worker。我可能仍然希望应用一些在$n重试后将消息抛弃的逻辑。

我仍然愿意接受更好的想法; - )

1 个答案:

答案 0 :(得分:1)

看起来你有竞争条件'问题是导致问题的原因。也许延迟消息发布或发布延迟消息是一个很好的选择,以确保图像同步到目标机器或在图像到达时发布消息(这可能很棘手)或只是按需同步图像(消息消耗时)。您甚至可以添加一些API来获取源图像,这样您就可以随时水平扩展您的消费者。我们的想法是让消费者尽可能地保持原子性和不可靠性。

回到原始问题,如果它是您的选项,请尝试Dead Letter Exchanges将失败的邮件移至单独的队列。混合失败的消息并且有效而没有确定的机制来检测重新发布的气味(由于潜在的循环问题,管理困难等原因)。但它确实取决于您的需求,消息率和硬件,如果某些解决方案产生稳定的结果并且您确定它 - 只需坚持下去。

注意,如果您使用的是php-amqplib,则可以同时开始使用来自多个队列的消息,这样您就可以使用主队列中的消息和推迟的消息(但是在这种情况下,您必须将消息发布到推迟的队列也被推迟,以防止它立即消耗)。

通常通过per-message或per-queue ttl和额外队列完成延迟消息发布,DLX设置为主工作队列,或者在您的情况下为推迟消息队列。