如何保证消息的可靠性
1. 生产者 -> 队列 (可靠投递)需要经过两步
1. 生产者 到 交换机
2. 交换机 到 队列
2. 队列 -> 消费者 (可靠消费)
1、生产者到交换机的保障是依靠confrimCallback机制
confrimCallback:确人回调,默认是不开启的。当开启这个模式之后,生产者会给交换机发送一个消息。交换机收到消息后??
spring:
rabbitmq:
publisher-confirm-type: correlated # 开启confirmCallback
void testConfirmCallBack(){
// 设置ConfimCallball, 重写其中的 confim方法
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
/*
ack 表示消息是否到达了交换机,交换机是否确认收到消息
cause 存储的是没有到达交换机的原因
*/
if(ack==false){
System.out.println("如果没有到达交换机,根据需要写你的业务代码");
}
}
});
Map<String,Object> message=new HashMap<>();
message.put("product_id",10);
message.put("num",50);
message.put("price",600);
rabbitTemplate.convertAndSend("abc","hello.orange.abc", JSON.toJSONString(message));
}
2、交换机到队列的消息保证
returnCallback 翻译过来就是返回回调,但是这种回调机制并不像 confirmCallback 机制一样,
confirmCallback 不管消息是否成功到达交换机都会被调用,
returnCallback 只有在交换机到达队列失败的时候才会被触发,当这个回调函数被调用的时候,
说明交换机的消息没有顺利的到达队列
void testReturnCallBack(){
// 为rabbitTemplate设置return机制触发的方法
rabbitTemplate.setReturnsCallback(messgae->{
System.out.println(messgae);
});
Map<String,Object> message=new HashMap<>();
message.put("product_id",10);
message.put("num",50);
message.put("price",600);
rabbitTemplate.convertAndSend(
RabbitConfiguration.exchange_name01, // 交换机名称
"das", // routingKey
JSON.toJSONString(message));//要发送的消息
}
3、保证消息到达消费者的可靠性
开启手动确认模式:
spring:
rabbitmq:
listener:
simple:
acknowledge-mode: manual # 使用手动确认模式
最后在手动确认channel.basicNack。可以选择重新发送
@Component
public class MyListener {
@RabbitListener(queues = {"springboot-topic-queue01"})
public void message(Message message, Channel channel) throws Exception{
//接受消息
System.out.println(message.getBody());
try {
System.out.println("业务处理");
// 没有出现异常,手动确认该消息,消息队列会删除该消息
channel.basicAck(
/// 获取消息的传送标签,queue使用该标签进行确认消息
message.getMessageProperties().getDeliveryTag(),
false // 是否把之前的消息全都确认。
);
}catch (Exception e){
// 如果出现异常,不确认该消息
channel.basicNack(
message.getMessageProperties().getDeliveryTag(),
false, // 是否确认多条
false // 是否重新发送
);
}
}
}