root há 2 anos atrás
pai
commit
2f0d039333

+ 1 - 1
api-common/src/main/java/api/common/util/TimeUtil.java

@@ -65,7 +65,7 @@ public class TimeUtil {
         Date d = c.getTime();
         String startDate = getToStringDate(d, 2) + " 00:00:00";
         String endDate = getToStringDate(d, 2) + " 23:59:59";
-        Map<String, Object> map = new HashMap();
+        Map<String, Object> map = new HashMap<>();
         map.put("startDate", startDate);
         map.put("endDate", endDate);
         map.put("toDate", getToStringDate(d, 2));

+ 3 - 1
simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/common/configuration/init/MyApplicationRunner.java

@@ -1,14 +1,16 @@
 package com.css.simulation.resource.scheduler.common.configuration.init;
 
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.boot.ApplicationArguments;
 import org.springframework.boot.ApplicationRunner;
 import org.springframework.stereotype.Component;
 
 @Component
+@Slf4j
 public class MyApplicationRunner implements ApplicationRunner {
 
     @Override
     public void run(ApplicationArguments args) {
-        System.out.println("ApplicationRunner");
+        log.info("应用启动了。");
     }
 }

+ 14 - 47
simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/common/util/ProjectUtil.java

@@ -370,7 +370,7 @@ public class ProjectUtil {
                 clusterId = clusterMapper.selectByUserId(parentUserId).getId();
             }
         } else {
-            throw new RuntimeException("ProjectUtil--getRedisPrefixByUserIdAndProjectIdAndTaksId 未知账户类型,无法获取集群信息!");
+            throw new RuntimeException("未知账户类型,无法获取集群信息。");
         }
         String clusterPrefix = "cluster:" + clusterId;
         String clusterRunningPrefix = clusterPrefix + ":running";
@@ -393,44 +393,6 @@ public class ProjectUtil {
     }
 
 
-    public PrefixTO getRedisPrefixByUserIdAndProjectId(String userId, String projectId) {
-        //3 获取用户类型(管理员账户、管理员子账户、普通账户、普通子账户)(独占、共享)
-        UserPO userPO = userMapper.selectById(userId);
-        String roleCode = userPO.getRoleCode();
-        String useType = userPO.getUseType();
-        String clusterId;
-        if (DictConstants.ROLE_CODE_SYSADMIN.equals(roleCode) || DictConstants.ROLE_CODE_ADMIN.equals(roleCode)) {  //3-1 管理员账户和管理员子账户直接执行
-            clusterId = DictConstants.SYSTEM_CLUSTER_ID;
-        } else if (DictConstants.ROLE_CODE_UESR.equals(roleCode)) { //3-2 普通账户,不管是独占还是共享,都在自己的集群里排队,根据自己的独占节点排队
-            clusterId = clusterMapper.selectByUserId(userId).getId();
-        } else if (DictConstants.ROLE_CODE_SUBUESR.equals(roleCode)) {
-            if (DictConstants.USER_TYPE_EXCLUSIVE.equals(useType)) {   //3-3 普通子账户,根据自己的独占节点排队
-                clusterId = clusterMapper.selectByUserId(userId).getId();
-            } else {    //3-4 共享子账户,根据父账户的共享节点排队
-                String parentUserId = userPO.getCreateUserId();
-                clusterId = clusterMapper.selectByUserId(parentUserId).getId();
-            }
-        } else {
-            throw new RuntimeException("ProjectUtil--getRedisPrefixByUserIdAndProjectIdAndTaksId 未知账户类型,无法获取集群信息!");
-        }
-        String clusterPrefix = "cluster:" + clusterId;
-        String clusterRunningPrefix = clusterPrefix + ":running";
-        String clusterWaitingPrefix = clusterPrefix + ":waiting";
-        String projectRunningKey = clusterRunningPrefix + ":" + projectId;
-        String projectWaitingKey = clusterWaitingPrefix + ":" + projectId;
-        String projectCheckKey = projectRunningKey + ":check";
-
-        return PrefixTO.builder()
-                .clusterPrefix(clusterPrefix)
-                .clusterRunningPrefix(clusterRunningPrefix)
-                .clusterWaitingPrefix(clusterWaitingPrefix)
-                .projectRunningKey(projectRunningKey)
-                .projectWaitingKey(projectWaitingKey)
-                .projectCheckKey(projectCheckKey)
-                .build();
-    }
-
-
     public PrefixTO getRedisPrefixByClusterIdAndProjectId(String clusterId, String projectId) {
         String clusterPrefix = "cluster:" + clusterId;
         String clusterRunningPrefix = clusterPrefix + ":running";
@@ -461,10 +423,6 @@ public class ProjectUtil {
         return clusterRunningKeySet.stream().filter(key -> StringUtil.countSubString(key, ":") == 3).collect(Collectors.toList());
     }
 
-    public void sendMessage(String topic, String message) {
-        kafkaTemplate.send(topic, message);
-    }
-
 
     public PrefixTO getRedisPrefixByProjectIdAndProjectType(String projectId, String projectType) {
         String userId;
@@ -473,7 +431,7 @@ public class ProjectUtil {
         } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
             userId = autoSubProjectMapper.selectCreateUserById(projectId);
         } else {
-            throw new RuntimeException("getRedisPrefixByProjectIdAndProjectType() 未知的项目类型!");
+            throw new RuntimeException("未知的项目类型。");
         }
 
         //3 获取用户类型(管理员账户、管理员子账户、普通账户、普通子账户)(独占、共享)
@@ -493,7 +451,7 @@ public class ProjectUtil {
                 clusterId = clusterMapper.selectByUserId(parentUserId).getId();
             }
         } else {
-            throw new RuntimeException("ProjectUtil--getRedisPrefixByUserIdAndProjectIdAndTaksId 未知账户类型,无法获取集群信息!");
+            throw new RuntimeException("未知账户类型,无法获取集群信息!");
         }
         String clusterPrefix = "cluster:" + clusterId;
         String clusterRunningPrefix = clusterPrefix + ":running";
@@ -522,14 +480,23 @@ public class ProjectUtil {
         String key = "node:" + nodeName + ":parallelism";
         String parallelismString = stringRedisTemplate.opsForValue().get(key);
         if (StringUtil.isEmpty(parallelismString)) {
-            throw new RuntimeException("addOneParallelismToNode() redisKey " + key + " 为空。");
+            throw new RuntimeException("redisKey " + key + " 为空。");
         }
         final int parallelismBefore = Integer.parseInt(parallelismString);
         final int parallelismAfter = parallelismBefore + 1;
         stringRedisTemplate.opsForValue().set(key, parallelismAfter + "");
-        log.info("addOneParallelismToNode() 归还节点 " + nodeName + " 并行度:" + parallelismBefore + " --> " + parallelismAfter);
+        log.info("归还节点 " + nodeName + " 并行度:" + parallelismBefore + " --> " + parallelismAfter);
     }
 
+    public void parallelismAddOne(String nodeName){
+
+    }
+
+    public void parallelismReduceOne(String nodeName){
+
+    }
+
+
     public List<String> getWaitingProjectMessageKeys() {
         final Set<String> keys = stringRedisTemplate.keys("*");
         if (CollectionUtil.isEmpty(keys)) {

+ 1 - 1
simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/dao/manager/TaskManager.java

@@ -158,7 +158,7 @@ public class TaskManager {
                     String isChoiceGpu = projectUtil.getProjectByProjectId(projectId).getIsChoiceGpu();
                     log.info("项目 " + projectId + " 是否需要生成 gpu 视频( 0是 1否 ):" + isChoiceGpu);
                     if ("1".equals(isChoiceGpu)) {
-                        final Boolean success = stringRedisTemplate.opsForValue().setIfAbsent("task:" + taskId + ":generateVideo:", "1");   // 分布式锁
+                        final Boolean success = stringRedisTemplate.opsForValue().setIfAbsent("project:" + projectId + ":task:" + taskId + ":generateVideo:", "1");   // 分布式锁
                         if (Boolean.TRUE.equals(success)) {
                             FutureTask<ResponseBodyVO<String>> videoTask = new FutureTask<>(() -> videoService.generateVideo(projectId, projectType, maxSimulationTime, taskId));
                             new Thread(videoTask, "generateVideo-" + StringUtil.getRandomEightBitUUID()).start();

+ 1 - 1
simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/service/TaskService.java

@@ -57,7 +57,7 @@ public class TaskService {
         SshClient sshClient = SshUtil.getClient();
         ClientSession clientSession = SshUtil.getSession(sshClient, hostname, username, password);
         //2 准备打分
-        log.info("TaskService--taskState 项目 " + projectId + "准备打分!");
+        log.info("项目 " + projectId + "准备打分!");
         taskManager.prepareScore(redisPrefix.getProjectRunningKey());
         //3 打分
         taskManager.score(redisPrefix, userId, projectId, projectType, clientSession);

+ 2 - 28
simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/web/scheduler/ClusterScheduler.java

@@ -1,14 +1,9 @@
 package com.css.simulation.resource.scheduler.web.scheduler;
 
-import api.common.pojo.constants.DictConstants;
 import api.common.util.CollectionUtil;
 import com.css.simulation.resource.scheduler.common.configuration.kubernetes.KubernetesConfiguration;
-import com.css.simulation.resource.scheduler.dao.mapper.AutoSubProjectMapper;
-import com.css.simulation.resource.scheduler.dao.mapper.ManualProjectMapper;
-import com.css.simulation.resource.scheduler.dao.entity.ProjectPO;
-import com.css.simulation.resource.scheduler.service.domain.KubernetesNodeTO;
 import com.css.simulation.resource.scheduler.common.util.KubernetesUtil;
-import com.css.simulation.resource.scheduler.common.util.RedisUtil;
+import com.css.simulation.resource.scheduler.service.domain.KubernetesNodeTO;
 import io.kubernetes.client.openapi.ApiClient;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
@@ -30,10 +25,6 @@ public class ClusterScheduler {
     private ApiClient apiClient;
     @Resource
     private StringRedisTemplate stringRedisTemplate;
-    @Resource
-    private ManualProjectMapper manualProjectMapper;
-    @Resource
-    private AutoSubProjectMapper autoSubProjectMapper;
 
     /**
      * 闲时重置所有并行度
@@ -47,25 +38,8 @@ public class ClusterScheduler {
             for (KubernetesNodeTO kubernetesNodeTO : initialNodeList) {
                 stringRedisTemplate.opsForValue().set("node:" + kubernetesNodeTO.getName() + ":parallelism", kubernetesNodeTO.getMaxParallelism() + "");
             }
-            log.info("initNodeParallelism() 重置节点并行度为:" + initialNodeList);
+            log.info("重置节点并行度为:" + initialNodeList);
         }
 
     }
-
-    /**
-     * 闲时删除 cluster 所有遗留数据
-     */
-    @Scheduled(fixedDelay = 2 * 60 * 1000)
-    @SneakyThrows
-    public void removeCluster() {
-        //1 查询是否有正在运行的项目
-        List<ProjectPO> manual = manualProjectMapper.selectByNowRunState(DictConstants.PROJECT_RUNNING);
-        List<ProjectPO> autoSub = autoSubProjectMapper.selectByNowRunState(DictConstants.PROJECT_RUNNING);
-
-        //2 如果没有正在运行的项目,则删除redis
-        if (CollectionUtil.isEmpty(manual) && CollectionUtil.isEmpty(autoSub)) {
-            RedisUtil.deleteByPrefix(stringRedisTemplate, "cluster:");
-            log.info("removeCluster() 清除 redis 中因错误残留的 cluster 数据。");
-        }
-    }
 }

+ 5 - 5
simulation-resource-scheduler/src/main/resources/logback-spring.xml

@@ -21,7 +21,7 @@
             <level>debug</level>
         </filter>
         <encoder>
-            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{5}).%M\(%F:%L\) %highlight(%msg) %n</pattern>
             <charset>utf-8</charset>
         </encoder>
     </appender>
@@ -38,7 +38,7 @@
         </rollingPolicy>
         <append>true</append>
         <encoder>
-            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{5}).%M\(%F:%L\) %highlight(%msg) %n</pattern>
             <charset>utf-8</charset>
         </encoder>
         <filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印DEBUG日志 -->
@@ -60,7 +60,7 @@
         </rollingPolicy>
         <append>true</append>
         <encoder>
-            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{5}).%M\(%F:%L\) %highlight(%msg) %n</pattern>
             <charset>utf-8</charset>
         </encoder>
         <filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印INFO日志 -->
@@ -82,7 +82,7 @@
         </rollingPolicy>
         <append>true</append>
         <encoder>
-            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{5}).%M\(%F:%L\) %highlight(%msg) %n</pattern>
             <charset>utf-8</charset>
         </encoder>
         <filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印ERROR日志 -->
@@ -104,7 +104,7 @@
         </rollingPolicy>
         <append>true</append>
         <encoder>
-            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{5}).%M\(%F:%L\) %highlight(%msg) %n</pattern>
             <charset>utf-8</charset>
         </encoder>
         <filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印WARN日志 -->

+ 21 - 21
simulation-resource-video/src/main/java/com/css/simulation/resource/video/controller/VideoController.java

@@ -2,7 +2,6 @@ package com.css.simulation.resource.video.controller;
 
 import api.common.pojo.common.ResponseBodyVO;
 import api.common.pojo.po.scene.VehicleTypePO;
-import api.common.pojo.vo.scene.SceneAccidentVO;
 import api.common.util.LinuxUtil;
 import com.css.simulation.resource.video.service.VideoService;
 import lombok.extern.slf4j.Slf4j;
@@ -16,16 +15,16 @@ import java.io.IOException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
+
 @Slf4j
 @RestController
 public class VideoController {
 
     @Resource
-    VideoService videoService;
+    private VideoService videoService;
     @Value("${scheduler.video-test-command}")
-    String testCommand;
+    private String testCommand;
 
 
     /**
@@ -38,7 +37,8 @@ public class VideoController {
             @RequestParam("maxSimulationTime") String maxSimulationTime,
             @RequestParam("taskId") String taskId
     ) {
-        return videoService.generateVideo(projectId, projectType, maxSimulationTime,taskId);
+        log.info("收到项目 " + projectId + " 的任务" + taskId + " 生成 cpu 视频的请求。");
+        return videoService.generateVideo(projectId, projectType, maxSimulationTime, taskId);
     }
 
 
@@ -54,10 +54,10 @@ public class VideoController {
 
     @RequestMapping(value = "/uploadToLocal")
     @ResponseBody
-    public ResponseBodyVO<Map<String,String>> uploadToLocal(@RequestBody MultipartFile file){
+    public ResponseBodyVO<Map<String, String>> uploadToLocal(@RequestBody MultipartFile file) {
         // 获取文件原本的名字
         String originName = file.getOriginalFilename();
-       String fileName=originName.substring(0,originName.lastIndexOf("."));
+        String fileName = originName.substring(0, originName.lastIndexOf("."));
 /*        // 判断文件是否是pdf文件
         Set<String> set = new HashSet<>();
         set.add(".pdf");
@@ -78,37 +78,37 @@ public class VideoController {
             return new ResponseBodyVO(ResponseBodyVO.Response.CLIENT_FAILURE, "上传的文件类型错误,只能上传osgb类型的文件");
         }*/
         // 创建保存路径
-       //日期格式
+        //日期格式
         SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSS");
         String format = sdf.format(new Date());
-       // String savePath = System.getProperty("user.dir") + "\\" + "files" +   "\\" + fileType + "\\" + format;
-       // 保存文件的文件夹
-       //String savePath="C:/Users/CSS/Desktop/ive转osgb/20220919";
-        String savePath="/root/disk1/simulation-cloud/esmini/resources/models/"+fileName+"/"+ format;
+        // String savePath = System.getProperty("user.dir") + "\\" + "files" +   "\\" + fileType + "\\" + format;
+        // 保存文件的文件夹
+        //String savePath="C:/Users/CSS/Desktop/ive转osgb/20220919";
+        String savePath = "/root/disk1/simulation-cloud/esmini/resources/models/" + fileName + "/" + format;
         log.info("车辆模型对应osgb地址:" + savePath);
         File folder = new File(savePath);
         // 判断路径是否存在,不存在则自动创建
-        if(!folder.exists()){
+        if (!folder.exists()) {
             folder.mkdirs();
         }
         String saveName = originName;
         try {
-            file.transferTo(new File(folder,saveName));
-            Map<String,String> map =new HashMap<>();
+            file.transferTo(new File(folder, saveName));
+            Map<String, String> map = new HashMap<>();
             String filePath = savePath + "/" + saveName;
-           // return new String("文件路径为:" + filePath);
-            map.put("filePath",filePath);
+            // return new String("文件路径为:" + filePath);
+            map.put("filePath", filePath);
             return new ResponseBodyVO(ResponseBodyVO.Response.SUCCESS, map);
-        } catch (IOException e){
+        } catch (IOException e) {
             return new ResponseBodyVO(ResponseBodyVO.Response.SERVER_FAILURE, e.getMessage());
-          //  return new String(e.getMessage());
+            //  return new String(e.getMessage());
         }
     }
 
     @RequestMapping(value = "/test1")
     @ResponseBody
-    public ResponseBodyVO<VehicleTypePO> test1(@RequestBody Map<String,String> map) {
-        VehicleTypePO po= videoService.vehicleById(map.get("projectId"),map.get("projectType"));
+    public ResponseBodyVO<VehicleTypePO> test1(@RequestBody Map<String, String> map) {
+        VehicleTypePO po = videoService.vehicleById(map.get("projectId"), map.get("projectType"));
         return new ResponseBodyVO(ResponseBodyVO.Response.SUCCESS, po);
     }
 

+ 2 - 2
simulation-resource-video/src/main/java/com/css/simulation/resource/video/service/VideoService.java

@@ -95,13 +95,13 @@ public class VideoService {
         //3 生成 xosc 文件
         String xoscPath = generateXosc(rootDirectoryPathOfLinux, xodrPathOfLinux, osgbPathOfLinux, projectId, projectType);
         // 启动虚拟窗口
-        log.info("生成 xosc 文件路径-----" + xoscPath);
+        log.info("生成 xosc 文件路径" + xoscPath);
         //4 生成图片
         String pictureDirectoryPath = rootDirectoryPathOfLinux + "picture";
         FileUtil.createDirectory(pictureDirectoryPath);
         String esminiCommandTemp = esminiCommand + " " + xoscPath + " " + pictureDirectoryPath + "/screenshot " + StringUtil.doubleToString(Double.parseDouble(maxSimulationTime), 2);
         LinuxUtil.execute2(XvfbCommand, esminiCommandTemp);
-        LinuxUtil.kill(esminiCommandTemp);  // 执行完许哟啊手动删除 esmini 进程
+        LinuxUtil.kill(esminiCommandTemp);  // 执行完手动删除 esmini 进程
 //        String esminiResult = LinuxUtil.execute(esminiCommandTemp);
         int num = 14;
         for (int i = 0; i < num; i++) {

+ 6 - 15
simulation-resource-video/src/main/resources/logback-spring.xml

@@ -13,6 +13,7 @@
     <springProfile name="test">
         <property name="LOG_HOME" value="./log"/>
     </springProfile>
+
     <!--输出到控制台-->
     <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
         <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
@@ -20,9 +21,7 @@
             <level>debug</level>
         </filter>
         <encoder>
-            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{5}).%M\(%F:%L\)
-                %highlight(%msg) %n
-            </pattern>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{5}).%M\(%F:%L\) %highlight(%msg) %n</pattern>
             <charset>utf-8</charset>
         </encoder>
     </appender>
@@ -39,9 +38,7 @@
         </rollingPolicy>
         <append>true</append>
         <encoder>
-            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{5}).%M\(%F:%L\)
-                %highlight(%msg) %n
-            </pattern>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{5}).%M\(%F:%L\) %highlight(%msg) %n</pattern>
             <charset>utf-8</charset>
         </encoder>
         <filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印DEBUG日志 -->
@@ -63,9 +60,7 @@
         </rollingPolicy>
         <append>true</append>
         <encoder>
-            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{5}).%M\(%F:%L\)
-                %highlight(%msg) %n
-            </pattern>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{5}).%M\(%F:%L\) %highlight(%msg) %n</pattern>
             <charset>utf-8</charset>
         </encoder>
         <filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印INFO日志 -->
@@ -87,9 +82,7 @@
         </rollingPolicy>
         <append>true</append>
         <encoder>
-            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{5}).%M\(%F:%L\)
-                %highlight(%msg) %n
-            </pattern>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{5}).%M\(%F:%L\) %highlight(%msg) %n</pattern>
             <charset>utf-8</charset>
         </encoder>
         <filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印ERROR日志 -->
@@ -111,9 +104,7 @@
         </rollingPolicy>
         <append>true</append>
         <encoder>
-            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{5}).%M\(%F:%L\)
-                %highlight(%msg) %n
-            </pattern>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{5}).%M\(%F:%L\) %highlight(%msg) %n</pattern>
             <charset>utf-8</charset>
         </encoder>
         <filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印WARN日志 -->