RabbitMQ提供了publisher confirm机制来避免消息发送到MQ过程中丢失。这种机制必须给每个消息指定一个唯一ID。消息发送到MQ以后,会返回一个结果给发送者,表示消息是否处理成功。
返回结果有两种方式:
-
publisher-confirm,发送者确认
-
消息成功投递到交换机,返回ack
-
消息未投递到交换机,返回nack
-
-
publisher-return,发送者回执
-
消息投递到交换机了,但是没有路由到队列。返回ACK,及路由失败原因。
-
开启消息回调要配置相应的application,
rabbitmq:
publisher-confirm-type: correlated
publisher-returns: true
template:
mandatory: true
定义return回调,查看有没有发送到交换机成功
@Slf4j
@Configuration
public class CommonConfig implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
RabbitTemplate rabbitTemplate = applicationContext.getBean(RabbitTemplate.class);
rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
// 投递失败,记录日志
log.info("消息发送失败,应答码{},原因{},交换机{},路由键{},消息{}",
replyCode, replyText, exchange, routingKey, message.toString());
// 如果有业务需要,可以重发消息
});
}
}
定义ConfirmCallback,确认是否投递到队列
CorrelationData correlationData = new CorrelationData();
correlationData.getFuture().addCallback(result ->{
if(result.isAck()) {
log.info("消息投递成功:" + correlationData.getId());
} else {
log.info("消息投递失败:" + result.getReason());
}
}, ex -> {
log.info("消息发送异常:" + ex.getMessage());
});
用法如下:
rabbitTemplate.convertAndSend("directExchange","direct",msg,correlationData);
消息回调能让代码更清楚的知道报错原因,还是很值得学习的。