死信队列
DLX, 全称为 Dead-Letter Exchange, 可以称之为死信交换器, 也有人称之为死信邮箱. 当消息在一个队列中变成死信 (dead message) 之后, 它能被重新被发送到另一个交换器中, 这个交换器就是 DLX, 绑定 DLX 的队列就称之为死信队列.
消息变成死信 - 般是由于以下几种情况:
1. 消息被拒绝 (basic.reject 或 basic.nack) 并且 requeue=false.
2. 消息 TTL 过期 [消息由于消息有效期(per-message TTL) 过期]
3. 队列达到最大长度(队列满了, 无法再添加数据到 mq 中)
消息变成死信后, 会被重新投递 (publish) 到另一个交换机上(Exchange), 这个交换机往往被称为 DLX(dead-letter-exchange)"死信交换机", 然后交换机根据绑定规则转发到对应的队列上, 监听该队列就可以被重新消费.
应用场景分析
在定义业务队列的时候, 可以考虑指定一个死信交换机, 并绑定一个死信队列, 当消息变成死信时, 该消息就会被发送到该死信队列上, 这样就方便我们查看消息失败的原因了
死信处理过程
死信处理过程
DLX 也是一个正常的 Exchange, 和一般的 Exchange 没有区别, 它能在任何的队列上被指定, 实际上就是设置某个队列的属性.
当这个队列中有死信时, RabbitMQ 就会自动的将这个消息重新发布到设置的 Exchange 上去, 进而被路由到另一个队列.
生产者 --> 消息 --> 交换机 --> 队列 --> 变成死信 --> DLX 交换机 -->队列 --> 监听 --> 消费者
路由死信消息
死信消息将被队列的死信交换机路由到其他队列, 在路由时有两种情况:
1. 使用在声明队列时指定的死信路由关键字
2. 没有设置时, 使用消息自身原来的路由关键字
例如, 如果你使用 foo 作为路由关键字发送了一条消息到交换机, 当消息成为死信后, 它使用 foo 作为路由关键字被发送到队列的死信交换机. 如果队列在声明时指定 "x-dead-letter-routing-key" 的值为 bar, 那么消息被发送到死信交换机时将会使用 bar 作为路由关键字.
注意, 如果队列没有设置死信路由关键字, 那消息被死信路由时将会使用它自身的原始路由关键字. 这包含了 CC 和 BCC 头参数设置的路由关键字.
当死信消息被重新发送时, 消息确认机制也会在内部被开启, 因此, 在原始队列删除这条消息之前, 消息最终到达的队列 - 死信队列必须确认该消息. 换句话说, 发送队列在接收到死信队列的确认消息之前不会删除原始消息. 注意, 如果在特殊情况下服务器宕机, 那么同样的消息将会在原始队列和死信队列中同时出现.
消息的死信路由可能会形成一个循环. 比如, 一个队列的死信的消息没有使用指定的死信路由关键字被发送到默认的交换机时. 消息在整个循环 (消息到达同一个队列两次) 中没有被拒绝, 那么消息将被丢弃.
对于 RabbitMQ 来说, DLX 是个非常有用的特性. 在消息不能够被消费者正常消费 (消息被拒绝: basic.reject 或 basic.nack) 的情况下, 消息会被放在死信队列中, 因此分析程序可以借助分析死信队列的消息来改善和优化系统.
来源: http://www.bubuko.com/infodetail-3259153.html