什么是消费端的限流?
假设一个场景,首先,我们Rabbitmq服务器有上万条未处理的消息,我们随便打开一个消费者客户端,会出现下面情况:
巨量的消息瞬间全部推送过来,但是我们单个客户端无法同时处理这么多数据!
RabbitMQ提供了一种qos (服务质量保证)功能,即在非自动确认消息的前提下,如果一定数目的消息(通过基于consume或者channel设置Qos的值)未被确认前,不进行消费新的消息。
1 | void BasicQos(uint prefetchSize, ushort prefetchCount, bool global); |
- prefetchSize:0
- prefetchCount:会告诉RabbitMQ不要同时给一个消费者推送多于N个消息,即一旦有N个消息还没有ack,则该consumer将block掉,直到有消息ack
- global: true\false 是否将上面设置应用于channel,简单点说,就是上面限制是channel级别的还是consumer级别
注:prefetchSize和global这两项,rabbitmq没有实现,暂且不研究prefetch count在no ask= false的情况下生效,即在自动应答的情况下这两个值是不生效的。并且千万不要使用AutoACK。一定要使用手动ack
消费端的手工ACK和NACK
消费端进行消费的时候,如果由于业务异常我们可以进行日志的记录,然后进行补偿!
如果由于服务器宕机等严重问题,那我们就需要手工进行ACK保障,消费端消费成功!
消费端的重回队列
消费端重回队列是为了对没有处理成功的消息,把消息重新会递给Broker!
一般我们在实际应用中,都会关闭重回队列,也就是设置为False。
TTL
- TTL是Time To Live的缩写,也就是生存时间
- RabbitMQ 支持消息的过期时间,在消息发送时可以进行指定
- RabbitMQ 支持队列的过期时间,从消息入队列开始计算,只要超过了队列的超时时间配置,那么消息会自动的清除
死信队列 DLX, Dead-Letter-Exchange
利用DLX,当消息在一个队列中变成死信(dead message)之后,它能被重新publish到另一个Exchange, 这个Exchange就是DLX
- DLX也是一个正常的Exchange,和一-般的Exchange没有区别,它能在任何的队列上被指定,实际上就是设置某个队列的属性。
- 当这个队列中有死信时,RabbitMQ就会 自动的将这个消息重新发布到设置的Exchange_上去,进而被路由到另一个队列。
- 可以监听这个队列中消息做相应的处理,这个特性可以弥补RabbitMQ3.0以前支持的immediate参数的功能。
消息变成死信有以下几种情况:
- 消息被拒绝(basic.reject/basic.nack) 并且requeue=false
- 消息TTL过期
- 队列达到最大长度