文章目录
1. 确认消息种类
RabbitMQ的消息确认有两种:
-
一种是消息发送确认
- 发送消息确认又分两种:
- 生产者将消息发送给交换器确认;
- 交换器传递给队列确认;
- 发送消息确认又分两种:
-
第二种是消费接收确认。
确认消费者是否成功消费了队列中的消息。
2. 消息发送确认
2.1 生产者将消息发送给交换器确认ConfirmCallback
通过实现ConfirmCallBack接口,消息发送到交换器Exchange后触发回调。
- 定义配置类
package com.es.rabbitmq;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* 用来确认生产者将消息发送给交换器
*
* @author wql
* @date 2021/11/14 8:43
*/
@Component
public class RabbitConfirmCallbackConfig implements RabbitTemplate.ConfirmCallback {
@Autowired
private RabbitTemplate rabbitTemplate;
@PostConstruct
public void init() {
// 指定ConfirmCallBack
rabbitTemplate.setConfirmCallback(this);
}
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
System.out.println("消息唯一标识 = " + correlationData);
System.out.println("确认结果 = " + ack);
System.out.println("失败原因 = " + cause);
}
}
- yaml配置规则
spring:
rabbitmq:
publisher-confirm-type: correlated
2.2 交换器传递给队列确认ReturnCallback
通过实现ReturnCallback接口,如果消息从交换器发送到对应队列失败时触发,比如根据发送消息时指定的routingKey找不到队列时会触发
- 定义配置类
package com.es.rabbitmq;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* 用来确认交换器传递给队列的过程中消息是否成功投递
*
* @author wql
* @date 2021/11/14 8:43
*/
@Component
public class RabbitReturnCallbackConfig implements RabbitTemplate.ReturnCallback {
@Autowired
private RabbitTemplate rabbitTemplate;
@PostConstruct
public void init() {
// 指定ConfirmCallBack
rabbitTemplate.setReturnCallback(this);
}
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
System.out.println("消息主体 message = " + message);
System.out.println("消息主体 replyCode = " + replyCode);
System.out.println("描述 replyText = " + replyText);
System.out.println("消息使用的交换机 exchange = " + exchange);
System.out.println("消息使用的路由键 routingKey = " + routingKey);
}
}
- yaml配置规则
spring:
rabbitmq:
publisher-returns: true
3. 消息接收确认
- AcknowledgeMode.
NONE
:不确认 - AcknowledgeMode.
AUTO
:自动确认 - AcknowledgeMode.
MANUAL
:手动确认
当然也可以通过观察客户端面板未确认消息数来观察
4.总结:
消息发送流程:
- 生产者:消息从生产者生产发送给Broker
- 消息队列:消息在Broker存放(vhost 可以理解为虚拟 broker),如果是镜像复制集群,消息将被复制到其他副本上
- 消费者:消费者从Broker上拉取信息,经过网络传输发送到Consumer
于是就有:
其中在Broker 副本拷贝刷盘的时候,也可能丢失数据,这也属于内存数据丢失原因之一;
如何解决,其实归根结底就是:
- 生产者-> 交换机 需要确认
- 交换机-> 队列 需要确认
- 交换机和队列 需要持久化
- 消费者手动确认