首先,我们需要知道,Rabbit本身是不支持延时队列的。但是,它有一个死信投递机制,可以曲线救国来实现我们想要的延时效果
所谓死信,是指某个队列中的消息未被正常消费,既被标记为死信。未正常消费情况可能如下:
- 消费者使用basic.reject或 basic.nack将requeue参数设置为false来否定该消息(https://www.rabbitmq.com/confirms.html)
- 该消息超时未被消费(https://www.rabbitmq.com/ttl.html)
- 消息被删除,因为其队列超过了长度限制 (https://www.rabbitmq.com/maxlength.html)
(以上摘自官方文档)
重点是,Rabbit可以为队列指定 死信交换机 和 死信RouteKey 参数,那么当该队列产生死信后,Rabbit便会自动将死信投递到所指定的交换机,通过RouteKey再到其它队列
利用该机制,设想:
- 建立A-E交换机和A-Q队列,并相互绑定
- 建立B-E交换机和B-Q队列,并相互绑定,RouteKey为B-Key
- 设置A-Q的消息超时时间为X毫秒(想要延时多少就设置多少),死信交换机为B-E,死信RouteKey为B-Key
- 开启消费者,指定消费队列为B-Q
- 生产者通过A-E发送消息到A-Q,因为A-Q没有任何消费者,X毫秒后,消息将变为死信,由MQ自动投递到B-E。B-E通过B-Key发送信息到B-Q,此时消费者收到信息,开启消费逻辑
通过以上过程,我们便可实现延时队列的效果啦~
以上步骤,3是本文的重点,此处对应的三个参数key分别为:
x-message-ttl :消息超时时间,单位为毫秒
x-dead-letter-exchange : 死信交换机
x-dead-letter-routing-key:死信RouteKey
web端操作截图如下(十分钟超时):
至此,一个延时队列就实现了,经实践,运行稳定~