一、发送端消息确认
(1)publish ===> broker
只要broker收到消息,就会执行 confirmCallback
# 开启发送端消息抵达Broker确认
spring.rabbitmq.publisher-confirms=true
(2)exchange ===> queue
如果exchange有消息没有成功发送至queue,就会执行RuturnCallback,例:routing key错误导致发送消息到队列失败
# 开启发送端消息抵达Queue确认
spring.rabbitmq.publisher-returns=true
# 只要消息抵达Queue,就会异步发送优先回调returnfirm
spring.rabbitmq.template.mandatory=true
(3)RabbitmqConfig
/**
* 定制RabbitTemplate
* 1、服务收到消息就会回调
* 1、spring.rabbitmq.publisher-confirms: true
* 2、设置确认回调
* 2、消息正确抵达队列就会进行回调
* 1、spring.rabbitmq.publisher-returns: true
* spring.rabbitmq.template.mandatory: true
* 2、设置确认回调ReturnCallback
*
* 3、消费端确认(保证每个消息都被正确消费,此时才可以broker删除这个消息)
*
*/
// @PostConstruct //MyRabbitConfig对象创建完成以后,执行这个方法
public void initRabbitTemplate() {
/**
* 1、只要消息抵达Broker就ack=true
* correlationData:当前消息的唯一关联数据(这个是消息的唯一id)
* ack:消息是否成功收到
* cause:失败的原因
*/
//设置确认回调
rabbitTemplate.setConfirmCallback((correlationData,ack,cause) -> {
System.out.println("confirm...correlationData["+correlationData+"]==>ack:["+ack+"]==>cause:["+cause+"]");
});
/**
* 只要消息没有投递给指定的队列,就触发这个失败回调
* message:投递失败的消息详细信息
* replyCode:回复的状态码
* replyText:回复的文本内容
* exchange:当时这个消息发给哪个交换机
* routingKey:当时这个消息用哪个路邮键
*/
rabbitTemplate.setReturnCallback((message,replyCode,replyText,exchange,routingKey) -> {
System.out.println("Fail Message["+message+"]==>replyCode["+replyCode+"]" +
"==>replyText["+replyText+"]==>exchange["+exchange+"]==>routingKey["+routingKey+"]");
});
}
二、消费端消息确认
(1) queue ===> consumer
默认是ack,consumer只要拿到消息就会自动确认,服务端就会删除queue中的消息,如果业务出现问题只有部分消息签收成功,剩余未签收的消息也会删除,为了能保存消息,需要设置为客户端手动确认签收
#手动签收ack
spring.rabbitmq.listener.simple.acknowledge-mode=manual
(2) 签收消息channel.basicAck(自增id,是否批量)
设置手动ack签收之后,如果有消息没有签收(签收失败),会显示未签收
自增id:2,签收完成2
自增id:4,签收完成4
如果服务重启,未签收的消息就会加入queue重新发送:Unacked ===> Ready
(3)拒签 channel.basicNack(自增id,是否批量,是否重新加入队列)
requeue=true 拒签的消息会加入queue重新发送
requeue=false 拒签的消息会直接丢弃,不会加入队列重新发送
@RabbitListener(queues = {"durunwu.queue"})
@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {
@RabbitHandler
public void msgListener2(Message message, OrderItemEntity orderItemEntity, Channel channel) throws IOException {
//顺序id,channel内按顺序自增了
long deliveryTag = message.getMessageProperties().getDeliveryTag();
if (deliveryTag % 2 == 0){
//basicAck(long deliveryTag, boolean multiple)
//channel内按顺序自增
channel.basicAck(deliveryTag,false);
System.out.println("自增id:"+deliveryTag+",签收完成" + orderItemEntity.getId());
}else {
//basicNack(long deliveryTag, boolean multiple, boolean requeue)
channel.basicNack(deliveryTag,false,true);
System.out.println("自增id:"+deliveryTag+",拒签"+orderItemEntity.getId());
}
}
}
控制台打印文章来源:https://www.toymoban.com/news/detail-637645.html
自增id:1,拒签1
自增id:2,签收完成2
自增id:3,拒签3
自增id:4,签收完成4
自增id:5,拒签5
自增id:6,签收完成1
自增id:7,拒签3
自增id:8,签收完成5
自增id:9,拒签3
自增id:10,签收完成3
(4)整合业务
如何签收?
业务完成 ===> 签收:basicAck(deliveryTag, false)
业务未完成 ===> 拒签:basicNack(deliveryTag, false, true)文章来源地址https://www.toymoban.com/news/detail-637645.html
到了这里,关于rabbitmq消息确认机制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!