RabbitMQ - 高级特性
目录
1. 高级特性
1.1 消息的可靠投递
在使用RabbitMQ
的时候,作为消息发送方希望杜绝任何消息丢失或者投递失败场景。RabbitMQ
为我们提供了两种方式用来控制消息的投递可靠性模式。
confirm
- 确认模式return
- 退回模式
rabbitmq
- 整个消息投递的路径为:
producer --> rabbitmq broker --> exchange --> queue --> consumer
- 消息从
producer --> exchange
投递失败则会返回一个confirmCallback
。 - 消息从
exchange --> queue
投递失败则会返回一个returnCallback
。
我们将利用这两个callback
控制消息的可靠性投递
1.1.1 确认模式
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit.xsd ">
<!-- 加载配置文件 -->
<context:property-placeholder location="classpath:properties/rabbitmq.properties"/>
<!-- 定义 rabbitmq connectionFactory -->
<rabbit:connection-factory id="connectionFactory"
host="${rabbitmq.host}"
port="${rabbitmq.port}"
username="${rabbitmq.username}"
password="${rabbitmq.password}"
virtual-host="${rabbitmq.virtual-host}"
publisher-confirms="true"
publisher-returns="true" />
<!-- 定义管理交换机、队列 -->
<rabbit:admin connection-factory="connectionFactory"/>
<!-- 定义 rabbitTemplate 对象操作可以在代码中方便发送消息 -->
<rabbit:template id="rabbitTemplate" connection-factory="connectionFactory"/>
<!-- 消息可靠性投递 - 生产端 -->
<rabbit:queue id="test_queue_confirm" name="test_queue_confirm"/>
<rabbit:direct-exchange name="test_exchange_confirm">
<rabbit:bindings>
<rabbit:binding queue="test_queue_confirm" key="confirm"></rabbit:binding>
</rabbit:bindings>
</rabbit:direct-exchange>
</beans>
- 消息从
producer --> exchange
则会返回一个confirmCallback
。
/**
* 生产者
*
* @author murphy
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/spring/spring-rabbitmq.xml")
public class ProducerTest {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 消息可靠性投递
* 确认模式
* 1. 确认模式开启:ConnectionFactory中开启publisher-confirms="true"
* 2. 在rabbitTemplate定义ConfirmCallBack回调函数
*/
@Test
public void testConfirm() {
// 定义回调
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
/**
* @param correlationData 相关配置信息
* @param ack exchange交换机 是否成功收到了消息。true 成功,false代表失败
* @param cause 失败原因
*/
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
System.out.println("Do Confirm.");
if (ack) {
// 接收成功
System.out.println("Receiving Successful! " + cause);
} else {
// 接收失败
System.out.println("Failed! " + cause);
// 业务处理 - 重发消息...
}
}
});
// 3. 发送消息
// - 失败案例 - 消息无法发送
rabbitTemplate.convertAndSend("test_exchange_confirm1","confirm","Message Confirm.");
// - 成功案例
rabbitTemplate.convertAndSend("test_exchange_confirm","confirm","Message Confirm.");
}
}
1.1.2 退回模式
- 消息从
exchange --> queue
投递失败则会返回一个returnCallback
/**
* 回退模式: 当消息发送给Exchange后,Exchange路由到Queue失败是 才会执行 ReturnCallBack
* 步骤:
* 1. 开启回退模式:publisher-returns="true"
* 2. 设置ReturnCallBack
* 3. 设置Exchange处理消息失败的模式:setMandatory
*
* 如果消息没有路由到Queue,则丢弃消息(默认)
* 如果消息没有路由到Queue,返回给消息发送方ReturnCallBack
*/
@Test
public void testReturn() {
// 设置交换机处理失败消息的模式 - false则直接丢弃消息,不进入回调 / true进入回调函数
rabbitTemplate.setMandatory(true);
// 2.设置ReturnCallBack
rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
/**
*
* @param message - 消息对象
* @param replyCode - 错误码
* @param replyText - 错误信息
* @param exchange - 交换机
* @param routingKey - 路由键
*/
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
System.out.println("Do ...");
System.out.println(message);
System.out.println(replyCode);
System.out.println(replyText);
System.out.println(exchange);
System.out.println(routingKey);
// 业务处理 - 重新发送
}
});
// 3. 发送消息
rabbitTemplate.convertAndSend("test_exchange_confirm","confirm - Wrong","Message Confirm.");
}
1.2 Consumer Ack
ack
指Acknowledge
,确认。 表示消费端收到消息后的确认方式。 有三种确认方式:
- 自动确认:
acknowledge="none"
- 手动确认:
acknowledge="manual"
- 根据异常情况确认:
acknowledge="auto"
(这种方式使用麻烦,不作讲解)
其中自动确认是指,当消息一旦被Consumer
接收到,则自动确认收到,并将相应message
从RabbitMQ
的消息缓存中移除。但是在实际业务处理中,很可能消息接收到,业务处理出现异常,那么该消息就会丢失。如果设置了手动确认方式,则需要在业务处理成功后,调用channel.basicAck()
,手动签收,如果出现异常,则调用channel.basicNack()
方法,让其自动重新发送消息。
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.