RabbitMq Acks / Republishing

时间:2015-10-02 12:13:16

标签: c# .net rabbitmq

使用Rabbit的C#项目。我发现在我看来,在连接或频道死亡时重新传递消息的文档中有什么相互矛盾的信息(哪一个是什么?)

这里的文档: http://www.rabbitmq.com/semantics.html

声明在频道关闭时它会重新发送

  

可以使用具有该功能的AMQP方法将消息返回到队列   一个重新排队参数(basic.recover,basic.reject和basic.nack),或   由于频道关闭,同时保留未确认的消息。任何   这些场景导致消息在后面重新排队   RabbitMQ的队列早于2.7.0发布。来自RabbitMQ发布   2.7.0,即使存在重新排队或频道关闭,消息也始终按发布顺序保存在队列中。

但是在这里:http://www.rabbitmq.com/tutorials/tutorial-two-dotnet.html

状态:仅当工人连接断开时

  

如果消费者在没有发送确认的情况下死亡,RabbitMQ将会理解   消息未完全处理并将其重新发送给另一个消息   消费者。这样你就可以确定没有消息丢失,即使   工人偶尔会死。

     

没有任何消息超时; RabbitMQ将重新发送消息   仅在工作人员连接死亡时。即使处理a也没关系   消息需要非常长的时间。

那么什么时候重新发生呢?当工人或渠道死亡?我可以在一个频道上消费,但在另一个频道上确认吗?

目前我创建了一个ChannelManager类,它可以打开N个通道,并在需要时将它们存储在ConcurrentQueue和Queues / Dequeues Channels中,并确保我们永远不会低于“最小”可用通道数。使用这种方法,我无法确保Consume和Ack在同一个频道上发生...

2 个答案:

答案 0 :(得分:4)

第二个引用措辞错误,但该工作页面周围的上下文仍然正确...您以粗体显示的句子将正确更改为:

  当消费者死亡时,RabbitMQ将重新发送消息。

以这种方式说这不会排除其他合法案件,但会说明他们在本文中指出了这一点。

...

如果要重新排队并重新传递邮件,则必须确保noAck设置为false(这是默认设置)。一旦你有了,你引用的第一段是正确的。

...

关于您的ChannelManager - 不必要。渠道是便宜的,快速的东西,可以根据需要站起来拆除。只要您使用所有开放频道,只有1个开放频道或拥有1,000个开放频道是可以的。

另一方面,连接价格昂贵。为每个应用实例打开一个连接。然后在该连接中使用尽可能多的频道。

答案 1 :(得分:0)

首先,拥有一个“通道池”(我称之为“通道池”)会给您的应用程序带来有害的复杂性。绝对不要在线程之间共享通道。将渠道视为端点标识符-它并不代表与代理的单独连接,而是代表通过代理与代理进行的独特讨论-read more here

第二,教程并不是真正的文档。这可能有助于理解代理的工作方式,但是我通常希望教程中编写的内容特定于该教程中所描述的场景。在这种情况下,文档说明了可能重新排列邮件的情况。

第三,重新排队和重新交付是分开的。重新交还只能在重新排队后发生,但不能保证。例如,一条消息可能在重新排队之后但在重新传递之前到期(可能是因为没有消费者可以接收该消息,或者它在队列中等待了太长时间)。

最后,传递给消费者的每条消息都会被分配一个传递标签。该标签特定于渠道以及渠道上的消费者。因此,不可能从另一个渠道ack开始,因为另一个渠道缺乏对交付标签的上下文了解。