RabbitMQ进阶

4.1 消息何如何从

这里主要介绍mandatory和immediate两个参数

4.1.1 mandatory参数

  当mandatory参数设置为true时,交换器无法根据自身当类型和路由键找到一个符合条件的队列,那么RabbitMQ会调用Basic.Return命令将消息返回给生产者,当mandatory为false时,出现上述情形,消息直接丢弃。
  那么生产者如何获取到没有被正确路由到合适队列的消息呢?这时候可以通过调用channel.addReturnListener来添加ReturnListener监听实现。

4.1.2 immediate参数

  当immediate参数设置为true时,如果交换器在将信息路由到队列的时候发现队列上并不存在任何消费者,则这条消息不入队。当路由键匹配的所有队列都没有消费者时,该消息会通过Basic.Return返回给生产者,即不用将消息存入队列而等待消费者了。
  注意:RabbitMQ 3.0版本开始去掉了对 immediate 参数的支持,对此 RabbitMQ 官方解释是: immediate 参数会影响镜像队列的性能 ,增加了 代码复杂性 , 建议采用 TTL 和 DLX 的方法替代。如果发送带 immediate 参数 (immediate 参数设置为 true) 的 Basic.Publish 客户端会报异常。

4.1.3 备份交换器

  备份交换器,应为名称为Alternate Exchange,简称AE;当使用mandtory参数时,需要加入addReturnListener逻辑,代码比较复杂,备份交换器就是了解决这个问题而诞生的,为一个交换器A指定一个备份交换器B,交换器A找不到匹配的队列,就会把该消息发送给交换器B,如果交换器B没有匹配到相应的队列,那么该条消息丢失。当然也可以通过策略的方式实现,当二者同时出现的时候,备份交换器的优先级更高。

  • 在整个消息路由的过程中,如果找不到相关的队列和交换器,RabbitMQ的客户端和服务端都不会报任何异常
  • 备份交换器和mandtory参数一起使用,则mandtory参数无效

4.2 过期时间TTL(Time To Live)

4.2.1 设置消息的TTL

  方法一、通过队列设置,队列中所有的消息都有相同的过期时间,一旦该消息过期,该条消息会立马从队列中抹去 ;
  方法二、单独设置某条消息的TTL:basic.publish()中加入expiration参数,当消息过期的时候不会立马从队列中抹去,因为消息是否过期是在投递给消费者的时候判定的;
如果方法一和方法二同时使用,则取较小的时间作为TTL,队列中的消息一旦超过TTL,就会变成死信(deal message),消费者将无法接收到该消息(这点也不是绝对的);

4.2.2 设置队列的TTL

通过 channel.queueDeclare方法中的x-expires参数

4.3 死信队列

DLX,全称为dead letter exchange,可以称之为死信交换器,也有人称之为死信邮箱,当一个消息在队列中变为死信,那么就会被重新发送到一个交换器中,那么这个交换器就称之为DLX,绑定DLX的队列就称为死信队列;
消息变成死信一般是有一下几种情况:

  • 消息被拒绝,并且requeue参数为false
  • 消息过期
  • 队列达到最大长度

4.4 延迟队列

消息发送到队列后,不希望立马被消费者消费,而是希望过一段时间以后再被消费,这就是延迟队列;常见 的使用场景:

  • 一个订单三十分钟未支付,然后进入其他处理程序
  • 用户设定一个时间远程开启家里的电器
    事实上,RabbitMQ并没有直接支持延迟队列,但是我们可以通过TTL+DLX来实现。

4.5 优先级队列

队列可以有优先级,队列中的消息也可以有优先级,队列中消息的优先级不能高于队列的优先级,只有当存在消息堆积当的时候,设置优先级才有意义,因为如果消费速度大于生产速度,其实消息都会被立马消费,设置优先级也就没有什么意义了。

4.6 RPC实现

是为了解决回调队列的问题,具体过程如下:
RabbitMQ进阶