RabbitMQ 死信队列

死信队列的作用

  使用 RabbitMQ 的时候可能会碰到以下几个问题:

  1. 消费者端调用了 basicNack 或者 basicReject,并且没有进行 requeue,如果没做其他措施的话,这个消息也就丢失了。
  2. 消息在队列的存活时间超过设置的 TTL 时间。
  3. 消息队列的消息数量已经超过最大队列长度。

  以上几个问题都会导致消息丢失,消息丢失的代价可大可小,视自己业务情况而定,有些业务如果消息丢失无所谓的话就不用理睬,相信大部分业务都是不允许丢失的。死信队列的出现就可以解决以上三个问题,当以上三个问题出现时,消息不会丢失,会重新放入死信队列,至于如何处理死信队列中的消息就看自己公司的业务了。

如何配置死信队列

  死信队列其实本身也是普通的队列,只是在逻辑上赋予了它特殊的含义,需要绑定对应的死信交换机,与队列概念一样,也是普通的交换机,赋予了死信的含义。那么整体流程如下:

  1. 创建死信交换机

    image-20210714152844371

  2. 创建死信队列

    image-20210714152945089

  3. 在死信交换机中绑定死信队列与死信交换机

    image-20210714153118816

  4. 创建业务交换机

    image-20210714153143466

  5. 创建业务队列并关联死信交换机与死信队列

    image-20210714153228905

  6. 在业务交换机中绑定业务队列与业务交换机

    image-20210714153256693

以上操作可以在 Web 上操作,亦可在项目中用代码实现。

  步骤 5 中的 x-dead-letter-exchange 指定死信交换机、x-dead-letter-routing-key 指定路由到指定 Queue 的路由 key,一般配置跟 Queue 一样。

  一般情况下会为每一个业务队列都配置一个相对应的死信队列,也可以多个业务队列共用一个死信队列。要注意的是业务队列和死信队列的交换机要区分开。

样例

  配置如下:

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: admin
    password: 123456
    virtual-host: 'example'
    # 生产者 ==>> Exchange 确认方式
    publisher-confirm-type: correlated
    # Exchange ==>> Queue
    publisher-returns: true
    listener:
      simple:
        # ACK 模式,此处选择自动 ACK
        acknowledge-mode: auto
        # 每次处理 100 条消息
        prefetch: 100
        # 决定由于监听器抛出异常而拒绝的消息是否被重新放回队列。默认值为 true,重新放回队列。这里设置为 false,如果多次重试还是异常就转发到死信队列
        default-requeue-rejected: false
        retry:
          # 开启重试
          enabled: true
          # 最大重试 3 次,涵盖当前次
          max-attempts: 3
          # 每次重试间隔时间
          initial-interval: 3000
          # 最大允许重试间隔时间,用来限制 initial-interval。
          max-interval: 10000
          # 下一次重试的时间间隔 = 上次重试时间间隔 * multiplier
          multiplier: 2

  消费者端简单抛个异常:

image-20210714154050624

image-20210714154109810

image-20210714154121044

  最终都跑到死信队列了。

发表评论

电子邮件地址不会被公开。 必填项已用*标注