在使用 RabbitMQ 的时候,作为消息发送方希望杜绝任何消息丢失或者投递失败场景
。RabbitMQ 为我们提供了两种方式
用来控制消息的投递可靠性模式。
- confirm 确认模式
- return 退回模式
rabbitmq 整个消息投递的路径为:
producer—>rabbitmq broker—>exchange—>queue—>consumer
- 消息
从 producer 到 exchange
则会返回一个confirmCallback
。 - 消息
从 exchange–>queue
投递失败则会返回一个returnCallback
。
确认模式(针对的是生产者发送消息到交换机的过程)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-rabbitmq-producer.xml")
public class ProducerTest {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 确认模式:
* 步骤:
* 1. 确认模式开启:ConnectionFactory中开启publisher-confirms="true",在配置文件设置
* 2. 在rabbitTemplate定义ConfirmCallBack回调函数
*/
@Test
public void testConfirm() {
//2. 定义回调
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
if (ack){ //说明消息到达了交换机
//接收成功
System.out.println("接收成功消息" + cause);
}else { //说明消息没有到达交换机
//接收失败
System.out.println("接收失败消息" + cause);
//做一些处理,让消息再次发送,具体逻辑自己编写。
}
}
});
//3. 发送消息
rabbitTemplate.convertAndSend("test_exchange_confirm", "confirm", "message confirm....");//成功
rabbitTemplate.convertAndSend("test_exchange_confirm000", "confirm", "message confirm....");//失败
}
}
退回模式(针对的是交换机发送消息到队列的过程)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-rabbitmq-producer.xml")
public class ProducerTest {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 回退模式: 当消息发送给Exchange后,Exchange路由到Queue失败时 才会执行 ReturnCallBack
* 步骤:
* 1. 开启回退模式:publisher-returns="true",在配置文件设置
* 2. 设置ReturnCallBack
* 3. 设置Exchange处理消息的模式:
* 1). 如果消息没有路由到Queue,则丢弃消息(默认)
* 2). 如果消息没有路由到Queue,返回给消息发送方ReturnCallBack
* rabbitTemplate.setMandatory(true);
*/
@Test
public void testReturn() {
//设置交换机处理失败消息的模式
rabbitTemplate.setMandatory(true);
//2.设置ReturnCallBack
rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
/**
* 交换机路由消息到队列失败,会返回结果信息,执行回调函数
* @param message 消息对象
* @param replyCode 错误码
* @param replyText 错误信息
* @param exchange 交换机
* @param routingKey 路由键
*/
@Override
public void returnedMessage(Message message, int replyCode,String replyText,String exchange,String routingKey) {
System.out.println("return 执行了....");
System.out.println(message);
System.out.println(replyCode);
System.out.println(replyText);
System.out.println(exchange);
System.out.println(routingKey);
//处理,消息我们这里也能捕获到,具体逻辑是将消息重回队列还是怎么着,看自己业务场景去编写
}
});
//3. 发送消息
rabbitTemplate.convertAndSend("test_exchange_confirm", "confirm", "message confirm....");
}
}
小结
- 设置 ConnectionFactory的publisher-confirms=“true”
开启 确认模式
。 - 使用 rabbitTemplate.setConfirmCallback 设置回调函数。当消息发送到 exchange 后回调 confirm 方法。在方法中判断 ack,如果为true,则发送成功,如果为false,则发送失败,需要处理。
- 设置 ConnectionFactory 的 publisher-returns=“true”
开启 退回模式
。 - 使用 rabbitTemplate.setReturnCallback 设置退回函数,当消息从exchange 路由到 queue 失败后,如果设置了 rabbitTemplate.setMandatory(true) 参数,则会将消息退回给 producer并执行回调函数returnedMessage