1.何为延迟队列
顾名思义,延迟队列就是进入该队列的消息会被延迟消费的队列。而一般的队列,消息一旦入队了之后就会被消费者马上消费。 延迟队列多用于需要延迟工作的场景。最常见的是以下两种场景:
1. 延迟消费
用户生成订单之后,需要过一段时间校验订单的支付状态,如果订单仍未支付则需要及时地关闭订单。用户注册成功之后,需要过一段时间比如一周后校验用户的使用情况,如果发现用户活跃度较低,则发送邮件或者短信来提醒用户使用。
1.2 延迟重试
比如消费者从队列里消费消息时失败了,但是想要延迟一段时间后自动重试。 如果不使用延迟队列,那么我们只能通过一个轮询扫描程序去完成。这种方案既不优雅,也不方便做成统一的服务便于开发人员使用。但是使用延迟队列的话,我们就可以轻而易举地完成。
2 RocketMq 对延迟队列的支持
其实rocketMq是支持延迟消息队列的。我们后端一般会使用到Springboot 来集成RocketMq 来处理数据。其中官方会有RocketMQTemplate , 其中的sysend 的方法有一个入参 dealyLevel 是代表延时级别的。
这里我们先不对他进行讨论, 他这个是基于生产者发送方来延时的。 现在我们要做的是类似于 @RocketMQMessageListener, 做为消费方, 接收方来做的。
3 设计思想和架构
1, 要实现自定义注解,里面包含rocketMq 的地址, 分组信息, topic 信息等。 这些信息有的默认使用的是配置文件的信息。
2, 在使用SpringBean 的后置处理器,对 自定义注解 进行拦截 封装成消息发送生产者对象。 在监听器里面使用哪个thread.sleep() 来获取注解里面的 延迟时长。在调用methon.invoke 的方法。直接返回结果。
3, 消息发送对象,要实现 InitializingBean , DisposableBean 来重新启动和销毁的方法。
4, 在使用springboot 的spi 把自定义的后置处理器的配置类 写入spring.factories 里面。
4,具体的代码
4.1 自定义注解
package com.ducheng.rocket.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DelayRocketMQListener {
/**
* RocketMQ topic
* @return
*/
String topic();
/**
* Tag
* @return
*/
String tag() default "*";
/**
* 延迟的时长
* @return
*/
int delayTime() default 0;
/**
* nameServer, 支持两种模式,模式是从配置文件获取。
* @return
*/
String nameServer() default "${rocketmq.name-server}";
/**
* 消费者组信息, 支持两种模式, m默认是从配置文件获取。
* @return
*/
String consumerGroup() default "${rocketmq.producer.group}" ;
}
复制代码
4.2 构建消费者对象
package com.duch