一,消息的可靠性投递
生产端可靠性投递
1,保障消息的成功发出
2,保障Broker节点成功接收到信息
3,发送端能收到Broker节点确认应答
4,有消息进行补偿机制。
解决方案一:
1,消息落库,对消息状态进行标记,在发送mq消息前先进行消息记录的落地,然后发送消息到Broker中,当Broker收到消息确认应答后修改消息的状态。如果某个消息没有得到Broker的应答,根据一定策略定时轮询消息进行处理。
缺点:效率不是太高,应该增加一次消息入库。
解决方案二:
消息的延迟投递做二次确认,回调检查。
缺点:稍微复杂也,并且不能100%保证可靠性。
二、Broker确认机制
1.Confirm 消息确认机制是指消息的确认,当生产都投递消息后,如果Broker收到消息,则会给生产者一个反馈。
生产者接收到应答后来确定消息是否正常的发送到了Broker中,这种方式也是消息的可靠性投递的核心保障。生产者是通过监听来得到Broker的消息反馈。需要Channel上开启确认模式:channel.confirmSelect(),并且在channel上增加监听:addConfirmListener.根据具体的结果对消息进行重新发送或记录日志等操作。
2.Return消息机制
Return Listen 主要用于处理一些不可路由的消息。如果我们在发送消息时,当前的Exchange不存在或者指定的路由Key无匹配,这时我们就需要监听这种不可达的消息,使用的就是Return Listen。
Mandatory:如果为true,则监听器会接收到路由不可达的消息,如果为False,那么Broker端自动删除改消息。
三、消费端限流策略
如果Rabbitmq服务器上堆积了上万条未处理的消息,当我们打开一个消费客户端时,会出现巨量消息瞬间推送过来,打夸消费端。当生产端的生产量大于消息端的消费能力时也会出现这个问题。
RabbitMQ提供了一种Qos(服务质量保证)功能,在非自动确认消息的前提下,如果一定数目的消息(通过Consume或者Channel设置Qos的值)未被确认前,Broker不再推送消息给消费者进行消费。
方法(消费端): void basicQos(uint prefetchSize,ushort prefechCount,bool global);
prefetchSize:消息的大小限制(一般我们设置成0,代表不限制,一般都是在生产端做消息大小的限制)
prefetchCount:一次推送来最大的消息数。
global:限流级别,true为Channel级别限制(Rabbitmq并未实现)。false代表consumer级别限制(一般为fase)。
四,消费端ACK与重回队列
手工消息签收有两个选择:ACK(确认,已经处理成功),和NACK(不确认,处理失败),如果返回NACK,Broker会重新投递这个消息。当消息者在一定时间内没有返回ACK,Broker也会再次发送消息到消息端。
channel.basicAck(envelope.getDeliveryTag(),false);
channel.basicNAck(envelope.getDeliveryTag(),false,false);
参1:消息唯一标示,参2:是否批量签收,参3:是否写入重回队列中(添加到队列的末尾端)
消费端的重回队列:消费端处理消息没成功,可以重新投递消息到Broker。实际应该种一般不开启,设置为false.
五、TTL队列/消息
TTL是Time To Live的缩写,也就是生存时间的意思
RabbitMQ 支持消息的过期时间,在消息发送时可以进行指定(消息级别的设置)。同时也支持队列的过期时间,从消息入队列开始计算,只要超过了队列的超时时间设置,那么消息会自动被清理。
六、死信队列DLX(Dead Letter Exchange)
当一个被发送的消息没有被正确消费时,可能让他转发到另一个Exchange上,这个Exchange就是DLX,DLX也是一个正常的Exchange,和一般的Exchange没有区别,它能在任何的队列上被指定,当一个队列中有设置死信队列时,RabbitMq就会自动将非正常消费的消息发送到Dlx队列中,下面几种情况会将消息转发到DLX中:
1.消息被拒签时(basic.reject/basic.nack)并且requeue=false(就是消端将重回队列关闭的情况下),
2.消息TTL过期
3.队列达到最大长度
设置方式: 在队列上加一个参数 arguments.put("x-dead-letter-exchange","dlx.exchange")
第一个参数是固定值,第二个参数是死信队列的名称
七、延迟队列
有些场景下我们需要将消息延迟一段时间后再进行真正的投递出去。比如 支付通知场景。当微信确认用户支付后,会通过回调方式告知下游商户支付状态,如果回调失败,会根据重试策略进行后续的多次延迟回调动作,这时我们就需要延迟队伍的特性去实现。
Rabbit Mq需要安装插件才能使用延迟队列,具体步骤:
1. 下载插件
2. 把下载好的插件放入到指定的目录
3.使用命令启动插件
4.创建延迟类型Exchange,创建队列,绑定队列到Exchange。
5.像普通方式一样发送消息,只不过要在消息的Heades中设置一个属性,就是延迟的时间 (x-delay,5000)