延迟队列可以实现消息在投递到
Exchange
之后,经过一定的时间之后再投递到相应的Queue
。再被消费者监听消费。 即:生产者投递的消息经过一段时间之后再被消费者消费。
该业务的其他实现方案:
Redis
,设置过期时间,监听过期事件。使用RabbitMQ延迟队列实现:
/usr/local/Cellar/rabbitmq/3.7.15/plugins
OrderController
为了简单起见,省略了Service层.x-delayed-type
,值为交换机类型,可以是fanout
,topic
,direct
。并且设置交换机的type为x-delayed-message
。可以看到,除了默认的交换机,SpringBoot已经帮我们创建好了延迟交换机order-delay-exchange
,并且此时messages delayed为0,因为我们还未向交换机投递消息。
在消息投递之前为每条消息都设置了延迟时长setDelay()
。
调用消费者的代码在上面OrderController
中,下定之后,订单数据落库,并且向MQ中投递延迟消息。可以回头看看。
为了方便查看到延迟投递的效果,我在消息投递和接收处都打印了日志,测试时可以看到消息投递和消息的时间间隔。
可以看到,打印出了投递日志,订单主键为666ae86aabe2a1b3120b34bb5f447bbe
的订单在2020-04-14 22:22:04.307
进行了投递,此时数据库中该订单的状态为100
,待支付。
messages delayed:1
,即目前有一条消息处于延迟状态。可以看到OrderConsumer
在10S后2020-04-14 22:22:14.320
接收到了主键为666ae86aabe2a1b3120b34bb5f447bbe
的订单消息。距离投递时间2020-04-14 22:22:04.307
为10S。此时查看DB中订单状态:
订单状态为200
已过期,且过期时间为2020-04-14 22:22:14
app:
rabbitmq:
delay:
order: 1M
消息都在延迟1分钟后投递到了队列-消费者。
建议收藏,当然我只是建议。
**在实际业务使用中,如果消费者的消费能力比较低下,会存在已经过期的消息阻塞积压在队列,无法在指定的时间内过期,导致业务出现异常。
实际上,按照我们业务意图,队里Queue里是不应该有大量消息存在的,因为投递到过期队列的消息已经是过期了的,应该立即被消费掉。**
2020-04-15 20:18:05.269 OrderSender : 订单[d6fd965b11f8db0fafb762d305db83b0]投递到MQ
2020-04-15 20:18:05.765 OrderSender : 订单[77ceb7f1bfbbcaf627224ac75e96b0e5]投递到MQ
2020-04-15 20:19:05.279 OrderConsumer : 消费者接收到延迟订单[d6fd965b11f8db0fafb762d305db83b0]
2020-04-15 20:19:15.316 OrderConsumer : 订单业务处理结束.....进行消息ack签收
2020-04-15 20:19:15.318 OrderConsumer : 消费者接收到延迟订单[77ceb7f1bfbbcaf627224ac75e96b0e5]
2020-04-15 20:19:25.330 OrderConsumer : 订单业务处理结束.....进行消息ack签收
第一个订单d6fd965b11f8db0fafb762d305db83b0
投递时间为2020-04-15 20:18:05.269
。1分钟后2020-04-15 20:19:05.279
接收到了通知,并且处理了10S后进行了签收ack。
第二个订单77ceb7f1bfbbcaf627224ac75e96b0e5
投递时间为2020-04-15 20:18:05.765
。1分钟过后并没有收到通知,而是在第一个订单处理完毕之后,2020-04-15 20:19:15.318
才收到了通知,比预期的时间长了10秒,实际延迟时间为1分钟+10秒。出现了业务异常。
任何技术的使用都不可生搬硬套,需要结合自己实际的业务场景进行相应的调整优化。在平时的工作中应该多关注程序在实际的运行过程中的结果是否符合我们的预期
本文涉及的源代码:https://github.com/FutaoSmile/springboot-learn-integration/releases/tag/v_rabbitmq_delay_queue
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。