Browse Source

场景计算优化

dengsixing 3 năm trước cách đây
mục cha
commit
961ffcd603
19 tập tin đã thay đổi với 701 bổ sung163 xóa
  1. 6 0
      4dkankan-center-modeling/pom.xml
  2. 2 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/ModelingApplication.java
  3. 57 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/bean/BuildSceneResultBean.java
  4. 11 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/constants/SysConstants.java
  5. 116 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/entity/BuildLog.java
  6. 19 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/exception/BuildException.java
  7. 100 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/generate/AutoGenerate.java
  8. 61 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/job/EcsJob.java
  9. 18 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/mapper/IBuildLogMapper.java
  10. 179 123
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/receiver/BuildSceneListener.java
  11. 16 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/IBuildLogService.java
  12. 20 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/impl/BuildLogServiceImpl.java
  13. 4 0
      4dkankan-center-modeling/src/main/resources/bootstrap-dev.yml
  14. 8 12
      4dkankan-center-scene/src/main/java/com/fdkankan/scene/controller/TestController.java
  15. 42 11
      4dkankan-center-scene/src/main/java/com/fdkankan/scene/listener/BuildScenePreMQListener.java
  16. 9 6
      4dkankan-center-scene/src/main/java/com/fdkankan/scene/listener/BuildSceneResultMQListener.java
  17. 9 10
      4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/impl/BuildScenePreServiceImpl.java
  18. 21 0
      4dkankan-common/src/main/java/com/fdkankan/common/exception/GlobalExceptionHandler.java
  19. 3 1
      4dkankan-common/src/main/java/com/fdkankan/common/response/BaseResponseAdvice.java

+ 6 - 0
4dkankan-center-modeling/pom.xml

@@ -94,6 +94,12 @@
 		</dependency>
 		</dependency>
 
 
 		<dependency>
 		<dependency>
+			<groupId>com.fdkankan</groupId>
+			<artifactId>4dkankan-utils-db</artifactId>
+			<version>2.0.0-SNAPSHOT</version>
+		</dependency>
+
+		<dependency>
 			<groupId>de.codecentric</groupId>
 			<groupId>de.codecentric</groupId>
 			<artifactId>spring-boot-admin-client</artifactId>
 			<artifactId>spring-boot-admin-client</artifactId>
 			<version>2.3.1</version>
 			<version>2.3.1</version>

+ 2 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/ModelingApplication.java

@@ -5,8 +5,10 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
 import org.springframework.cloud.openfeign.EnableFeignClients;
 import org.springframework.cloud.openfeign.EnableFeignClients;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.ComponentScan;
+import org.springframework.scheduling.annotation.EnableScheduling;
 
 
 @SpringBootApplication
 @SpringBootApplication
+@EnableScheduling
 @EnableDiscoveryClient
 @EnableDiscoveryClient
 @EnableFeignClients("com.fdkankan.*.api.feign")
 @EnableFeignClients("com.fdkankan.*.api.feign")
 @ComponentScan(basePackages = {"com.fdkankan.*"})
 @ComponentScan(basePackages = {"com.fdkankan.*"})

+ 57 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/bean/BuildSceneResultBean.java

@@ -0,0 +1,57 @@
+package com.fdkankan.modeling.bean;
+
+import com.fdkankan.common.constant.ModelingBuildStatus;
+import java.util.HashMap;
+import java.util.Map;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * <p>
+ * TODO
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2022/4/6
+ **/
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class BuildSceneResultBean {
+
+    private ModelingBuildStatus buildStatus;
+
+    private String resultTopicName;
+
+    private String cameraType;
+
+    private String fileId;
+
+    private int payStatus;
+
+    private String num;
+
+    private Map<String, String> uploadMap;
+
+    private String path;
+
+    private Integer pushChannel;
+
+    private String pushToken;
+
+    private String prefix;
+
+    private Integer videoVersion;
+
+    /**
+     * 计算耗时
+     */
+    private Long duration;
+
+
+
+
+}

+ 11 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/constants/SysConstants.java

@@ -1,6 +1,10 @@
 package com.fdkankan.modeling.constants;
 package com.fdkankan.modeling.constants;
 
 
 import com.fdkankan.common.util.FileUtils;
 import com.fdkankan.common.util.FileUtils;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.beans.factory.annotation.Value;
@@ -13,6 +17,13 @@ public class SysConstants {
     public static String hostName;
     public static String hostName;
     public static int modelTimeOut;
     public static int modelTimeOut;
 
 
+    public static List<String> residenceServiceHostName = new ArrayList<>();
+
+    public static volatile Boolean SYSTEM_BUILDING = false;
+    public static volatile Boolean SYSTEM_OFFING = false;
+
+    public static ExecutorService executorService = Executors.newFixedThreadPool(1);
+
     public static final String DINGTALK_MSG_PATTERN = "**环境**: %s\n\n" +
     public static final String DINGTALK_MSG_PATTERN = "**环境**: %s\n\n" +
             "**服务器名称**: %s\n\n" +
             "**服务器名称**: %s\n\n" +
             "**失败原因**: %s\n\n" +
             "**失败原因**: %s\n\n" +

+ 116 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/entity/BuildLog.java

@@ -0,0 +1,116 @@
+package com.fdkankan.modeling.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author 
+ * @since 2022-04-07
+ */
+@Getter
+@Setter
+@TableName("t_build_log")
+public class BuildLog implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 场景码
+     */
+    @TableField("num")
+    private String num;
+
+    /**
+     * 资源路径
+     */
+    @TableField("data_source")
+    private String dataSource;
+
+    /**
+     * 主题名称
+     */
+    @TableField("topic_name")
+    private String topicName;
+
+    /**
+     * -10:其他原因失败
+-3:重复计算
+-2:计算失败
+-1:计算超时
+0:计算中
+1:计算成功
+     */
+    @TableField("build_status")
+    private Integer buildStatus;
+
+    /**
+     * 服务器名称
+     */
+    @TableField("host_name")
+    private String hostName;
+
+    @TableField("build_type")
+    private Integer buildType;
+
+    /**
+     * 相机类型
+     */
+    @TableField("camera_type")
+    private Integer cameraType;
+
+    @TableField("source")
+    private String source;
+
+    /**
+     * java程序异常详情
+     */
+    @TableField("reason")
+    private String reason;
+
+    @TableField("log_detail_path")
+    private String logDetailPath;
+
+    /**
+     * 计算耗时
+     */
+    @TableField("duration")
+    private Long duration;
+
+    /**
+     * 开始计算时间
+     */
+    @TableField("create_time")
+    private Date createTime;
+
+    /**
+     * 结束计算时间
+     */
+    @TableField("update_time")
+    private Date updateTime;
+
+    /**
+     * 0-有效,1-删除
+     */
+    @TableField("tb_status")
+    @TableLogic
+    private Integer tbStatus;
+
+
+}

+ 19 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/exception/BuildException.java

@@ -0,0 +1,19 @@
+package com.fdkankan.modeling.exception;
+
+import com.fdkankan.common.constant.ModelingBuildStatus;
+
+public class BuildException extends RuntimeException{
+
+    private static final long serialVersionUID = -1518945670203783450L;
+    private ModelingBuildStatus buildStatus;
+
+
+    public BuildException(ModelingBuildStatus buildStatus){
+        super(buildStatus.message());
+        this.buildStatus = buildStatus;
+    }
+
+    public ModelingBuildStatus getBuildStatus() {
+        return buildStatus;
+    }
+}

+ 100 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/generate/AutoGenerate.java

@@ -0,0 +1,100 @@
+package com.fdkankan.modeling.generate;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.generator.FastAutoGenerator;
+import com.baomidou.mybatisplus.generator.config.OutputFile;
+import com.baomidou.mybatisplus.generator.config.rules.DateType;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public class AutoGenerate {
+
+
+    public static void main(String[] args) {
+
+        System.out.println("相对路径指定到:"+ System.getProperty("user.dir"));
+
+
+        String path =System.getProperty("user.dir") + "\\4dkankan-center-modeling";
+
+        generate(path,"modeling", getTables(new String[]{
+                "t_build_log",
+        }));
+
+//        generate(path,"goods", getTables(new String[]{
+//                        "t_camera","t_camera_detail","t_camera_out","t_camera_space","t_camera_version",
+//                        "t_company","t_goods","t_goods_sku","t_cart","t_goods_spec",
+//                        "t_goods_spec_value","t_goods_spu_spec","t_sn_code"
+//        }));
+//
+//        generate(path,"order", getTables(new String[]{
+//                        "t_increment_order","t_invoice","t_order","t_order_item",
+//                        "t_pre_sale","t_space_sdk","t_trade_log","t_commerce_order","t_download_order","t_expansion_order"
+//        }));
+//        generate(path,"order", getTables(new String[]{
+//                        "t_virtual_order"
+//        }));
+//
+//        generate(path,"user", getTables(new String[]{
+//                        "t_user","t_user_increment","t_manager","t_province","t_increment_type","t_intercom_message","t_receiver_info"
+//        }));
+    }
+
+    public static List<String> getTables(String [] tableNames){
+        return new ArrayList<>(Arrays.asList(tableNames));
+    }
+
+
+    public static void  generate(String path,String moduleName,  List<String> tables){
+        FastAutoGenerator.create("jdbc:mysql://192.168.0.47:13306/4dkankan-center-modeling",
+                "root","4dkk2020cuikuan%")
+                .globalConfig(builder -> {
+                    builder.author("")               //作者
+                            .outputDir(path+"\\src\\main\\java")    //输出路径(写到java目录)
+                            //.enableSwagger()           //开启swagger
+                            .commentDate("yyyy-MM-dd")
+                            .dateType(DateType.ONLY_DATE)
+                            .fileOverride();            //开启覆盖之前生成的文件
+
+                })
+                .packageConfig(builder -> {
+                    builder.parent("com.fdkankan")
+                            .moduleName(moduleName)
+                            .entity("entity")
+                            .service("service")
+                            .serviceImpl("service.impl")
+                            .controller("controller")
+                            .mapper("mapper")
+                            .xml("test.mapper")
+                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml,path+"\\src\\main\\resources\\mapper\\"+moduleName));
+                })
+                .strategyConfig(builder -> {
+                    builder.addInclude(tables)
+                            .addTablePrefix("t_")
+
+                            .serviceBuilder()
+                            .formatServiceFileName("I%sService")
+                            .formatServiceImplFileName("%sServiceImpl")
+
+                            .entityBuilder()
+                            .enableLombok()
+                            .logicDeleteColumnName("tb_status")
+                            .enableTableFieldAnnotation()
+//                            .superClass(BaseEntity.class)
+
+                            .controllerBuilder()
+                            .formatFileName("%sController")
+                            .enableRestStyle()
+
+                            .mapperBuilder()
+                            .superClass(BaseMapper.class)
+                            .formatMapperFileName("I%sMapper")
+                            .enableMapperAnnotation()
+                            .formatXmlFileName("%sMapper");
+                })
+                // .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
+                .execute();
+    }
+}

+ 61 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/job/EcsJob.java

@@ -0,0 +1,61 @@
+package com.fdkankan.modeling.job;
+
+import com.fdkankan.common.util.RubberSheetingUtil;
+import com.fdkankan.modeling.constants.SysConstants;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import javax.annotation.PostConstruct;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
+
+@Component
+public class EcsJob {
+
+    private static final Logger log = LoggerFactory.getLogger(EcsJob.class);
+
+    @Autowired
+    private RubberSheetingUtil rubberSheetingUtil;
+
+    @PostConstruct
+    public void deleteEcs() {
+        log.info("常驻服务列表:{}", SysConstants.residenceServiceHostName);
+        log.info("当前服务名称:{}", SysConstants.hostName);
+        log.info("当前服务是否是常驻服务:{}", SysConstants.residenceServiceHostName.contains(SysConstants.hostName));
+        if (!ObjectUtils.isEmpty(SysConstants.residenceServiceHostName) && SysConstants.residenceServiceHostName.contains(SysConstants.hostName)) {
+            log.info("此服务是常驻服务");
+            return;
+        }
+        Executors.newSingleThreadScheduledExecutor().scheduleWithFixedDelay(() -> {
+
+            //判断消息树
+
+                    // 判断是否有任务执行
+                    if (SysConstants.SYSTEM_BUILDING) {
+                        log.error("{} 服务构建中,退出停止服务请求!", SysConstants.hostName);
+                        return;
+                    }
+                    log.info("服务未构建,准备停止服务!");
+                    if (!SysConstants.executorService.isShutdown()) {
+                        SysConstants.SYSTEM_OFFING = true;
+                        if (!SysConstants.SYSTEM_BUILDING) {
+                            SysConstants.executorService.shutdown();
+                            log.error("{} 线程池关闭,不接受新的构建请求!", SysConstants.hostName);
+                        }else{
+                            SysConstants.SYSTEM_OFFING = false;
+                            log.error("{} 服务构建中,退出停止服务请求!", SysConstants.hostName);
+                        }
+                    }
+                    // 没有任务执行时,则退出
+                    if (SysConstants.executorService.isShutdown() && SysConstants.executorService.isTerminated()) {
+                        log.error("{} 请求阿里云关闭弹性伸缩", SysConstants.hostName);
+                        rubberSheetingUtil.deleteEcs(SysConstants.hostName);
+                    } else {
+                        log.error("{} 服务构建中,退出删除程序失败!", SysConstants.hostName);
+                    }
+                },
+                50, 60, TimeUnit.MINUTES);
+    }
+}

+ 18 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/mapper/IBuildLogMapper.java

@@ -0,0 +1,18 @@
+package com.fdkankan.modeling.mapper;
+
+import com.fdkankan.modeling.entity.BuildLog;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2022-04-07
+ */
+@Mapper
+public interface IBuildLogMapper extends BaseMapper<BuildLog> {
+
+}

+ 179 - 123
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/receiver/BuildSceneListener.java

@@ -11,12 +11,17 @@ import static com.fdkankan.push.PushMessageConfig.IOS_SECRET_Z;
 
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.exceptions.ExceptionUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.common.constant.BuildStatus;
 import com.fdkankan.common.constant.ConstantFilePath;
 import com.fdkankan.common.constant.ConstantFilePath;
 import com.fdkankan.common.constant.ConstantUrl;
 import com.fdkankan.common.constant.ConstantUrl;
+import com.fdkankan.common.constant.ModelingBuildStatus;
+import com.fdkankan.common.constant.ServerCode;
 import com.fdkankan.common.constant.UploadFilePath;
 import com.fdkankan.common.constant.UploadFilePath;
+import com.fdkankan.common.exception.BusinessException;
 import com.fdkankan.common.util.ComputerUtil;
 import com.fdkankan.common.util.ComputerUtil;
 import com.fdkankan.common.util.CreateObjUtil;
 import com.fdkankan.common.util.CreateObjUtil;
 import com.fdkankan.common.util.FileUtil;
 import com.fdkankan.common.util.FileUtil;
@@ -25,7 +30,11 @@ import com.fdkankan.common.util.SceneUtil;
 import com.fdkankan.dingtalk.DingTalkSendUtils;
 import com.fdkankan.dingtalk.DingTalkSendUtils;
 import com.fdkankan.fyun.constant.StorageType;
 import com.fdkankan.fyun.constant.StorageType;
 import com.fdkankan.fyun.oss.UploadToOssUtil;
 import com.fdkankan.fyun.oss.UploadToOssUtil;
+import com.fdkankan.modeling.bean.BuildSceneResultBean;
 import com.fdkankan.modeling.constants.SysConstants;
 import com.fdkankan.modeling.constants.SysConstants;
+import com.fdkankan.modeling.entity.BuildLog;
+import com.fdkankan.modeling.exception.BuildException;
+import com.fdkankan.modeling.service.IBuildLogService;
 import com.fdkankan.mq.message.BuildSceneFailDTMqMessage;
 import com.fdkankan.mq.message.BuildSceneFailDTMqMessage;
 import com.fdkankan.mq.message.BuildSceneMqMessage;
 import com.fdkankan.mq.message.BuildSceneMqMessage;
 import com.fdkankan.mq.message.BuildSceneResultMqMessage;
 import com.fdkankan.mq.message.BuildSceneResultMqMessage;
@@ -60,6 +69,7 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.TimeoutException;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.StopWatch;
 import org.apache.rocketmq.spring.annotation.MessageModel;
 import org.apache.rocketmq.spring.annotation.MessageModel;
 import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
 import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
 import org.apache.rocketmq.spring.core.RocketMQListener;
 import org.apache.rocketmq.spring.core.RocketMQListener;
@@ -119,99 +129,83 @@ public class BuildSceneListener implements RocketMQListener<String> {
     @Autowired
     @Autowired
     private DingTalkSendUtils dingTalkSendUtils;
     private DingTalkSendUtils dingTalkSendUtils;
 
 
+    @Autowired
+    private IBuildLogService buildLogService;
+
     @Override
     @Override
-    public synchronized void onMessage(String message) {
+    public void onMessage(String message) {
         log.info("开始处理消息,消费者组:{},主题名:{}, 消息内容:{}", consumerGroup, topicName, message);
         log.info("开始处理消息,消费者组:{},主题名:{}, 消息内容:{}", consumerGroup, topicName, message);
+        if (ObjectUtils.isEmpty(message)) {
+            SysConstants.SYSTEM_BUILDING = false;
+            log.error("消息体为空,退出构建,当前服务器id:{}", SysConstants.hostName);
+            return;
+        }
         BuildSceneMqMessage buildSceneMqMessage = JSONObject.parseObject(message, BuildSceneMqMessage.class);
         BuildSceneMqMessage buildSceneMqMessage = JSONObject.parseObject(message, BuildSceneMqMessage.class);
-        if(StrUtil.isBlank(buildSceneMqMessage.getSceneNum())){
-            log.error("消息结构错误,消费者组:{},主题名:{}, 消息内容:{}", consumerGroup, topicName, message);
+        if(Objects.isNull(buildSceneMqMessage) || StrUtil.isBlank(buildSceneMqMessage.getSceneNum())){
+            log.error("消息内容错误,消费者组:{},主题名:{}, 消息内容:{}", consumerGroup, topicName, message);
             return;
             return;
         }
         }
         process(buildSceneMqMessage);
         process(buildSceneMqMessage);
+
+        log.info("处理消息结束,消费者组:{},主题名:{}, 消息内容:{}", consumerGroup, topicName, message);
     }
     }
 
 
     public void process(BuildSceneMqMessage message) {
     public void process(BuildSceneMqMessage message) {
-        final ExecutorService exec = Executors.newFixedThreadPool(1);
-        Callable<String> call = (Callable<String>) () -> {
-            //开始执行耗时操作
-            String key = RedisKey.SCENE_BUILDING + message.getSceneNum();
-            try {
-                // 获取缓存锁,防止重复消费
-                Long building = redisUtil.incr(key, 1);
-                if (building.compareTo(1L) != 0) {
-                    log.error("场景正在构建中,退出构建,当前服务器id:{},参数:{}", SysConstants.hostName, JSONObject.toJSONString(message));
-                } else {
-                    redisUtil.expire(key, Duration.of(SysConstants.modelTimeOut, ChronoUnit.HOURS));
-                }
-                //休眠2秒等待数据入库
-                Thread.sleep(2000L);
-                try {
-                    FileUtils.writeFile("/opt/hosts/running.txt", DateUtil.formatDateTime(new Date()));
-                    String tomcatLog = "scenenum:" + message.getSceneNum() + "\ntime:" + DateUtil.formatDateTime(new Date()) +
-                            " action:create hostname:" + SysConstants.hostName;
-                    //打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
-                    FileWriter writer = new FileWriter("/mnt/elastic_log/tomcat" + "_" + message.getSceneNum() + ".log", true);
-                    writer.write(tomcatLog);
-                    writer.close();
-                } catch (Exception e) {
-                    e.printStackTrace();
-                }
 
 
-                this.buildScene(message);
-                redisUtil.del(key);
-                try {
-                    FileUtils.deleteFile("/opt/hosts/running.txt");
-                    String tomcatLog = "scenenum:" + message.getSceneNum() + "\ntime:" + DateUtil.formatDateTime(new Date()) +
-                            " action:delete hostname:" + SysConstants.hostName;
-                    //打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
-                    FileWriter writer = new FileWriter("/mnt/elastic_log/tomcat" + "_" + message.getSceneNum() + "log", true);
-                    writer.write(tomcatLog);
-                    writer.close();
-                } catch (Exception e) {
-                    e.printStackTrace();
-                }
-            } catch (Exception e) {
-                log.error("大场景计算失败",e);
-                // TODO: 2022/1/25 测试阶段,先注释掉推送
-//                this.sendDingTalkMq("计算失败", message);
-            }finally {
-                //释放锁
-                redisUtil.del(key);
-            }
-            log.info("场景生成好了***");
-            return "success";
-        };
-        Future<String> future = exec.submit(call);
+        SysConstants.SYSTEM_BUILDING = true;
+        if (SysConstants.SYSTEM_OFFING) {
+            SysConstants.SYSTEM_BUILDING = false;
+            log.error("服务实例:{} 正在关闭,退出构建!", SysConstants.hostName);
+            throw new BusinessException(ServerCode.SERVER_CLOSING);
+        }
+        //开始计时
+        StopWatch watch = new StopWatch();
+        watch.start();
+
+        BuildLog buildLog = new BuildLog();
+        BuildSceneResultBean buildSceneResult = new BuildSceneResultBean();
+
+        Future<BuildSceneResultBean> future = null;
         try {
         try {
-            future.get(SysConstants.modelTimeOut, TimeUnit.HOURS); //任务处理超时时间设为 24个小时
+
+            //休眠2秒等待准备数据
+            Thread.sleep(2000L);
+
+            //计算前准备
+            preBuild(message, buildLog);
+
+            future = SysConstants.executorService.submit(()->{
+                return buildScene(message);
+            });
+            buildSceneResult = future.get(SysConstants.modelTimeOut, TimeUnit.SECONDS);
+
+            //结束计时
+            watch.stop();
+            buildLog.setDuration(watch.getTime(TimeUnit.SECONDS));
         } catch (TimeoutException ex) {
         } catch (TimeoutException ex) {
-            ex.printStackTrace();
-            StringWriter trace=new StringWriter();
-            ex.printStackTrace(new PrintWriter(trace));
-            log.error("超时了");
-            log.error(trace.toString());
-            FileUtils.deleteFile("/opt/hosts/running.txt");
-            future.cancel(true);
-            // TODO: 2022/1/25 测试阶段,先注释掉推送
-//            this.sendDingTalkMq("计算超时", message);
-        } catch (Exception e) {
-            e.printStackTrace();
-            StringWriter trace=new StringWriter();
-            e.printStackTrace(new PrintWriter(trace));
-            log.error(trace.toString());
-            FileUtils.deleteFile("/opt/hosts/running.txt");
-            future.cancel(true);
-            // TODO: 2022/1/25 测试阶段,先注释掉推送
-//            this.sendDingTalkMq("计算失败", message);
+            log.error("服务实例:{} 构建异常:",SysConstants.hostName,ex);
+            buildSceneResult.setBuildStatus(ModelingBuildStatus.OVERTIME);
+        } catch (BuildException e){
+            buildSceneResult.setBuildStatus(e.getBuildStatus());
+        } catch(Exception e) {
+            log.error("服务实例:{} 构建异常:", SysConstants.hostName, e);
+            if (e.getCause() instanceof BuildException) {
+                buildSceneResult.setBuildStatus(((BuildException) e.getCause()).getBuildStatus());
+            } else {
+                buildSceneResult.setBuildStatus(ModelingBuildStatus.FAILED);
+                //未知异常,记录异常信息
+                buildLog.setReason(ExceptionUtil.stacktraceToString(e, 3000));
+            }
         }
         }
+        //计算后处理
+        afterBuild(message, buildSceneResult, buildLog);
 
 
     }
     }
 
 
-    private void buildScene(BuildSceneMqMessage message){
-        boolean buildSuccess = Boolean.FALSE;
+    private BuildSceneResultBean buildScene(BuildSceneMqMessage message){
+        ModelingBuildStatus buildStatus = ModelingBuildStatus.FAILED;
         String projectNum = null;
         String projectNum = null;
         Long computeTime = null;//计算耗时
         Long computeTime = null;//计算耗时
-        JSONObject videosJson = null;
         //如果mq生产者在消息体中执行了计算结果mq的主题名,就发到这个主题名,否则就发送到配置的主题名
         //如果mq生产者在消息体中执行了计算结果mq的主题名,就发到这个主题名,否则就发送到配置的主题名
         String resultTopicName = StrUtil.isNotBlank(message.getResultReceiverMqName()) ?
         String resultTopicName = StrUtil.isNotBlank(message.getResultReceiverMqName()) ?
                 message.getResultReceiverMqName() : buildSceneResultTopic;
                 message.getResultReceiverMqName() : buildSceneResultTopic;
@@ -232,9 +226,6 @@ public class BuildSceneListener implements RocketMQListener<String> {
         String resolution = message.getResolution();
         String resolution = message.getResolution();
         //判断调用V2还是V3版本的算法
         //判断调用V2还是V3版本的算法
         String buildType = ObjectUtils.isEmpty(message.getBuildType()) ? "V2" : message.getBuildType();
         String buildType = ObjectUtils.isEmpty(message.getBuildType()) ? "V2" : message.getBuildType();
-        String webSite = message.getWebSite();
-        Integer sceneStatus = message.getSceneStatus();
-        String thumb = message.getThumb();
 
 
         String dataPath = "data/data" + projectNum;//老版本文件路径
         String dataPath = "data/data" + projectNum;//老版本文件路径
 
 
@@ -244,11 +235,6 @@ public class BuildSceneListener implements RocketMQListener<String> {
         Integer videoVersion = null;
         Integer videoVersion = null;
 
 
         try{
         try{
-            if(StringUtils.equals(message.getIsStandardization(),"1")){
-                //表示标定算法
-                ComputerUtil.computerCalibration(message.getPath());
-                return;
-            }
 
 
             Map<String, String> dataMap = ComputerUtil.getTypeString(cameraType, algorithm,
             Map<String, String> dataMap = ComputerUtil.getTypeString(cameraType, algorithm,
                     resolution);
                     resolution);
@@ -277,17 +263,6 @@ public class BuildSceneListener implements RocketMQListener<String> {
 
 
             } else {
             } else {
 
 
-                //休眠1秒,否则可能获取不到场景资源
-                Thread.sleep(1000);
-//                if(sceneProId == null){
-//                    log.error("场景不存在,场景码:{}", projectNum);
-//                    // TODO: 2022/1/25 测试阶段,先注释掉推送
-////                    this.sendDingTalkMq("场景不存在", message);
-//                    return;
-//                }
-
-                long start = System.currentTimeMillis();
-
                 path = SceneUtil.getPath(path, cameraName, fileId, Integer.parseInt(cameraType), unicode);
                 path = SceneUtil.getPath(path, cameraName, fileId, Integer.parseInt(cameraType), unicode);
 
 
                 String dataFdagePath = path + File.separator + "capture" +File.separator+"data.fdage";
                 String dataFdagePath = path + File.separator + "capture" +File.separator+"data.fdage";
@@ -320,7 +295,6 @@ public class BuildSceneListener implements RocketMQListener<String> {
                 //计算模型并返回需要上传oss的文件集合
                 //计算模型并返回需要上传oss的文件集合
                 map = ComputerUtil.computer(projectNum, path, buildType);
                 map = ComputerUtil.computer(projectNum, path, buildType);
                 //计算完成时间
                 //计算完成时间
-                computeTime = (System.currentTimeMillis() - start) / 1000;
                 log.info("计算完成耗时:{}",computeTime);
                 log.info("计算完成耗时:{}",computeTime);
 
 
                 if(Integer.parseInt(cameraType) == 5 || Integer.parseInt(cameraType) == 6){
                 if(Integer.parseInt(cameraType) == 5 || Integer.parseInt(cameraType) == 6){
@@ -353,18 +327,66 @@ public class BuildSceneListener implements RocketMQListener<String> {
             }
             }
 
 
             CreateObjUtil.deleteFile(path.replace(ConstantFilePath.BUILD_MODEL_PATH, "/") + "/capture");
             CreateObjUtil.deleteFile(path.replace(ConstantFilePath.BUILD_MODEL_PATH, "/") + "/capture");
-            buildSuccess = Boolean.TRUE;
-        } catch(Exception e){
-            log.error("计算大场景失败"+projectNum, e);
-            // TODO: 2022/1/25 测试阶段,先注释掉推送
-//            this.sendDingTalkMq("计算失败", message);
-        }finally {
-            //发送计算结果到mq,再由消费者消费并操作数据库
-            this.sendCallResult(buildSuccess, resultTopicName, cameraType, computeTime, fileId, payStatus,
-                projectNum, videosJson, map, path, pushChannel, pushToken,prefix, videoVersion);
+            buildStatus = ModelingBuildStatus.SUCCESS;
+        }
+        finally {
             //上传status.json   console.log
             //上传status.json   console.log
-            this.uploadStatusJsonAndConsoleLog(sceneStatus, webSite, projectNum, thumb, payStatus);
+//            this.uploadStatusJsonAndConsoleLog(sceneStatus, webSite, projectNum, thumb, payStatus);
 
 
+            //发送计算结果到mq,再由消费者消费并操作数据库
+//            this.sendCallResult(buildSuccess, resultTopicName, cameraType, computeTime, fileId, payStatus,
+//                projectNum, videosJson, map, path, pushChannel, pushToken,prefix, videoVersion);
+
+            return BuildSceneResultBean.builder()
+                .buildStatus(buildStatus)
+                .resultTopicName(resultTopicName)
+                .cameraType(cameraType)
+                .fileId(fileId)
+                .payStatus(payStatus)
+                .num(projectNum)
+                .uploadMap(map)
+                .path(path)
+                .pushChannel(pushChannel)
+                .pushToken(pushToken)
+                .prefix(prefix)
+                .videoVersion(videoVersion)
+                .build();
+        }
+    }
+
+    private void afterBuild(BuildSceneMqMessage message, BuildSceneResultBean buildSceneResult, BuildLog buildLog){
+        try {
+            ModelingBuildStatus buildStatus = buildSceneResult.getBuildStatus();
+            String buildLogPath = String.format(UploadFilePath.BUILD_LOG_PATH, message.getSceneNum());
+            log.info("服务{} 计算结束:{},计算状态:{}", SysConstants.hostName, buildLog.getNum(),buildStatus.message());
+
+            if(!buildStatus.equals(ModelingBuildStatus.REPEAT)){
+                //释放锁
+                redisUtil.del(String.format(RedisKey.SCENE_BUILDING, message.getSceneNum()));
+                //如果是重复计算,没有走到计算逻辑,不需要上传日志文件
+                buildLog.setLogDetailPath(prefixAli+ buildLogPath + "console.log");
+            }
+            buildLog.setBuildStatus(buildStatus.code());
+            buildLog.setCameraType(Integer.parseInt(buildSceneResult.getCameraType()));
+            buildLogService.updateById(buildLog);
+
+            if(buildStatus.equals(ModelingBuildStatus.REPEAT)){
+                return;
+            }
+
+            //生成status.json文件
+            this.writeStatusJson(message.getSceneStatus(), message.getWebSite(),
+                message.getSceneNum(),message.getThumb(),message.getPayStatus());
+
+        } catch (Exception e) {
+            log.error("计算后业务处理出错!", e);
+        }finally {
+            //发送计算结果mq
+            buildSceneResult.setDuration(buildLog.getDuration());
+            this.sendCallResult(message, buildSceneResult);
+
+            //计算完毕,将当前系统构建状态改为false
+            SysConstants.SYSTEM_BUILDING = false;
         }
         }
     }
     }
 
 
@@ -387,6 +409,25 @@ public class BuildSceneListener implements RocketMQListener<String> {
 
 
     }
     }
 
 
+    private void preBuild(BuildSceneMqMessage message, BuildLog buildLog) throws BuildException {
+
+        // 初始化日志参数
+        buildLog.setHostName(SysConstants.hostName);
+        buildLog.setTopicName(topicName);
+        buildLog.setNum(message.getSceneNum());
+        buildLog.setDataSource(message.getDataSource());
+        buildLogService.save(buildLog);
+
+        String key = RedisKey.SCENE_BUILDING + message.getSceneNum();
+        Long building = redisUtil.incr(key, 1);
+        if (building.compareTo(1L) != 0) {
+            log.error("场景正在构建中,退出构建,当前服务器id:{},参数:{}", SysConstants.hostName, JSONObject.toJSONString(message));
+            throw new BuildException(ModelingBuildStatus.REPEAT);
+        } else {
+            redisUtil.expire(key, Duration.of(SysConstants.modelTimeOut, ChronoUnit.HOURS));
+        }
+    }
+
     private void copyToEditDir(String num) throws IOException {
     private void copyToEditDir(String num) throws IOException {
 
 
         String editImagesPath = String.format(UploadFilePath.IMG_EDIT_PATH, num);
         String editImagesPath = String.format(UploadFilePath.IMG_EDIT_PATH, num);
@@ -405,28 +446,43 @@ public class BuildSceneListener implements RocketMQListener<String> {
         }
         }
     }
     }
 
 
-    private void sendCallResult(boolean buildSuccess, String resultTopicName, String cameraType, Long computeTime, String fileId,
-                                Integer payStatus, String projectNum, JSONObject videosJson,Map<String, String> uploadFiles,
-                                String path, Integer pushChannel, String pushToken, String prefix, Integer videoVersion){
-        rocketMQProducer.sendOneWay(resultTopicName,
+    /**
+     * 发送计算结果
+     * @param message
+     * @param buildSceneResult
+     */
+    private void sendCallResult(BuildSceneMqMessage message, BuildSceneResultBean buildSceneResult){
+        ModelingBuildStatus buildStatus = buildSceneResult.getBuildStatus();
+        //重复计算不需要发送mq做后置处理
+        if(buildStatus.equals(ModelingBuildStatus.REPEAT)){
+            return;
+        }
+        boolean buildSuccess = buildStatus.equals(ModelingBuildStatus.SUCCESS) ? true : false;
+        rocketMQProducer.sendOneWay(buildSceneResult.getResultTopicName(),
                 BuildSceneResultMqMessage.builder()
                 BuildSceneResultMqMessage.builder()
                     .buildSuccess(buildSuccess)
                     .buildSuccess(buildSuccess)
-                    .cameraType(cameraType)
-                    .computeTime(computeTime)
-                    .fileId(fileId)
-                    .payStatus(payStatus)
-                    .sceneCode(projectNum)
-                    .uploadFiles(uploadFiles)
-                    .path(path)
-                    .pushChannel(pushChannel)
-                    .pushToken(pushToken)
-                    .prefix(prefix)
-                    .videoVersion(videoVersion)
+                    .cameraType(buildSceneResult.getCameraType())
+                    .computeTime(buildSceneResult.getDuration())
+                    .fileId(buildSceneResult.getFileId())
+                    .payStatus(buildSceneResult.getPayStatus())
+                    .sceneCode(message.getSceneNum())
+                    .uploadFiles(buildSceneResult.getUploadMap())
+                    .path(buildSceneResult.getPath())
+                    .pushChannel(buildSceneResult.getPushChannel())
+                    .pushToken(buildSceneResult.getPushToken())
+                    .prefix(buildSceneResult.getPrefix())
+                    .videoVersion(buildSceneResult.getVideoVersion())
                     .build());
                     .build());
+
+        //如果是计算失败,需要发送钉钉
+        if(!buildSuccess){
+            // TODO: 2022/1/25 测试阶段,先注释掉推送
+//            this.sendDingTalkMq(buildStatus.message(), message);
+        }
     }
     }
 
 
-    private void uploadStatusJsonAndConsoleLog(Integer sceneStatus, String webSite, String projectNum,
-                                               String thumb, Integer payStatus){
+    private void writeStatusJson(Integer sceneStatus, String webSite,
+            String projectNum, String thumb, Integer payStatus){
         try{
         try{
             JSONObject statusJson = new JSONObject();
             JSONObject statusJson = new JSONObject();
             //临时将-2改成1,app还没完全更新
             //临时将-2改成1,app还没完全更新
@@ -444,7 +500,7 @@ public class BuildSceneListener implements RocketMQListener<String> {
             FileUtils.writeFile(ConstantFilePath.SCENE_PATH+"data/data"+projectNum+File.separator+"status.json", statusJson.toString());
             FileUtils.writeFile(ConstantFilePath.SCENE_PATH+"data/data"+projectNum+File.separator+"status.json", statusJson.toString());
 
 
         }catch (Exception e){
         }catch (Exception e){
-            log.error("上传status.json/console.log失败", e);
+            log.error("生成status.json失败!", e);
         }
         }
     }
     }
 
 

+ 16 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/IBuildLogService.java

@@ -0,0 +1,16 @@
+package com.fdkankan.modeling.service;
+
+import com.fdkankan.modeling.entity.BuildLog;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author 
+ * @since 2022-04-07
+ */
+public interface IBuildLogService extends IService<BuildLog> {
+
+}

+ 20 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/impl/BuildLogServiceImpl.java

@@ -0,0 +1,20 @@
+package com.fdkankan.modeling.service.impl;
+
+import com.fdkankan.modeling.entity.BuildLog;
+import com.fdkankan.modeling.mapper.IBuildLogMapper;
+import com.fdkankan.modeling.service.IBuildLogService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author 
+ * @since 2022-04-07
+ */
+@Service
+public class BuildLogServiceImpl extends ServiceImpl<IBuildLogMapper, BuildLog> implements IBuildLogService {
+
+}

+ 4 - 0
4dkankan-center-modeling/src/main/resources/bootstrap-dev.yml

@@ -12,6 +12,10 @@ spring:
             group: DEFAULT_GROUP
             group: DEFAULT_GROUP
             refresh: true
             refresh: true
         shared-configs:
         shared-configs:
+          - data-id: common-db-config.yaml
+              group: DEFAULT_GROUP
+              refresh: true
+
           - data-id: common-redis-config.yaml
           - data-id: common-redis-config.yaml
             group: DEFAULT_GROUP
             group: DEFAULT_GROUP
             refresh: true
             refresh: true

+ 8 - 12
4dkankan-center-scene/src/main/java/com/fdkankan/scene/controller/TestController.java

@@ -18,6 +18,10 @@ import com.fdkankan.scene.vo.SceneEditInfoVO;
 import com.fdkankan.scene.vo.SceneVO;
 import com.fdkankan.scene.vo.SceneVO;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Lists;
 import java.util.ArrayList;
 import java.util.ArrayList;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.beans.factory.annotation.Value;
@@ -26,6 +30,7 @@ import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.bind.annotation.RestController;
 
 
 import javax.sql.DataSource;
 import javax.sql.DataSource;
@@ -34,6 +39,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
 import java.util.UUID;
 import java.util.UUID;
+import org.springframework.web.multipart.MultipartFile;
 
 
 @RefreshScope
 @RefreshScope
 @RestController
 @RestController
@@ -73,8 +79,8 @@ public class TestController {
     RedisLockUtil redisLockUtil;
     RedisLockUtil redisLockUtil;
 
 
 
 
-    @GetMapping("/test")
-    public String test(String path, String buildType) throws Exception {
+    @PostMapping("/test")
+    public String test(String aaa) throws Exception {
 
 
 //        JSONObject dataJson = new JSONObject();
 //        JSONObject dataJson = new JSONObject();
 //        dataJson.put("obj2txt", true);
 //        dataJson.put("obj2txt", true);
@@ -92,16 +98,6 @@ public class TestController {
 
 
 //        folderService.list();
 //        folderService.list();
 
 
-        List<SceneEditInfoVO> list = new ArrayList<>();
-        for (int i = 0; i < 10000000; i++){
-            list.add(SceneEditInfoVO.builder().num("aaa" + i)
-                .description("123adfffffffffffffffffffffffffffffffffasdfadhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhsfvhbsfghsdfgdfgrdg").build());
-        }
-
-
-        Thread.sleep(50000000);
-
-
 
 
         return "123";
         return "123";
 
 

+ 42 - 11
4dkankan-center-scene/src/main/java/com/fdkankan/scene/listener/BuildScenePreMQListener.java

@@ -1,12 +1,15 @@
 package com.fdkankan.scene.listener;
 package com.fdkankan.scene.listener;
 
 
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.common.constant.ModelingBuildStatus;
 import com.fdkankan.common.util.SceneUtil;
 import com.fdkankan.common.util.SceneUtil;
 import com.fdkankan.fyun.oss.UploadToOssUtil;
 import com.fdkankan.fyun.oss.UploadToOssUtil;
 import com.fdkankan.mq.message.BuildSceneMqMessage;
 import com.fdkankan.mq.message.BuildSceneMqMessage;
 import com.fdkankan.mq.util.RocketMQProducer;
 import com.fdkankan.mq.util.RocketMQProducer;
 import com.fdkankan.platform.api.feign.PlatformGoodsClient;
 import com.fdkankan.platform.api.feign.PlatformGoodsClient;
 import com.fdkankan.platform.api.feign.PlatformUserClient;
 import com.fdkankan.platform.api.feign.PlatformUserClient;
+import com.fdkankan.redis.constant.RedisKey;
+import com.fdkankan.redis.util.RedisUtil;
 import com.fdkankan.scene.service.IBuildScenePreService;
 import com.fdkankan.scene.service.IBuildScenePreService;
 import com.fdkankan.scene.service.ISceneEditControlsService;
 import com.fdkankan.scene.service.ISceneEditControlsService;
 import com.fdkankan.scene.service.ISceneEditInfoService;
 import com.fdkankan.scene.service.ISceneEditInfoService;
@@ -14,10 +17,15 @@ import com.fdkankan.scene.service.ISceneFileBuildService;
 import com.fdkankan.scene.service.ISceneProExtService;
 import com.fdkankan.scene.service.ISceneProExtService;
 import com.fdkankan.scene.service.ISceneProService;
 import com.fdkankan.scene.service.ISceneProService;
 import com.fdkankan.scene.service.ISceneService;
 import com.fdkankan.scene.service.ISceneService;
+import java.time.Duration;
+import java.time.temporal.ChronoUnit;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.spring.annotation.MessageModel;
+import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
 import org.apache.rocketmq.spring.core.RocketMQListener;
 import org.apache.rocketmq.spring.core.RocketMQListener;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
 
 
 
 
 /**
 /**
@@ -28,14 +36,14 @@ import org.springframework.beans.factory.annotation.Value;
  * @date 2022/2/23
  * @date 2022/2/23
  **/
  **/
 @Slf4j
 @Slf4j
-//@Component
-//@RocketMQMessageListener(
-//        consumerGroup = "${rocketmq.consumer.build-scene-pre-group}",
-//        topic = "${rocketmq.build-scene.topicName.topic-modeling-a-pre}",
-//        messageModel = MessageModel.CLUSTERING,//负载均衡模式
-//        consumeThreadMax = 10,
-//        consumeTimeout = 172801000L
-//)
+@Component
+@RocketMQMessageListener(
+        consumerGroup = "${rocketmq.consumer.build-scene-pre-group}",
+        topic = "${rocketmq.build-scene.topicName.topic-modeling-a-pre}",
+        messageModel = MessageModel.CLUSTERING,//负载均衡模式
+        consumeThreadMax = 10,
+        consumeTimeout = 172801000L
+)
 public class BuildScenePreMQListener implements RocketMQListener<String> {
 public class BuildScenePreMQListener implements RocketMQListener<String> {
 
 
 
 
@@ -72,6 +80,11 @@ public class BuildScenePreMQListener implements RocketMQListener<String> {
     private RocketMQProducer producer;
     private RocketMQProducer producer;
     @Value("${rocketmq.build-scene.topicName.topic-modeling-a}")
     @Value("${rocketmq.build-scene.topicName.topic-modeling-a}")
     private String topicName;
     private String topicName;
+    @Autowired
+    RedisUtil redisUtil;
+
+    @Value("${model.timeOut:48}")
+    private int modelTimeOut;
 
 
 
 
     @Override
     @Override
@@ -88,7 +101,18 @@ public class BuildScenePreMQListener implements RocketMQListener<String> {
     }
     }
 
 
     private void process(BuildSceneMqMessage message){
     private void process(BuildSceneMqMessage message){
+        boolean success = false;
+        String reason = null;
         try {
         try {
+            String key = RedisKey.SCENE_BUILDING + message.getSceneNum();
+            Long building = redisUtil.incr(key, 1);
+            if (building.compareTo(1L) != 0) {
+                log.error("场景正在构建中,退出构建,参数:{}", JSONObject.toJSONString(message));
+                reason = "重复计算";
+            } else {
+                redisUtil.expire(key, Duration.of(modelTimeOut, ChronoUnit.HOURS));
+            }
+
             //根据相机类型,组装资源路径
             //根据相机类型,组装资源路径
             String path = SceneUtil.getPath(message.getPath(), message.getCameraName(),
             String path = SceneUtil.getPath(message.getPath(), message.getCameraName(),
                 message.getFileId(), Integer.parseInt(message.getCameraType()), message.getUnicode());
                 message.getFileId(), Integer.parseInt(message.getCameraType()), message.getUnicode());
@@ -99,13 +123,20 @@ public class BuildScenePreMQListener implements RocketMQListener<String> {
             //发送mq,就进行计算
             //发送mq,就进行计算
             producer.syncSend(topicName, message);
             producer.syncSend(topicName, message);
 
 
+            success = true;
+
             log.info("场景计算前置处理完成,场景码:{}", message.getSceneNum());
             log.info("场景计算前置处理完成,场景码:{}", message.getSceneNum());
 
 
         }catch (Exception e){
         }catch (Exception e){
             log.error("场景计算前置处理出错", e);
             log.error("场景计算前置处理出错", e);
-            //发送钉钉
-            String serverPath = message.getPath().substring(0,message.getPath().lastIndexOf("/")+1).concat(message.getPrefix());
-//            buildScenePreService.handFail("前置处理失败", serverPath, message.getSceneNum(), BuildScenePreServiceImpl.hostName, null);
+            reason = "场景计算前置处理出错";
+        }finally {
+            //如果前置处理失败,发送钉钉消息
+            if(!success){
+                String serverPath = message.getPath().substring(0,message.getPath().lastIndexOf("/")+1).concat(message.getPrefix());
+//            buildScenePreService.handFail(reason, serverPath, message.getSceneNum(), BuildScenePreServiceImpl.hostName, null);
+            }
+
         }
         }
     }
     }
 
 

+ 9 - 6
4dkankan-center-scene/src/main/java/com/fdkankan/scene/listener/BuildSceneResultMQListener.java

@@ -45,12 +45,15 @@ import java.util.Calendar;
 import java.util.Map;
 import java.util.Map;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.spring.annotation.MessageModel;
+import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
 import org.apache.rocketmq.spring.core.RocketMQListener;
 import org.apache.rocketmq.spring.core.RocketMQListener;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.beans.factory.annotation.Value;
 
 
 import java.util.List;
 import java.util.List;
 import java.util.Objects;
 import java.util.Objects;
+import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
 
 
 
 
@@ -62,12 +65,12 @@ import org.springframework.transaction.annotation.Transactional;
  * @date 2022/2/23
  * @date 2022/2/23
  **/
  **/
 @Slf4j
 @Slf4j
-//@Component
-//@RocketMQMessageListener(
-//        consumerGroup = "${rocketmq.consumer.build-scene-result-group}",
-//        topic = "${rocketmq.build-scene-result.topicName.topic-modeling-a}",
-//        messageModel = MessageModel.CLUSTERING//负载均衡模式
-//)
+@Component
+@RocketMQMessageListener(
+        consumerGroup = "${rocketmq.consumer.build-scene-result-group}",
+        topic = "${rocketmq.build-scene-result.topicName.topic-modeling-a}",
+        messageModel = MessageModel.CLUSTERING//负载均衡模式
+)
 public class BuildSceneResultMQListener implements RocketMQListener<String> {
 public class BuildSceneResultMQListener implements RocketMQListener<String> {
 
 
     @Value("${rocketmq.consumer.build-scene-result-group}")
     @Value("${rocketmq.consumer.build-scene-result-group}")

+ 9 - 10
4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/impl/BuildScenePreServiceImpl.java

@@ -348,21 +348,20 @@ public class BuildScenePreServiceImpl implements IBuildScenePreService {
     @Override
     @Override
     public void uploadLogFile(String num, String dataSource) {
     public void uploadLogFile(String num, String dataSource) {
         String dataPath = String.format(UploadFilePath.DATA_VIEW_PATH, num);
         String dataPath = String.format(UploadFilePath.DATA_VIEW_PATH, num);
+        String buildLogPath = String.format(UploadFilePath.BUILD_LOG_PATH, num);
 
 
         //todo 待删除old_path
         //todo 待删除old_path
-        uploadToOssUtil.upload(ConstantFilePath.SCENE_PATH+"data/data"+num+File.separator+"status.json",
-            "data/data"+num+File.separator+"status.json");
+        uploadToOssUtil.upload(
+            ConstantFilePath.SCENE_PATH + "data/data" + num + File.separator + "status.json",
+            "data/data" + num + File.separator + "status.json");
 
 
-        uploadToOssUtil.upload(ConstantFilePath.SCENE_PATH+"data/data"+num+File.separator+"status.json",
-            dataPath+"status.json");
+        uploadToOssUtil.upload(
+            ConstantFilePath.SCENE_PATH + "data/data" + num + File.separator + "status.json",
+            dataPath + "status.json");
 
 
-        //上送日志  //todo 待删除old_path
-        uploadToOssUtil.upload(dataSource+File.separator+"console.log",
-            "build_log/"+num+File.separator+"console.log");
+        uploadToOssUtil.upload(dataSource + File.separator + "console.log",
+            buildLogPath + "console.log");
 
 
-        //上送日志
-        uploadToOssUtil.upload(dataSource+File.separator+"console.log",
-            dataPath+"console.log");
     }
     }
 
 
     @Override
     @Override

+ 21 - 0
4dkankan-common/src/main/java/com/fdkankan/common/exception/GlobalExceptionHandler.java

@@ -6,21 +6,25 @@ import com.fdkankan.common.constant.ErrorCode;
 import com.fdkankan.common.constant.ServerCode;
 import com.fdkankan.common.constant.ServerCode;
 import com.fdkankan.common.response.ResultData;
 import com.fdkankan.common.response.ResultData;
 import java.util.List;
 import java.util.List;
+import java.util.Map;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpServletResponse;
 import javax.xml.transform.Result;
 import javax.xml.transform.Result;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.catalina.Server;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.HttpStatus;
 import org.springframework.validation.BindException;
 import org.springframework.validation.BindException;
 import org.springframework.validation.BindingResult;
 import org.springframework.validation.BindingResult;
 import org.springframework.validation.FieldError;
 import org.springframework.validation.FieldError;
 import org.springframework.validation.ObjectError;
 import org.springframework.validation.ObjectError;
 import org.springframework.web.bind.MethodArgumentNotValidException;
 import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.MissingServletRequestParameterException;
 import org.springframework.web.bind.annotation.ControllerAdvice;
 import org.springframework.web.bind.annotation.ControllerAdvice;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.bind.annotation.ResponseStatus;
 import org.springframework.web.bind.annotation.ResponseStatus;
 import org.springframework.web.bind.annotation.RestControllerAdvice;
 import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.multipart.MultipartException;
 import org.springframework.web.servlet.NoHandlerFoundException;
 import org.springframework.web.servlet.NoHandlerFoundException;
 
 
 /**
 /**
@@ -62,6 +66,23 @@ public class GlobalExceptionHandler {
 //        return ResultData.error(ServerCode.SYSTEM_ERROR.code(), "系统繁忙,请稍后重试");
 //        return ResultData.error(ServerCode.SYSTEM_ERROR.code(), "系统繁忙,请稍后重试");
 //    }
 //    }
 
 
+    @ResponseBody
+    @ExceptionHandler(value = MissingServletRequestParameterException.class)
+    public ResultData missingServletRequestParameterException(
+        MissingServletRequestParameterException e){
+        return ResultData.error(
+            ServerCode.PARAM_REQUIRED.code(),
+            ServerCode.PARAM_REQUIRED.formatMessage(e.getParameterName()));
+    }
+
+    @ResponseBody
+    @ExceptionHandler(value = MultipartException.class)
+    public ResultData multipartException(MultipartException e){
+        return ResultData.error(
+            ServerCode.PARAM_REQUIRED.code(),
+            ServerCode.PARAM_REQUIRED.formatMessage("文件"));
+    }
+
 
 
     /**
     /**
      * 校验错误拦截处理
      * 校验错误拦截处理

+ 3 - 1
4dkankan-common/src/main/java/com/fdkankan/common/response/BaseResponseAdvice.java

@@ -25,7 +25,9 @@ public class BaseResponseAdvice implements ResponseBodyAdvice<Object> {
     }
     }
 
 
     @Override
     @Override
-    public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
+    public Object beforeBodyWrite(Object body, MethodParameter methodParameter,
+        MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass,
+        ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
 //        if(serverHttpRequest.getURI().getPath().contains("feign")){
 //        if(serverHttpRequest.getURI().getPath().contains("feign")){
 //            return body;
 //            return body;
 //        }
 //        }