RabbitMQ在“确认”模式下的通道行为

时间:2011-12-01 11:33:52

标签: rabbitmq

我在理解RabbitMQ的确认方面遇到了一些麻烦,我从RabbitMQ看到以下解释:

注释

  

如果代理在崩溃之前崩溃,它会丢失持久消息   消息写入磁盘。在某些条件下,这会导致   经纪人以令人惊讶的方式行事。例如,考虑一下   情形:

     
      
  • 客户端将持久性消息发布到持久队列

  •   
  • 客户端使用队列中的消息(注意消息是持久的并且队列持久),但尚未确认,

  •   
  • 经纪人死亡并重新启动,

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

  •   
     

此时,客户端可以合理地假设该消息   将再次交付。情况并非如此:重启导致了   经纪人失去了信息。为了保证持久性,a   客户应该使用确认。如果出版商的频道已经进入   确认模式,出版商不会收到确认   丢失的信息(因为消费者没有得到它,但它没有   写入磁盘)。

然后我使用这个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更改为manual ack,我将所有消息发布到队列并逐个使用消息,然后我停止rabbitmq在使用过程中服务器,我现在期望的是,在重新启动rabbitmq服务器后,左侧消息将丢失,因为通道未处于确认模式,但在服务器重新启动后我仍然会看到队列中的所有其他消息。
  3. 由于我是RabbitMQ的新手,有人能告诉我确认理解的问题在哪里吗?

2 个答案:

答案 0 :(得分:3)

我的理解是“频道确认”是Broker确认它成功地从制作人那里获得了消息,无论消费者是否收到此消息。根据队列类型和邮件传递模式,请参阅http://www.rabbitmq.com/confirms.html了解详细信息,

在以下情况下确认消息:

  • 它决定邮件不会路由到队列 (如果设置了强制标志,则首先发送basic.return)或
  • 瞬态消息已到达其所有队列(和镜像)或
  • 持久性消息已到达其所有队列(和镜像)并且已持久保存到磁盘(和fsynced)或
  • 已从其所有队列中消耗(并且如果必要时已确认)持久性消息

答案 1 :(得分:0)

老问题但是很好..

  

我将所有消息发布到队列并逐个使用消息,然后我在使用过程中停止rabbitmq服务器,我现在期望在重启Rabbitmq服务器后左侧消息将丢失,因为该通道是不是在确认模式下,但在服务器重启后我仍然看到队列中的所有其他消息。

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

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

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

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