|
@@ -0,0 +1,146 @@
|
|
|
+package com.hb.proj.third;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.concurrent.ArrayBlockingQueue;
|
|
|
+import java.util.concurrent.BlockingQueue;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+
|
|
|
+import com.hb.proj.diagnose.FeatureExtractor;
|
|
|
+import com.hb.proj.diagnose.XGBoostDataUtil;
|
|
|
+import com.hb.proj.diagnose.XGBoostEngine;
|
|
|
+import com.hb.proj.model.DiagnoseStandard;
|
|
|
+import com.hb.proj.model.DiagramFeatureSample;
|
|
|
+import com.hb.proj.model.DiagramSample;
|
|
|
+import com.hb.proj.rep.DiagramSampleService;
|
|
|
+
|
|
|
+import jakarta.annotation.PostConstruct;
|
|
|
+import jakarta.annotation.PreDestroy;
|
|
|
+
|
|
|
+@Component
|
|
|
+public class RedisMsgProcessor {
|
|
|
+
|
|
|
+ private final static Logger logger = LoggerFactory.getLogger(RedisMsgProcessor.class);
|
|
|
+
|
|
|
+ private final BlockingQueue<DiagramSample> msgQueue = new ArrayBlockingQueue<>(200);
|
|
|
+
|
|
|
+ private volatile boolean running = true;
|
|
|
+
|
|
|
+ private static final int BATCH_SIZE = 20;
|
|
|
+
|
|
|
+ // 队列为空时的等待时间(毫秒)
|
|
|
+ private static final long POLL_TIMEOUT = 1000;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private XGBoostEngine xgbEngine;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private DiagramSampleService sampleService;
|
|
|
+
|
|
|
+
|
|
|
+ public int getQueueSize() {
|
|
|
+ return msgQueue.size();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将消息加入队列
|
|
|
+ * @param msg
|
|
|
+ */
|
|
|
+ public void addMsg(DiagramSample msg) {
|
|
|
+ try {
|
|
|
+ msgQueue.put(msg);
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ logger.error("接收功图样本出现异常:{}",e.getMessage());
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
+ throw new RuntimeException("Message queue interrupted", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 启动实际处理线程
|
|
|
+ */
|
|
|
+ @PostConstruct
|
|
|
+ public void init() {
|
|
|
+ new Thread(this::process).start();
|
|
|
+ }
|
|
|
+
|
|
|
+ @PreDestroy
|
|
|
+ public void shutdown() {
|
|
|
+ running = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void process() {
|
|
|
+ List<DiagramSample> batch=null;
|
|
|
+ DiagramSample sample=null;
|
|
|
+ int drained=0;
|
|
|
+ while (running && !Thread.currentThread().isInterrupted()) {
|
|
|
+ try {
|
|
|
+ batch= new ArrayList<>(BATCH_SIZE);
|
|
|
+ drained = msgQueue.drainTo(batch, BATCH_SIZE);
|
|
|
+ if (drained == 0) {
|
|
|
+ // 队列为空时,阻塞等待至少一条消息
|
|
|
+ sample = msgQueue.poll(POLL_TIMEOUT, TimeUnit.MILLISECONDS);
|
|
|
+ if (sample != null) {
|
|
|
+ batch.add(sample);
|
|
|
+ // 继续非阻塞获取剩余消息
|
|
|
+ msgQueue.drainTo(batch, BATCH_SIZE - 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!batch.isEmpty()) {
|
|
|
+ handleBatch(batch);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch(InterruptedException e) {
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ catch (Exception e) {
|
|
|
+ logger.error("处理功图样本消息出现异常:{}",e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //应用关闭时检查是否还有未处理的样本
|
|
|
+ handleRemainingMsg();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 实际的业务处理
|
|
|
+ * @param batch
|
|
|
+ */
|
|
|
+ private void handleBatch(List<DiagramSample> batchSamples) {
|
|
|
+ List<DiagramFeatureSample> feaSamples=new ArrayList<>(batchSamples.size());
|
|
|
+ for(DiagramSample sample : batchSamples) {
|
|
|
+ feaSamples.add(FeatureExtractor.extract(sample));
|
|
|
+ }
|
|
|
+ float[][] rst=xgbEngine.predict(XGBoostDataUtil.build(feaSamples, false));
|
|
|
+
|
|
|
+ Map<Integer,DiagnoseStandard> labelStdMapping=sampleService.loadLabelStdMapping();
|
|
|
+
|
|
|
+ DiagnoseStandard diagnoseStd=null;
|
|
|
+ for(int i=0,len=rst.length;i<len;i++) {
|
|
|
+ diagnoseStd=labelStdMapping.get((int)rst[i][0]);
|
|
|
+ logger.info("诊断结果:{},{}",batchSamples.get(i).getWellName(),diagnoseStd.getConclusion());
|
|
|
+ }
|
|
|
+
|
|
|
+ logger.info("本次完成批量诊断{}个",batchSamples.size());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理队列剩余消息(优雅关闭用)
|
|
|
+ */
|
|
|
+ private void handleRemainingMsg() {
|
|
|
+ List<DiagramSample> remaining = new ArrayList<>();
|
|
|
+ msgQueue.drainTo(remaining);
|
|
|
+ if (!remaining.isEmpty()) {
|
|
|
+ logger.info("处理剩余功图样本消息: " + remaining.size());
|
|
|
+ handleBatch(remaining);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|