1

我正在实现 RabbitMQ 以在另一台服务器上执行一些图像编辑操作。但是,有时请求可能会在源图像同步到该服务器之前到达该服务器 - 在这种情况下,我想将消息弹出回队列并在所有其他操作完成后处理它。

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

目前我觉得我被迫实现一些逻辑,只是将原始消息重新提交给交换,但我想避免这种情况。既是因为同一条消息可能已在另一台服务器上成功处理(使用它自己的队列),也是因为我希望这是一种常见的模式,必须有更好的方法。

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

谢谢!

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

我目前的解决方案:

  • $dead_letter_exchange在原始队列上声明死信交换$worker
  • 宣布恢复交换$recovery_exchange
  • 声明一个队列$dead_queue,ax-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 的消息在五秒钟后仅在该特定队列(服务器)上返回给工作人员进行重试。我可能仍想应用一些在$n重试后将消息丢弃的逻辑。

我仍然对更好的想法持开放态度;-)

4

1 回答 1

1

看起来你有“竞争条件”问题,这是问题的原因。也许延迟消息发布或发布延迟消息是一个不错的选择,以确保图像同步到目标机器或在图像到达时发布消息(这可能很棘手)或只是按需同步图像(当消息消耗时)。您甚至可以添加一些 API 来获取源图像,这样您就可以随时横向扩展您的消费者,而不会感到任何痛苦。这个想法是让消费者尽可能地原子化和不可靠。

回到原来的问题,如果它适合您,请尝试死信交换将失败的消息移动到单独的队列。混合失败的消息和有效的消息,但没有确定的机制来检测重新发布的气味(由于潜在的循环问题、管理困难等原因)。但这实际上取决于您的需求、消息速率和硬件,如果某些解决方案产生稳定的结果并且您对此很确定 - 坚持下去。

请注意,如果您使用 php-amqplib,您可以同时开始从多个队列消费消息,因此您可以从主队列和延迟消息消费消息(但在这种情况下,您必须将消息发布到延迟队列延迟也可以防止它立即消耗)。

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

于 2014-08-11T22:53:59.730 回答