其他分享
首页 > 其他分享> > 【RabbitMQ 笔记】— 死信队列

【RabbitMQ 笔记】— 死信队列

作者:互联网

死信交换器,Dead Letter Exchange,下文简称 DLX。当消息在一个队列中变成死信(Dead Letter)之后,它会被发送到另一个交换器中,这个交换器就是 DLX,绑定 DLX 的队列就称为死信队列。

消息变成死信一般由以下几种情况:

那就先聊聊过期时间

过期时间(TTL)

TTL,全称 time to live。RabbitMQ 里分为消息的过期时间和队列的过期时间

消息的 TTL

有两种方式可以设置消息的过期时间

其实上面两种设置过期时间的方式判定消息是否过期的逻辑也是不一样的,区别如下

队列的 TTL

可以通过 channel.queueDeclare 方法中 x-expires 参数(单位毫秒,不能设置为 0)可以可控制队列被自动删除前未使用状态的时间。未使用定义如下:

死信队列

DLX 也是个普通的交换器,和一般的交换器没有区别。当一个队列存在死信时,RabbitMQ 会把消息发送给 DLX,进而被路由到另一个队列,这个队列就是死信队列。然后可以监听这个队列中的消息进行相应的处理。这个特性与将消息的 TTL 设置为 0 配合使用可以弥补 immediate 参数的功能。

通过 channel.queueDeclare 方法中设置 x-dead-letter-exchange 参数来为队列添加 DLX。也可以为这个 DLX 指定路由键,设置 x-dead-letter-routing-key 参数指定。如果没有指定,则使用原队列的路由键。

具体代码如下

try(Connection connection = ConnectionUtil.getConnection()) {
    Channel channel = connection.createChannel();
    // 创建死信交换器, 死信队列
    channel.exchangeDeclare(DLX, BuiltinExchangeType.FANOUT.getType(), true, false, null);
    channel.queueDeclare(DLX_QUEUE, true, false, false, null);
    channel.queueBind(DLX_QUEUE, DLX, "");
    // 创建 normalExchange
    channel.exchangeDeclare(NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT.getType(), true, false, null);
    Map<String, Object> args = new HashMap<>(2);
    args.put("x-message-ttl", EXPIRE_TIME); // 设置队列消息的过期时间
    args.put("x-dead-letter-exchange", DLX); // 为队列添加死信交换器
    channel.queueDeclare(NORMAL_QUEUE, true, false, false, args);
    channel.queueBind(NORMAL_QUEUE, NORMAL_EXCHANGE, ROUTING_KEY);
    // 发送消息
    byte[] bytes = "dlx message coming!".getBytes();
    channel.basicPublish(NORMAL_EXCHANGE, ROUTING_KEY, MessageProperties.PERSISTENT_TEXT_PLAIN, bytes);
} catch (IOException e) {
    e.printStackTrace();
}

上述代码示意图如下
image

对于 RabbitMQ 来说,DLX 是个很有用的特性,他可以处理异常情况下,消息不能够正常消费(消费者调用了 Basic.Nac 或者 Basic.reject)而被置入死信队列的情况,后续分析程序可以通过消费这个死信队列中的内容来分析当时遇到的异常情况,进而可以进一步优化。另外,DLX 配合 TTL 还可以实现延时队列的功能。

参考

《RabbitMQ实战指南》

标签:队列,RabbitMQ,过期,死信,消息,DLX,channel
来源: https://www.cnblogs.com/tailife/p/16358952.html