这是我参与8月更文挑战的第28天,活动详情查看:8月更文挑战
队列订阅
消费方式
- 通过AMQP的basic.comsume 命令订阅,将信道设置为接收模式。订阅后消费者在消费最近接收的消息后会自动接收下一条消息。
- 只想获取单条消息而不是持续订阅。通过basic.get命令,如果想要获取多条,就执行多条basic.get命令。不建议循环该命令用于实现自动接收,影响Rabbit性能。
订阅机制
如果消息发送到了没人订阅的队列,消息会在队列中等待,直到有消费者订阅了该队列,消息会发送给消费者。
如果队列中有多个消费者,队列将以循环的模式分发消息,每条消息只会发给一个消费者。
确认接收
消费者接收到消息之后,需要发送一个确认接收basic.ack命令告诉Rabbit,Rabbit才会将这条消息删除。
如果消费者接收到消息后没有返回ack命令,消息队列就不会将消息再发给该消费者,会将该消息发送给其他消费者。当有耗时的消息时,需要延迟ack的时间,防止过载。
拒绝消息
收到消息后,想要拒绝
-
断开连接(建立和断开连接会增加rabbit负担)
-
2.00版本及以上,使用basic.reject 命令。
-
当reject的request参数设置为true,RabbitMQ会将消息发送给其他消费者
-
request参数为false,RabbitMQ会将消息直接删除。
-
为什么使用false来代理确认消息?
确认消息也会将消息删除,但是存在一个dead letter队列,会将拒绝并false的消息存放在其中。如果想从中受益,可以使用false。
-
创建队列
使用queue.declare命令创建队列,当消费者已经订阅了一个队列,就无法声明新的队列了,必须先取消订阅,将信道模式改成传输。
当创建队列时需要指定队列名,否则Rabbit会随机名称并在declare响应中返回。
其他有用的参数:
- exclusive— true,队列私有,只有你一个消费者
- auto-delete —当最后一个消费者取消订阅后,该队列就会销毁,配合exclusive用于临时队列。
如果尝试声明一个已存在的队列,Rabbit就会什么都不做。如果想要检测是否存在,将declare的passive选项设置为true,如果存在,返回成功。
谁来创建队列?
一般,消费者创建队列,生产者创建交换机,消费者将队列和交换机绑定。
公平分配
根据轮询策略,如果有个消费者压力很重,但是另一个消费者压力很小,就会浪费效率。
可以通过basicQos(int count)来设置消息的预取数量。
- 如果队列中的数量大于等于预取数量,不会把消息放入队列。
- 如果队列中的数量小于预取数量,那么确认判断哪个消费者现在处于空闲状态,就会将多余的预取数量分配到空闲消费者中。
优点:能减少性能浪费,也能平滑得使新的消费者加入。
-
如何判断预取数量?
假设从RabbitMQ服务端队列取消息、传输消息到消费者耗时为50ms,消费者消费消息耗时4ms,消费者传输确认消息到服务端耗时为50ms。若网络状况、消费者处理速度稳定,则预取数量的最优数值为:(50 + 4 + 50)/4=26个。