RabbitMq生成者消息可靠性投递【精通】
-
生产者的消息可靠性支持的两种方式
- 事务
- confirms
-
开启confirms
设置ConnectionFactory的publisher-confirms="true" 开启确认模式。
-
监听服务器的应答
//2. 定义回调 rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() { /** * * @param correlationData 相关配置信息 * @param ack exchange交换机 是否成功收到了消息。true 成功,false代表失败 * @param cause 失败原因 */ @Override public void confirm(CorrelationData correlationData, boolean ack, String cause) { System.out.println("confirm方法被执行了...."); if (ack) { //接收成功 System.out.println("接收成功消息" + cause); } else { //接收失败 System.out.println("接收失败消息" + cause); //做一些处理,让消息再次发送。 } } });
RabbitMq 监听未找到队列的消息Return【精通】
-
开启return功能
设置ConnectionFactory的publisher-return="true" 开启确认模式。
-
设置生产端需要获取未找到的队列消息内容
//设置交换机处理失败消息的模式,false直接丢掉消息 rabbitTemplate.setMandatory(true);
-
设置监听回调函数
//2.设置ReturnCallBack rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() { /** * * @param message 消息对象 * @param replyCode 错误码 * @param replyText 错误信息 * @param exchange 交换机 * @param routingKey 路由键 */ @Override public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) { System.out.println("return 执行了...."); System.out.println(message); System.out.println(replyCode); System.out.println(replyText); System.out.println(exchange); System.out.println(routingKey); //处理 } });
confirms与return的区别【熟练】
- confirms是生产者到broker之间保障消息的不丢失,return是监听exchange到queue之间消息丢失情况
消费端的消息可靠性消费【精通】
-
监听器实现ChannelAwareMessageListener接口
-
开启手动确认模式(acknowledge)
-
none:自动确认【默认】
-
auto:依据异常信息自动确认
-
manual:手动确认
<rabbit:listener-container connection-factory="connectionFactory" acknowledge="manual" prefetch="1" >
-
-
手动确认消息
-
确认成功
channel.basicAck(消息的唯一ID,是否批量确认)
-
确认失败
channel.basicNack(消息的唯一ID,是否批量确认,是否重新把消息放回队列)
-
@Override
public void onMessage(Message message, Channel channel) throws Exception {
// 消息的ID
long deliveryTag = message.getMessageProperties().getDeliveryTag();
try {
//1.接收转换消息
System.out.println(new String(message.getBody()));
//2. 处理业务逻辑
System.out.println("处理业务逻辑...");
int i = 3/0;//出现错误
//3. 手动签收
channel.basicAck(deliveryTag,true);
} catch (Exception e) {
//e.printStackTrace();
//4.拒绝签收
/*
第三个参数:requeue:重回队列。如果设置为true,则消息重新回到queue,broker会重新发送该消息给消费端
*/
channel.basicNack(deliveryTag,true,false);
//channel.basicReject(deliveryTag,true);
}
}
设置消费端消息的消费速度【熟练】
-
设置每次拉取消息最大数量(prefetch)
<rabbit:listener-container connection-factory="connectionFactory" acknowledge="manual" prefetch="1" >
-
开启手动消息确认
设置消息的过期时间TTL(精通)
- 单个消息的过期时间只在队列头才生效
- 消息和队列都设置过期时间,时间短的生效
-
设置队列的过期时间
//在创建队列时设置队列消息的ttl过期时间 : x-message-ttl @Configuration public class QueueConfig { @Bean public Queue queue(){ return QueueBuilder.durable("test").withArgument("x-message-ttl",1000).build(); } }
-
设置单个消息的过期时间(消息只在队列头才生效)
// 消息后处理对象,设置一些消息的参数信息 MessagePostProcessor messagePostProcessor = new MessagePostProcessor() { @Override public Message postProcessMessage(Message message) throws AmqpException { //1.设置message的信息 message.getMessageProperties().setExpiration("5000");//消息的过期时间 //2.返回该消息 return message; } }; //消息单独过期 rabbitTemplate.convertAndSend("test_exchange_ttl", "ttl.hehe", "message ttl....",messagePostProcessor);
死信相关概念【精通】
-
定义:
- 死信:被服务器即将丢弃的消息
- 死信队列:存储死信消息的队列(是一个普通队列)
- 死信交换机:死信队列绑定的交换机(是一个普通的交换机)
-
死信产生的条件:
- 队列满了
- 消费者拒绝接受(requeue=false)
- 消息TTL过期
-
使用:
-
在队列上配置死信交换机信息即可
x-dead-letter-exchange:交换机名称 x-dead-letter-routing-key:死信发送是的routingkey
-
队列的属性设置【精通】
- x-max-length:设置队列的长度
- x-dead-letter-exchange:交换机名称
- x-dead-letter-routing-key:死信发送是的routingkey
- x-message-ttl:设置队列消息过期时间
延迟队列【精通】
- 在rabbitmq中直接提供延迟队列的功能,但是可以使用TTL过期时间+死信队列的方式来变通实现延迟队列功能