一、保证可靠性消息投递
首先需要明确,效率与可靠性是无法兼得的,如果要保证每一个环节都成功,势必会对消息的收发效率造成影响。 如果是一些业务实时一致性要求不是特别高的场合,可以牺牲一些可靠性来换取效率。
在消息投递过程中,一共有四处需要保证可靠性。如图。
①
代表消息从生产者发送到Exchange;②
代表消息从Exchange路由到Queue;③
代表消息在Queue中存储;④
代表消费者订阅Queue并消费消息。
二、解决方案
2.1 确保消息发送到RabbitMQ服务器
可能因为网络或者Broker的问题导致1失败,而生产者是无法知道消息是否正确发送到Broker的。 有两种解决方案,第一种是Transaction(事务)模式,第二种Confirm(确认)模式。
- Transaction(事务)模式:
在通过channel.txSelect
方法开启事务之后,我们便可以发布消息给RabbitMQ了,如果事务提交成功,则消息一定到达了RabbitMQ中,如果在事务提交执行之前由于RabbitMQ异常崩溃或者其他原因抛出异常,这个时候我们便 可以将其捕获,进而通过执行channel.txRollback
方法来实现事务回滚。使用事务机制的话会很大程度消耗RabbitMQ的性能,一般不建议使用。 - Confirm(确认)模式:
生产者通过调用channel.confirmSelect方法(即Confirm.Select命令)将信道设置为confirm模式。一旦消息被投 递到所有匹配的队列之后,RabbitMQ就会发送一个确认(Basic.Ack)给生产者(包含消息的唯一ID),这就使得生产者知晓消息已经正确到达了目的地了。
2.2 确保消息从交换机路由到正确的队列
可能因为路由关键字错误,或者队列不存在,或者队列名称错误导致2失败。 这种情况一般不存在,队列和交换机都是进