赞
踩
消息的可靠传输是指消息从Producer发送到Broker,再到Consumer被消费的整个过程中,要确保消息不丢失,如果出现消息丢失的情况,系统也要能发现,并执行一些补偿措施,而不是消息丢了都不知道,石沉大海。
如图,消息从Producer发送到Broker再到Consumer被消费的整个传输过程中,因为网络中断等原因,可能会造成消息的丢失,出现消息丢失的情况有以下几种:
1、Producer将消息发送到交换机的路上,因为网路中断等原因,消息丢失;
2、消息到达了交换机,但是交换机根据路由规则如果找不到匹配的queue,消息也会被抛弃;
3、消息发送到Broker后会存放在内存中(没有开启持久化的情况下),如果Consumer还没来得及消费,Broker挂掉了,那么消息也会丢失;
4、默认情况下,RabbitMQ开启的是自动确认autoack,即Consumer收到消息还没有处理时,就会返回一个确认应答ack,Broker收到ack,则认为消息已消费成功,会将该消息从队列中删除。如果Consumer在返回ack后宕机或者在处理消息时发生异常,就会造成消息丢失;
要保证消息可靠传输,就要解决上面的几个问题,下面我们来看一下怎么解决这些问题。
1、生产者将消息发送到交换机的路上,消息丢失怎么办?
一般有两种解决方案:
① 开启事务,Producer发送消息时开启事务,如果发生异常事务回滚,但开启事务就意味着降低性能,尤其在高并发环境,慎用,本文demo不用这种方法!
② 开启生产者confirm机制,在SpringBoot中,在application.yml配置文件中设置spring.rabbitmq.publisher-confirm-type=correlated,生产类实现RabbitTemplate.ConfirmCallback接口,重写confirm方法,不管消息是否成功发送到交换机,都会回调confirm方法,可以在这个方法里做判断处理。
2、消息到达了交换机,但是没有找到匹配的队列造成的消息丢失怎么应对?
SpringBoot中,在application.yml配置文件中设置spring.rabbitmq.publisher-returns=true,生产者类实现RabbitTemplate.ReturnCallback接口,重写returnedMessage方法,在交换机没有找到匹配队列时会回调returnedMessage方法,可在这个方法内做重试补偿。如果找到了匹配队列,就不再回调这个方法。
3、消息到达Broker后会暂存在内存中,如果Consumer还没来得及消费,Broker挂掉了,导致的消息丢失问题怎么解决?
设置持久化,以保证即使Broker挂掉,服务重启后消息依然会恢复,
① 将Exchange设置为持久化的;
② 将Queue设置为持久化的;
③ 将message设置为持久化的。
但这里还有个问题,设置了持久化的消息存入Broker之后,还需要一段时间才能存入磁盘(虽然很短,但不能忽视),因为Broker并不会为每条消息都实时同步存盘,如果这个很短的时间内发生宕机、异常、重启等情况,消息也会丢失,解决办法是引入"RabbitMQ的镜像队列"(RabbitMQ集群,Master挂了Slave会换上去充当Master)。
4、Consumer宕机或处理消息时发生异常导致的消息丢失怎么应对?
关闭autoack,开启手动ack(将autoAck参数为false)。消费者在处理完成后再发送ack给Broker,Brok
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。