2011-12-01 45 views
7

我有一些很难理解的RabbitMQ的确认,我看到了下面从RabbitMQ的解释:行为“确认”模式的RabbitMQ渠道

经纪人失去,如果持久性消息在所述 消息被写入磁盘之前它崩溃。在某些情况下,这会导致经纪人以令人惊讶的方式行事。例如,考虑这个 场景:

  • 客户端发布的持久消息持久的队列

  • 客户端从队列中消耗消息(指出消息是持久性和队列耐用) ,但还没有确认它,

  • 经纪人死了,被重新启动,

  • 客户端重新连接并开始消费消息。

此时,客户可以合理地认为消息 将再次发送。情况并非如此:重新启动导致代理丢失信息 。为了保证持久性,一个 客户端应该使用确认。如果发布者的通道已经在 确认模式,出版商也不会接收到 失去消息的ACK(因为消费者没有ack'd它,它一直没 写入到磁盘)。

然后我用这http://hg.rabbitmq.com/rabbitmq-java-client/file/default/test/src/com/rabbitmq/examples/ConfirmDontLoseMessages.java做一些基本的测试和验证确认,但得到一些奇怪的结果:

  1. 的waitForConfirmsOrDie方法不会阻止制片人,这是我的预期不同,我想waitForConfirmsOrDie会阻止生产者,直到所有的消息被删除或者其中一个消息被删除。
  2. 我从发布者中删除了channel.confirmSelect()和channel.waitForConfirmsOrDie(),并将消费者从auto ack更改为手动ack,我将所有消息发布到队列并逐个使用消息,然后停止rabbitmq服务器在消耗过程中,我现在期望的是在rabbitmq服务器重新启动后,左边的消息将会丢失,因为通道不处于确认模式,但在服务器重新启动后仍然可以看到队列中的所有其他消息。

因为我是RabbitMQ的新手,谁能告诉我我的确认问题在哪里?

回答

3

我的理解是,“渠道确认”是为经纪人确认成功从生产者处获得消息,而不管消费者是否对此消息进行了确认。根据队列类型和消息传递模式,请参阅http://www.rabbitmq.com/confirms.html的细节,

的消息被证实时:

  • 它决定的消息不会被路由到队列 (如果强制标志被设置,那么一个暂时的消息已经到达了它的所有队列(和镜像)或者是一个持久的消息已经到达了它的所有队列(和镜像)并且被持久化到了磁盘(和fsynced)或者
  • 持久性消息已经从它的所有队列
0

老问题,但消费(如果需要确认)哦..

我发布到队列中的所有消息和接收消息一个接一个,那么我在消费过程中会停止rabbitmq服务器,我现在所期望的是在rabbitmq服务器重新启动后留下的消息将会丢失,因为该通道未处于确认模式,但我仍然可以看到队列中的所有其他消息服务器重启。

这实际上是如何工作的,如果启用了持久性。如果服务器崩溃或出现其他问题,则无法确认消息,因此不会从队列中删除。

只有在确认要处理消息时,消息才会从队列中删除,或者代理在服务器崩溃之前尚未将消息写入内存或磁盘。

确认和确认可以设置,如果需要,生产者不会等待acks。我现在找不到确切的命令,但它确实存在。

更多关于确认和确认:https://www.rabbitmq.com/reliability.html