首先确定消息可能在哪些位置丢失---不同的位置可以有不同的解决方案。
1.从生产者--交换机
2.从交换机--队列
3.队列里面
4.消费者消费时
1.保证消息从生产者到交换机
comfirm确认机制
* 1. 手动开启确认机制spring.rabbitmq.publisher-confirm-type=correlated
* 2. 为rabbitTemplate设置确认回调函数
/**
* 1. 手动开启确认机制spring.rabbitmq.publisher-confirm-type=correlated
* 2. 为rabbitTemplate设置确认回调函数
*/
@Test
public void testConfirm(){
//为rabbitTemplate设置确认回调函数
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
//不管是否到达交换机 都会触发该方法
@Override
public void confirm(CorrelationData correlationData, boolean b, String s) {
if(b==false){
//根据自己的业务完成相应的代码
System.out.println("消息发送失败---订单回滚");
}
}
});
rabbitTemplate.convertAndSend("testX2","a","Hello Springboot2");
}
2 保证消息可以从交换机到队列
returning机制: 如果消息无法到达队列,则会触发returning机制。如果能从交换机到队列则不会触发returning机制。
默认rabbitMQ不开启该机制。
* 1.开启returning机制 spring.rabbitmq.publisher-returns=true
* 2.为rabbitTemplate设置returning回调函数
/**
* 1.开启returning机制 spring.rabbitmq.publisher-returns=true
* 2.为rabbitTemplate设置returning回调函数
*/
@Test
public void testReturning(){
rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
//该方法只要从交换机到队列失败时才会触发
@Override
public void returnedMessage(ReturnedMessage returned) {
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~");
}
});
rabbitTemplate.convertAndSend("testX","ax","Hello Springboot2");
}
3 如何保证消息在队列
-
队列持久化--->
-
搭建rabbitmq集群--保证高可用
4 消费者可靠的消费消息
1.修改为手动确认模式
#改为自动确认spring.rabbitmq.listener.simple.acknowledge-mode=manual
2.当业务处理完毕后在确认消息给队列让其删除该消息
@RabbitListener(queues = "test01")
public void test01(Message message, Channel channel){
byte[] body = message.getBody();
long deliveryTag = message.getMessageProperties().getDeliveryTag();
System.out.println("接受到消息"+new String(body));
try {
System.out.println("处理业务代码");
System.out.println("业务处理完毕");
//手动确认---队列会把该信息移除。
//long deliveryTag,消息的标记
// boolean multiple: 是否把之前没有确认的消息以前确认掉。
channel.basicAck(deliveryTag,true);
}catch (Exception e){
//1.让队列在给我发一次。
//long deliveryTag, boolean multiple,
// boolean requeue: 继续发给我 还是直接
try {
channel.basicNack(deliveryTag,true,true);
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
如何保证消息的可靠性。
-
设置confirm和returning机制
-
设置队列和交互机的持久化
-
搭建rabbitMQ服务集群
-
消费者改为手动确认机制。
5.如何限制消费者消费消息的条数
-
设置消费者消费消息的条数
-
消费者端必须为手动确认模式。
#设置消费者最多一次消费的消息个数spring.rabbitmq.listener.simple.prefetch=5
@RabbitListener(queues = "test03")
public void test03(Message message, Channel channel) throws IOException {
byte[] body = message.getBody();
System.out.println("消息的内容:"+new String(body));
// channel.basicAck(message.getMessageProperties().getDeliveryTag(),true);
}
6.设置过期时间
TTL:time to live
可以为整个队列设置也可以单独为某条信息设置
7.单独为消息设置过期时间
@Test
public void test02() {
MessagePostProcessor messagePostProcessor=new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
message.getMessageProperties().setExpiration("10000");
return message;
}
};
rabbitTemplate.convertAndSend("testX", "d", "Hello Springboot",messagePostProcessor);
}