10:39:00:807 INFO 14876 — [ntContainer#0-1] c.i.mq.listener.SpringRabbitListener : 消费者接收到了dl.queue的延迟消息
`总结:`
1.消息超时的两种方式是?
* 1)给队列设置ttl属性,进入队列后超过ttl时间的消息变为死信
* 2)给消息设置ttl属性,队列接收到消息超过ttl时间后变为死信
* 3)两者共存时,以时间短的ttl为准
2.如何实现发送一个消息20秒后消费者才收到消息?
* 1)给消息的目标队列指定死信交换机
* 2)消费者监听与死信交换机绑定的队列
* 3)发送消息时给消息设置ttl为20秒
### 3.3 延迟队列 Delay Queue
利用TTL结合死信交换机,我们实现了消息发出后,消费者延迟收到消息的效果。这种消息模式就称为延迟队列(Delay Queue)模式。
延迟队列的使用场景包括:
* 延迟发送短信
* 用户下单,如果用户在15 分钟内未支付,则自动取消
* 预约工作会议,20分钟后自动通知所有参会人员
#### 3.3.1 安装DelayExchange插件
官方的安装指南地址为:https://blog.rabbitmq.com/posts/2015/04/scheduling-messages-with-rabbitmq
上述文档是基于linux原生安装RabbitMQ,然后安装插件。
因为我们之前是基于Docker安装RabbitMQ,所以下面我们会讲解基于Docker来安装RabbitMQ插件。
1. 下载插件
RabbitMQ有一个官方的插件社区,地址为:https://www.rabbitmq.com/community-plugins.html
其中包含各种各样的插件,包括我们要使用的DelayExchange插件:
大家可以去对应的GitHub页面下载3.8.9版本的插件,地址为https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases/tag/3.8.9这个对应RabbitMQ的3.8.5以上版本。
课前资料也提供了下载好的插件:`rabbitmq_delayed_message_exchange-3.8.9-0199d11c.ez`
2. 上传插件
因为我们是基于Docker安装,所以需要先查看RabbitMQ的插件目录对应的数据卷。如果不是基于Docker的同学,请参考第一章部分,重新创建Docker容器。
我们之前设定的RabbitMQ的数据卷名称为`mq-plugins`,所以我们使用下面命令查看数据卷:
docker volume inspect mq-plugins
可以得到下面结果:
[root@iZ2ze1r1nnqykr8zfme6cjZ tmp]# docker volume inspect mq-plugins
[
{
“CreatedAt”: “2024-03-26T11:02:23+08:00”,
“Driver”: “local”,
“Labels”: null,
“Mountpoint”: “/var/lib/docker/volumes/mq-plugins/_data”,
“Name”: “mq-plugins”,
“Options”: null,
“Scope”: “local”
}
]
接下来,将插件上传到这个目录即可:`Mountpoint`目录下
3. 安装插件
最后就是安装了,需要进入MQ容器内部来执行安装。我的容器名为`mq`,所以执行下面命令:
docker exec -it mq bash
执行时,请将其中的 `-it` 后面的`mq`替换为你自己的容器名.
进入容器内部后,执行下面命令开启插件:
rabbitmq-plugins enable rabbitmq_delayed_message_exchange
结果如下:
Enabling plugins on node rabbit@mq1:
rabbitmq_delayed_message_exchange
The following plugins have been configured:
rabbitmq_delayed_message_exchange
rabbitmq_management
rabbitmq_management_agent
rabbitmq_prometheus
rabbitmq_web_dispatch
Applying plugin configuration to rabbit@mq1…
The following plugins have been enabled:
rabbitmq_delayed_message_exchange
started 1 plugins.
最后通过`exit`命令退出容器
4. 使用插件
DelayExchange插件的原理是对官方原生的Exchange做了功能的升级:
* 将DelayExchange接受到的消息暂存在内存中(官方的Exchange是无法存储消息的)。
* 在DelayExchange中计时,超时后才投递消息到队列中
1)如何创建一个延迟交换机?
在RabbitMQ的管理平台声明一个DelayExchange:
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a422215e37c54483a4404870f4d55120.png)
2)如何发送一个延迟消息?
消息的延迟时间需要在发送消息的时候指定:
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/454a4016979c42058c46d4c7e8d4ed90.png)
#### 3.3.2 SpringAMQP使用延迟队列插件
`演示:在消费者consumer声明延迟交换机,有两种方式:`
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/0667f0f04d334e4c9d45c27d438f6543.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/288655f271f84bcfaaba8b4eb78e41a9.png)
`然后在发布者publisher发送一个延迟消息,添加一个x-delay`
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/56ec0f89d8854ec78dfe2988e40ea2cb.png)
测试发现报错,解释:理论上消息到达了交换机会立即将消息转发出去,而延迟交换机会将消息保存下来,等时间到后再转发消息,因此在等待的时间会返回给发布者一个未到达队列的错误。
生产者的日志:
11:25:22:536 INFO 5756 — [ main] cn.itcast.mq.spring.SpringAmqpTest : 发送消息成功
11:25:22:552 ERROR 5756 — [nectionFactory1] cn.itcast.mq.config.CommonConfig : 消息发送到队列失败。响应码:312, 失败原因:NO_ROUTE, 交换机: delay.direct, 路由key:delay, 消息: (Body:‘[B@5f1df