跳到主要内容
英文版本为准

本页译自英文,由模型翻译。若与英文原文存在差异,以英文原文为准。

发布者确认与事务

向 RabbitMQ 的一次发布,在帧写出时、服务器确认时或信道事务提交时完成。

发布完成的三种方式:发后即忘在帧写出时,发布者确认在服务器应答时,事务在提交时发后即忘发布者确认事务basic.publish帧写出后立即返回confirm.select一次basic.publish每条消息收到 basic.ack或 basic.nacktx.select一次basic.publish一次或多次tx.commitcommit-ok:每次发布都可见没有队列接收的消息会被确认并丢弃:本 crate 发布时不带 mandatory 标志
以文字阅读本图
  1. 发后即忘: basic.publish; 帧写出 后立即 返回
  2. 发布者确认: confirm.select 一次; basic.publish; 每条消息 收到 basic.ack 或 basic.nack; 没有队列接收的消息会被确认并丢弃: 本 crate 发布时不带 mandatory 标志
  3. 事务: tx.select 一次; basic.publish 一次或多次; tx.commit; commit-ok: 每次发布 都可见
  4. basic.publish → 帧写出 后立即 返回
  5. confirm.select 一次 → basic.publish
  6. basic.publish → 每条消息 收到 basic.ack 或 basic.nack
  7. tx.select 一次 → basic.publish 一次或多次
  8. basic.publish 一次或多次 → tx.commit
  9. tx.commit → commit-ok: 每次发布 都可见

basic.publish 本身没有应答。发送后就继续往下走的发布者对这条消息一无所知:不存在的交换机或出了故障的队列都不会被察觉。

发布者确认补上了这个应答。confirm.select 之后,信道为它的发布编号,服务器在承担起每条消息的责任后,用 basic.ack 应答。对持久队列中的持久化消息,这意味着已写入磁盘;对仲裁队列,这意味着已被法定数量的副本接受。basic.nack 表示服务器无法处理这条消息,这种情况很少见:它来自队列的内部错误。

不匹配任何绑定的消息也会被确认。交换机找不到队列,服务器确认这条消息,然后丢弃它。只有 mandatory 标志才会让服务器把这样的消息退回给发布者。

信道事务在服务器上暂存发布。tx.select 之后,发布一直等到 tx.commit;commit-ok 表示其中每一次发布都已可见,tx.rollback 则丢弃它们。每次提交都是一次等待服务器的往返。节点在提交过程中故障时,RabbitMQ 不保证原子性。

在本 crate 中​

发布策略决定模式,更强的模式就是另一个策略:

策略信道发布何时返回
LapinPublish连接上所有这类发布者共用的一个信道帧写出之后
ConfirmsPublish自己的信道,处于确认模式服务器确认之后;否定确认是一个错误
ServerTxPublish自己的信道,处于事务模式在事务内,提交时

发布者确认或事务信道在第一次发布时打开,所以从不发布的策略不持有信道。每次发布都不带 mandatory,所以已确认的发布仍可能没有到达任何队列:确认表示服务器收下了消息,而不是有队列持有它。除非策略另行指定,消息都是持久化的。

信道错误会关闭信道,连接保持不变。一次发往不存在的交换机的发后即忘发布就足以触发它,而发布者看不到服务器的应答。下一次发布会打开一个新信道。带着未完成的事务而失效的事务信道是个例外:事务存在于这个信道上,所以提交会失败,而不是报告成功。

ConfirmsPublish 的事务是服务中的一个缓冲区。提交按顺序发布缓冲的消息,并等待每一个确认。它对每条消息是持久的,但不是原子的:在失败的那条之前发出的消息仍然是已发布的。ServerTxPublish 的事务是 RabbitMQ 自己的事务。每个信道只有一个,因为 tx.select 让信道本身进入事务模式。

协议规则来自 RabbitMQ(发布者确认、事务)。