1、死信队列
1.1消息什么时候变为死信(dead-letter)
消息被否定接收,消费者使用basic.reject 或者 basic.nack并且requeue 重回队列属性设为false。
消息在队列里得时间超过了该消息设置的过期时间(TTL)。
消息队列到达了它的最大长度,之后再收到的消息。
1.2死信队列的原理
当一个消息再队列里变为死信时,它会被重新publish到另一个exchange交换机上,这个exchange就为DLX。因此我们只需要在声明正常的业务队列时添加一个可选的"x-dead-letter-exchange"参数,值为死信交换机,死信就会被rabbitmq重新publish到配置的这个交换机上,我们接着监听这个交换机就可以了。
1.3 代码实现
引入amqp依赖
声明交换机,队列
声明一个类用于发送带过期时间的消息
编写一个类用于消费消息
编写Controller调用发送消息方法测试结果
配置文件application.properties
启动项目,打开rabbitmq控制台,可以看到交换机和队列已经创建好。
在浏览器中请求http://localhost:4399/send?msg=hello&time=5,从控制台的输出来看,刚好5s后接收到消息。
1.4死信队列的一个小注意点
当我往死信队列中发送两条不同过期时间的消息时,如果先发送的消息A的过期时间大于后发送的消息B的过期时间时,由于消息的顺序消费,消息B过期后并不会立即重新publish到死信交换机,而是会等到消息A过期后一起被消费。
依次发送两个请求http://localhost:4399/send?msg=消息A&time=30和http://localhost:4399/send?msg=消息B&time=10,消息A先发送,过期时间30S,消息B后发送,过期时间10S,我们想要的结果应该是10S收到消息B,30S后收到消息A,但结果并不是,控制台输出如下:
消息A30S后被成功消费,紧接着消息B被消费。因此当我们使用死信队列时应该注意是否消息的过期时间都是一样的,比如订单超过10分钟未支付修改其状态。如果当一个队列各个消息的过期时间不一致时,使用死信队列就可能达不到延时的作用。这时候我们可以使用延时插件来实现这需求。
2 、延时插件
RabbitMQ Delayed Message Plugin是一个rabbitmq的插件,所以使用前需要安装它,可以参考的GitHub地址:https://github.com/rabbitmq/rabbitmq-delayed-message-exchange
2.1如何实现
安装好插件后只需要声明一个类型type为"x-delayed-message"的exchange,并且在其可选参数下配置一个key为"x-delayed-typ",值为交换机类型(topic/direct/fanout)的属性。
声明一个队列绑定到该交换机
在发送消息的时候消息的header里添加一个key为"x-delay",值为过期时间的属性,单位毫秒。
代码就在上面,配置类为DMP开头的,发送消息的方法为send2()。
启动后在rabbitmq控制台可以看到一个类型为x-delayed-message的交换机。
继续在浏览器中发送两个请求http://localhost:4399/send2?msg=消息A&time=30和http://localhost:4399/send2?msg=消息B&time=10,控制台输出如下,不会出现死信队列出现的问题:
死信交换机官网介绍:https://www.rabbitmq.com/dlx.html
延时插件GitHub:https://github.com/rabbitmq/rabbitmq-delayed-message-exchange
领取专属 10元无门槛券
私享最新 技术干货