package com.bx.imcommon.mq; import com.alibaba.fastjson.JSONObject; import com.bx.imcommon.util.ThreadPoolExecutorFactory; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; import javax.annotation.PreDestroy; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.*; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * reids 队列拉取定时任务 * * @author: Blue * @date: 2024-07-15 * @version: 1.0 */ @Slf4j @Component public class RedisMQPullTask implements CommandLineRunner { private static final ScheduledThreadPoolExecutor EXECUTOR_SERVICE = ThreadPoolExecutorFactory.getThreadPoolExecutor(); @Autowired(required = false) private List consumers = Collections.emptyList(); @Autowired private RedisMQTemplate redisMQTemplate; @Override public void run(String... args) { consumers.forEach((consumer -> { // 注解参数 RedisMQListener annotation = consumer.getClass().getAnnotation(RedisMQListener.class); String key = consumer.generateKey(); int batchSize = annotation.batchSize(); int period = annotation.period(); // 获取泛型类型 Type superClass = consumer.getClass().getGenericSuperclass(); Type type = ((ParameterizedType)superClass).getActualTypeArguments()[0]; EXECUTOR_SERVICE.execute(new Runnable() { @Override public void run() { List datas = new LinkedList<>(); try { if(consumer.isReady()){ // 拉取一个批次的数据 List objects = pullBatch(key, batchSize); for (Object obj : objects) { if (obj instanceof JSONObject) { JSONObject jsonObject = (JSONObject)obj; Object data = jsonObject.toJavaObject(type); consumer.onMessage(data); datas.add(data); } } if(!datas.isEmpty()){ consumer.onMessage(datas); } } } catch (Exception e) { log.error("数据消费异常,队列:{}", key, e); } // 继续消费数据 if (!EXECUTOR_SERVICE.isShutdown()) { if (datas.size() < batchSize) { // 数据已经消费完,等待下一个周期继续拉取 EXECUTOR_SERVICE.schedule(this, period, TimeUnit.MICROSECONDS); } else { // 数据没有消费完,直接开启下一个消费周期 EXECUTOR_SERVICE.execute(this); } } } }); })); } private List pullBatch(String key, Integer batchSize) { List objects = new LinkedList<>(); if (redisMQTemplate.isSupportBatchPull()) { // 版本大于6.2,支持批量拉取 objects = redisMQTemplate.opsForList().leftPop(key, 100); } else { // 版本小于6.2,只能逐条拉取 Object obj = redisMQTemplate.opsForList().leftPop(key); while (!Objects.isNull(obj) && objects.size() < batchSize) { objects.add(obj); obj = redisMQTemplate.opsForList().leftPop(key); } } return objects; } @PreDestroy public void destory(){ ThreadPoolExecutorFactory.shutDown(); } }