瀏覽代碼

1、解决多线程异常问题。

jessie 5 年之前
父節點
當前提交
ebfc095da2

+ 6 - 2
src/main/java/com/pavis/ai/app/fjsocrasy/common/config/AsyncConfig.java

@@ -23,11 +23,13 @@ public class AsyncConfig {
         //最大线程数5:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
         executor.setMaxPoolSize(5);
         //缓冲队列180:用来缓冲执行任务的队列
-        executor.setQueueCapacity(10);
+        executor.setQueueCapacity(200);
         //允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
         executor.setKeepAliveSeconds(60);
         //线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
         executor.setThreadNamePrefix("Async-OcrFjs-");
+        // 原因:导致调用线程(可能是主线程)等待,直到阻塞队列中有空间为止。解决方法:RejectedExecutionHandlerImpl
+        executor.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
         executor.initialize();
         return executor;
     }
@@ -40,11 +42,13 @@ public class AsyncConfig {
         //最大线程数5:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
         executor.setMaxPoolSize(10);
         //缓冲队列180:用来缓冲执行任务的队列
-        executor.setQueueCapacity(10);
+        executor.setQueueCapacity(200);
         //允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
         executor.setKeepAliveSeconds(60);
         //线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
         executor.setThreadNamePrefix("Async-LinkFjs-");
+        // 原因:导致调用线程(可能是主线程)等待,直到阻塞队列中有空间为止。解决方法:RejectedExecutionHandlerImpl
+        executor.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
         executor.initialize();
         return executor;
     }

+ 23 - 0
src/main/java/com/pavis/ai/app/fjsocrasy/common/config/RejectedExecutionHandlerImpl.java

@@ -0,0 +1,23 @@
+package com.pavis.ai.app.fjsocrasy.common.config;
+
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * @author guanhuijuan
+ * @create 2020-07-13 14:36
+ * @desc RejectedExecutionHandlerImpl
+ **/
+public class RejectedExecutionHandlerImpl implements RejectedExecutionHandler {
+    @Override
+    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
+        try {
+            // based on the BlockingQueue documentation below should block until able to place on the queue...
+            executor.getQueue().put(r);
+        }
+        catch (InterruptedException e) {
+            throw new RejectedExecutionException("Unexpected InterruptedException while waiting to add Runnable to ThreadPoolExecutor queue...", e);
+        }
+    }
+}

+ 24 - 0
src/main/java/com/pavis/ai/app/fjsocrasy/common/utils/test/TestAsync.java

@@ -0,0 +1,24 @@
+package com.pavis.ai.app.fjsocrasy.common.utils.test;
+
+import com.pavis.ai.app.fjsocrasy.form.FileDetails;
+import lombok.*;
+
+import java.util.List;
+
+/**
+ * @author guanhuijuan
+ * @create 2020-07-09 11:18
+ * @desc
+ **/
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class TestAsync {
+    private String reqId;
+    private String fileType;
+    private String data;
+    private Long startTime;
+    private List<FileDetails> parsedFilePaths;
+}

+ 50 - 9
src/main/java/com/pavis/ai/app/fjsocrasy/controller/BackController.java

@@ -8,6 +8,8 @@ import com.pavis.ai.app.fjsocrasy.common.config.properties.CommonProperties;
 import com.pavis.ai.app.fjsocrasy.common.http.ResultBody;
 import com.pavis.ai.app.fjsocrasy.common.utils.DateUtils;
 import com.pavis.ai.app.fjsocrasy.common.utils.ocr.GeneralUtils;
+import com.pavis.ai.app.fjsocrasy.common.utils.test.TestAsync;
+import com.pavis.ai.app.fjsocrasy.form.FileDetails;
 import com.pavis.ai.app.fjsocrasy.form.ProVersion;
 import com.pavis.ai.app.fjsocrasy.form.SendData;
 import com.pavis.ai.app.fjsocrasy.form.res.ResData;
@@ -262,6 +264,24 @@ public class BackController {
         return ResultBody.ok().data(internalSendService.testSign("1"));
     }
 
+    @ApiOperation("async本地测试接口")
+    @ApiOperationSupport(order = 11)
+    @PostMapping("/api/async")
+    public ResultBody async(@RequestBody TestAsync testAsync) throws Exception {
+        System.err.println(testAsync.getReqId()+","+testAsync.getFileType()
+                +","+testAsync.getData()+","+testAsync.getStartTime()+","+
+                testAsync.getParsedFilePaths());
+        uploadService.uploadAsync( testAsync.getReqId(),  testAsync.getFileType(),
+                testAsync.getData(),   testAsync.getStartTime(),testAsync.getParsedFilePaths());
+        // uploadService.upload(reqId,fileType,data,startTime,parsedFilePaths);
+        // String url = "http://192.168.1.73:18000/down/fjs/3/20200622/3_11a238f7-eba8-4dbd-a04d-05500a62a2c8.jpg";
+        // Map<String, Object> urlMap = new HashMap<>();
+        // urlMap.put("url",url);
+        // return ResultBody.ok().data(internalSendService.testSign(url));
+
+        // uploadService.upload("tes20200622","3","{}",files,startTime);
+        return ResultBody.ok().data("succ");
+    }
 
     // @ApiOperation("Api接口每分钟访问次数限制")
     // @AuthIgnore
@@ -407,19 +427,38 @@ public class BackController {
                 .descriptionFour("")
                 .build();
         ProVersion pv13 = ProVersion.builder()
-                .date("2020-06-03")
-                .version("V1.13")
-                .descriptionOne("解决联系人方式解析为不一致问题")
-                .descriptionTwo("用户画像bug修复")
-                .descriptionThree("新增字段midConfidence")
-                .descriptionFour("")
+                .date("2020-06-03 测试环境")
+                .version("V3.5")
+                .descriptionOne("1、解决联系人方式解析为不一致问题;2、用户画像bug修复;" +
+                        "3、新增字段midConfidence")
+                .descriptionTwo("2020-05-27 生产环境")
+                .descriptionThree("v1.12")
+                .descriptionFour("1、空白图片整体置信度设置为0;2、用户画像功能;")
                 .build();
 
         ProVersion pv14 = ProVersion.builder()
-                .date("2020-06-05")
-                .version("V1.14")
+                .date("2020-06-05  测试环境")
+                .version("V3.5")
                 .descriptionOne("新增字段midConfidence")
-                .descriptionTwo("")
+                .descriptionTwo("2020-06-05  生产环境")
+                .descriptionThree("v1.13")
+                .descriptionFour("1、修复后台解析联系人信息存储问题。")
+                .build();
+
+        ProVersion pv15 = ProVersion.builder()
+                .date("2020-06-18 测试环境")
+                .version("V3.6")
+                .descriptionOne("1、使用opencv库查找印章区域。")
+                .descriptionTwo("2020-06-09 生产环境")
+                .descriptionThree("V1.14")
+                .descriptionFour("1、新增字段中间置信度midConfidence。")
+                .build();
+
+        ProVersion pv16 = ProVersion.builder()
+                .date("2020-07-09 测试环境")
+                .version("V3.7")
+                .descriptionOne("1、针对“推荐函”维护一份“推荐人员”及“推荐人员联系方式”的库,用来优化识别;2、解决速度慢的问题。")
+                .descriptionTwo("2、线程异常解决。")
                 .descriptionThree("")
                 .descriptionFour("")
                 .build();
@@ -438,6 +477,8 @@ public class BackController {
         ver.add(pv12);
         ver.add(pv13);
         ver.add(pv14);
+        ver.add(pv15);
+        ver.add(pv16);
         return ver;
     }
 

+ 9 - 8
src/main/java/com/pavis/ai/app/fjsocrasy/controller/OcrController.java

@@ -73,14 +73,15 @@ public class OcrController {
         }
     }
 
-    /**
-     * 同步请求。
-     * @param reqId
-     * @param fileType
-     * @param data
-     * @param files
-     * @return
-     */
+
+        /**
+         * 同步请求。
+         * @param reqId
+         * @param fileType
+         * @param data
+         * @param files
+         * @return
+         */
     @ApiOperation("富士通图片识别同步接口")
     @PostMapping("/fjs/ocr/syn")
     public ResultBody resSynchronous(String reqId,String fileType,String data, @RequestParam("files") MultipartFile[] files) throws Exception {

+ 4 - 3
src/main/java/com/pavis/ai/app/fjsocrasy/service/EternalSendService.java

@@ -10,9 +10,9 @@ import org.springframework.web.bind.annotation.PostMapping;
  * @desc 回传数据富士通。
  **/
 // 本地测试环境
-@FeignClient(value = "eternalSendService",url = "http://192.168.1.73:18000")
+// @FeignClient(value = "eternalSendService",url = "http://192.168.1.73:18000")
 // 测试环境
-// @FeignClient(value = "eternalSendService",url = "http://61.155.215.241:52090")
+@FeignClient(value = "eternalSendService",url = "http://61.155.215.241:52090")
 // 生产环境
 // @FeignClient(value = "eternalSendService",url = "http://61.155.215.241:53090")
 public interface EternalSendService {
@@ -22,6 +22,7 @@ public interface EternalSendService {
      * @param data
      * @return
      */
-    @PostMapping(value = "/ocr/api/receive",produces = {MediaType.APPLICATION_JSON_UTF8_VALUE},consumes = "application/json")
+    @PostMapping(value = "/ocr/api/receive",produces = {MediaType.APPLICATION_JSON_UTF8_VALUE},
+            consumes = "application/json")
     String send(String data);
 }

+ 2 - 2
src/main/java/com/pavis/ai/app/fjsocrasy/service/InternalSendService.java

@@ -21,8 +21,8 @@ import java.util.Map;
 // @FeignClient(value = "internalSendService",url = "http://192.168.1.200:28011")
 // @FeignClient(value = "internalSendService",url = "http://127.0.0.1:28011")
 // 测试环境
-// @FeignClient(value = "internalSendService",url = "http://180.76.146.227:8099")
-@FeignClient(value = "internalSendService",url = "http://180.76.146.227:8089")
+@FeignClient(value = "internalSendService",url = "http://180.76.146.227:8099")
+// @FeignClient(value = "internalSendService",url = "http://180.76.146.227:8089")
 // @FeignClient(value = "internalSendService",url = "http://180.76.146.227:18888")
 // 生产环境
 // @FeignClient(value = "internalSendService",url = "http://47.104.109.52:8089")

+ 12 - 0
src/main/java/com/pavis/ai/app/fjsocrasy/service/UploadService.java

@@ -18,6 +18,18 @@ import java.util.Map;
  **/
 public interface UploadService {
 
+    /**
+     * 文件上传。
+     * @param reqId
+     * @param fileType
+     * @param data
+     * @param files
+     * @return
+     * @throws Exception
+     */
+    List<FileDetails> uploadAsync(String reqId, String fileType, String data,  Long startTime, List<FileDetails> parsedFilePaths) throws Exception;
+
+
     /**
      * 文件上传。
      * @param reqId

+ 2 - 1
src/main/java/com/pavis/ai/app/fjsocrasy/service/impl/OcrServiceImpl.java

@@ -80,7 +80,7 @@ public class OcrServiceImpl implements OcrService {
         // 2.2 获取ocr返回值。
         log.info("step ***2: ocr***");
         Map<String,Object> ocrMap = toOcrMap(reqId,fileType,url,fileName,data,startTime);
-        System.err.println("***"+JSON.toJSONString(ocrMap));
+
         if (null != ocrMap && ocrMap.containsKey("req_id")){
             // 3、用户画像相似匹配。
             linkService.match(ocrMap.get("req_id").toString(),ocrMap.get("type").toString(),startTime,
@@ -554,6 +554,7 @@ public class OcrServiceImpl implements OcrService {
         if (uploadService.findLinkByBo(bo).size() > 1){
             log.info("关联数据START...");
             Map<String,Object> linkMap = uploadService.link(bo,ocr,fileType);
+            linkMap.put("req_id",reqId);
             return linkMap;
         }
         matchMap.put("source_data", fileType.equals("2") || fileType.equals("13") || fileType.equals("14") || fileType.equals("17")

+ 3 - 2
src/main/java/com/pavis/ai/app/fjsocrasy/service/impl/OtherServiceImpl.java

@@ -33,8 +33,9 @@ public class OtherServiceImpl implements OtherService {
 
     @Override
     public void uploading(String reqId, String fileType, String data, MultipartFile[] files, Long startTime, List<FileDetails> parsedFilePaths) throws IOException {
-        String suffix = files[0].getOriginalFilename().substring(files[0].getOriginalFilename().lastIndexOf("."));
-        String fileName = UUID.randomUUID().toString() + suffix;
+        // String suffix = files[0].getOriginalFilename().substring(files[0].getOriginalFilename().lastIndexOf("."));
+        // String fileName = UUID.randomUUID().toString() + suffix;
+        String fileName = UUID.randomUUID().toString();
         // 2、参数封装供ocr使用。
         Map<String, Object> rbmqMap = new HashMap<>();
         rbmqMap.put("reqId", reqId);

+ 8 - 0
src/main/java/com/pavis/ai/app/fjsocrasy/service/impl/UploadServiceImpl.java

@@ -220,6 +220,14 @@ public class UploadServiceImpl implements UploadService {
     private OtherService otherService;
 
 
+    @Override
+    public List<FileDetails> uploadAsync(String reqId, String fileType, String data,  Long startTime, List<FileDetails> parsedFilePaths) throws Exception {
+        otherService.uploading(reqId,fileType,data,null,startTime,parsedFilePaths);
+        // todo 待处理。
+        // return "1";
+        return parsedFilePaths;
+    }
+
     @Override
     public List<FileDetails> upload(String reqId, String fileType, String data, MultipartFile[] files, Long startTime) throws Exception {
         // 1、将上传信息数据写入库,并将文件数据写入磁盘,同时返回待处理的图片路径。

+ 2 - 1
src/main/resources/application-dev.yml

@@ -2,7 +2,8 @@ spring:
   datasource:
 #    url: jdbc:mysql://192.168.1.73/fjs_ocr_11?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT
 #    url: jdbc:mysql://192.168.1.73/fjs_ocr_12?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT
-    url: jdbc:mysql://192.168.1.73/fjs_ocr_13?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT
+#    url: jdbc:mysql://192.168.1.73/fjs_ocr_13?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT
+    url: jdbc:mysql://192.168.1.73/fjs_ocr_14?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT
     driver-class-name: com.mysql.cj.jdbc.Driver
     username: root
     password: root

+ 4 - 4
src/main/resources/application.yml

@@ -1,14 +1,14 @@
 server:
 #  测试环境
-#  port: 8000
+  port: 8000
 #  生产环境
-  port: 18000
+#  port: 18000
 spring:
   application:
     name: fujisu-ocr-server
   profiles:
-    active: dev
-#    active: test
+#    active: dev
+    active: test
 #    active: prod
   servlet:
     multipart:

+ 16 - 16
src/test/java/com/pavis/ai/app/fjsocrasy/FjsOcrAsyApplicationTests.java

@@ -1,16 +1,16 @@
-package com.pavis.ai.app.fjsocrasy;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.junit4.SpringRunner;
-
-@RunWith(SpringRunner.class)
-@SpringBootTest
-public class FjsOcrAsyApplicationTests {
-
-    @Test
-    public void contextLoads() {
-    }
-
-}
+// package com.pavis.ai.app.fjsocrasy;
+//
+// import org.junit.Test;
+// import org.junit.runner.RunWith;
+// import org.springframework.boot.test.context.SpringBootTest;
+// import org.springframework.test.context.junit4.SpringRunner;
+//
+// @RunWith(SpringRunner.class)
+// @SpringBootTest
+// public class FjsOcrAsyApplicationTests {
+//
+//     @Test
+//     public void contextLoads() {
+//     }
+//
+// }