RabbitMQ总结-队列订阅

170 阅读3分钟

这是我参与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个。