个人理解: rabbitmq发送消息到交换机、队列当中,不希望看到任何消息丢失或者发送失败的情况。所以就需要一种机制来实现发送消息的可靠性,发送者知道发送的消息是否成功,是否被消费。
RabbitMq提供了俩种方式来控制消息的发送可靠性。
1. confirm 确认模式
消息发送到交换机Exchange成功或者失败时, 回调
2. return 退回模式
当消息发送给Exchange后,Exchange路由到Queue失败时处理
confirm模式:在配置文件中配置:
publisher-confirm-type: correlated
在执行rabbitTemplate.send()或者messageProperties.setContentType()前,设置rabbitTemplate.setConfirmCallback,代码:
/**
* 消息发送到交换机Exchange失败时, 回调
* 需要配置 publisher-confirm-type: correlated
*/
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
/**
*
* @param correlationData 相关配置信息
* @param ack exchange交换机是否成功收到 消息,true 成功,false失败
* @param cause 失败原因
*/
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
if (ack) {
System.out.println("发送到交换机成功");
return;
}
System.out.println("发送到交换机失败");
}
});
//fanout模式只往exchange里发送消息。分发到exchange下的所有queue
rabbitTemplate.send("fanoutExchange5", "", new Message(message.getBytes("UTF-8"), messageProperties));
return "message sended : " + message;
发送消息后,如果发送到了fanoutExchange5,ack为true,如果没找到,为false,都要执行confirm方法。
return 回退模式:当消息发送给Exchange后,Exchange路由到Queue失败时
* 1. 如果消息没有路由到queue,默认丢弃消息(false)。
* 2.如果消息没有路由到queue,返回消息到ReturnsCallback(需要设置rabbitTemplate.setMandatory(true)。)
在配置文件中配置:
publisher-returns: true
代码:
/**
* 回退模式:当消息发送给Exchange后,Exchange路由到Queue失败时,才执行setReturnsCallback
*步骤:
* 1. 开启回退模式:publisher-returns: true
* 2. 设置ReturnsCallback
* 3. 设置Exchange处理消息模式:
* 1. 如果消息没有路由到queue,默认丢弃消息(false)。
* 2.如果消息没有路由到queue,返回消息到ReturnsCallback(true)
*/
//设置Exchange处理消息模式
rabbitTemplate.setMandatory(true);
rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
@Override
public void returnedMessage(ReturnedMessage returnedMessage) {
System.out.println("执行了"+returnedMessage);
}
});
//发消息
rabbitTemplate.send("helloWorldqueue", new Message(message.getBytes("UTF-8"), messageProperties));
return "message sended : " + message;
如果没有设置
rabbitTemplate.setMandatory(true)
则为默认配置,丢弃消息。
创建配置类,添加 @Configuration 注解。
package com.fan.testsendupdatell.configs;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
@Slf4j
@Configuration
public class RabbitCallbackConfig implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {
@Bean
RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
rabbitTemplate.setMandatory(true);
rabbitTemplate.setConfirmCallback(this);
rabbitTemplate.setReturnCallback(this);
return rabbitTemplate;
}
// 下边这样写也可以
// @Autowired
// private RabbitTemplate rabbitTemplate;
// @PostConstruct
// public void init() {
// rabbitTemplate.setMandatory(true);
// rabbitTemplate.setReturnCallback(this);
// rabbitTemplate.setConfirmCallback(this);
// }
/**
* 消息发送到交换机Exchange失败时, 回调
* @param correlationData 相关配置信息
* @param ack exchange交换机是否成功收到 消息,true 成功,false失败
* @param cause 失败原因
*/
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
if (!ack) {
log.error("confirm==>发送到broker失败\r\n" +
"correlationData={}\r\n" + "ack={}\r\n" + "cause={}",
correlationData, ack, cause);
} else {
log.info("confirm==>发送到broker成功\r\n" +
"correlationData={}\r\n" + "ack={}\r\n" + "cause={}",
correlationData, ack, cause);
}
}
/**
* 回退模式:当消息发送给Exchange后,Exchange路由到Queue失败时,才执行setReturnsCallback
*步骤:
* 1. 开启回退模式:publisher-returns: true
* 2. 设置ReturnsCallback
* 3. 设置Exchange处理消息模式:
* 1. 如果消息没有路由到queue,默认丢弃消息(false)。
* 2.如果消息没有路由到queue,返回消息到ReturnsCallback(true)
* //设置Exchange处理消息模式 rabbitTemplate.setMandatory(true);
*/
@Override
public void returnedMessage(Message message, int replyCode, String replyText,
String exchange, String routingKey) {
log.info("returnedMessage==> \r\n" + "message={}\r\n" + "replyCode={}\r\n" +
"replyText={}\r\n" + "exchange={}\r\n" + "routingKey={}",
message, replyCode, replyText, exchange, routingKey);
}
}
配置完成后,直接可以发送
rabbitTemplate.send()
自动根据配置执行模式方法。