From 7d03d9fe3714a10fdd51f24e3c84da31a36f4ad8 Mon Sep 17 00:00:00 2001 From: wzp <2040239371@qq.com> Date: 星期二, 15 七月 2025 14:28:14 +0800 Subject: [PATCH] fix:修复docker转化pdf文件卡顿和IO暴涨问题。 用单例控制docker转化,并监控docker状态 --- src/main/java/com/ots/common/utils/poi/WordUtil.java | 6 src/main/java/com/ots/project/tool/PdfUtil.java | 1 src/main/java/com/ots/project/tool/report/LAQ/chart/LAQChart.java | 18 +- src/main/java/com/ots/project/tool/PdfDockerUtil.java | 292 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 306 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/ots/common/utils/poi/WordUtil.java b/src/main/java/com/ots/common/utils/poi/WordUtil.java index 59c478a..44f60fa 100644 --- a/src/main/java/com/ots/common/utils/poi/WordUtil.java +++ b/src/main/java/com/ots/common/utils/poi/WordUtil.java @@ -12,6 +12,7 @@ import com.ots.project.exam.domain.TReportTemplate; import com.ots.project.exam.dto.JAQTableStyle; import com.ots.project.exam.dto.WordParam; +import com.ots.project.tool.PdfDockerUtil; import com.ots.project.tool.PdfUtil; import com.ots.project.tool.ShellTool; import com.ots.project.tool.exam.ExamUtil; @@ -1236,7 +1237,7 @@ } catch (Exception e) { e.printStackTrace(); } - + //鍒犻櫎鏂囦欢 deleteFileByStr(deleteFileStrList); return AjaxResult.success(fileName + ".zip"); } @@ -1287,7 +1288,8 @@ }else if(ReportTypeEnum.LAQ.getCode().equals(reportType)){ // 鑾峰彇寮�濮嬫椂闂� long startTime = System.currentTimeMillis(); - PdfUtil.dockerConvertPDF(EssConfig.getProfile(),EssConfig.getDocx2pdfPath(),reportName); +// PdfUtil.dockerConvertPDF(EssConfig.getProfile(),EssConfig.getDocx2pdfPath(),reportName); + PdfDockerUtil.convertPDF(EssConfig.getProfile(),EssConfig.getDocx2pdfPath(),reportName); // 鑾峰彇缁撴潫鏃堕棿 long endTime = System.currentTimeMillis(); diff --git a/src/main/java/com/ots/project/tool/PdfDockerUtil.java b/src/main/java/com/ots/project/tool/PdfDockerUtil.java new file mode 100644 index 0000000..97a1b2c --- /dev/null +++ b/src/main/java/com/ots/project/tool/PdfDockerUtil.java @@ -0,0 +1,292 @@ +package com.ots.project.tool; + +import lombok.extern.slf4j.Slf4j; + +import java.io.*; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.MessageFormat; +import java.util.concurrent.TimeUnit; + +/** + * Docker杞寲pdf涓撶敤澶勭悊宸ュ叿 + * 浣跨敤鍗曚緥妯″紡瀹炵幇 + */ +@Slf4j +public class PdfDockerUtil { + + /** + * 鍗曚緥瀹炰緥 + */ + private static volatile PdfDockerUtil instance; + + /** + * 瀹瑰櫒鍚嶇О鍓嶇紑 + */ + private static final String CONTAINER_NAME_PREFIX = "pdf_converter_"; + + /** + * 鏂囦欢閿佽矾寰� + */ + private static final String LOCK_FILE_PATH = System.getProperty("java.io.tmpdir") + "/pdf_docker_lock"; + + /** + * 浠诲姟瓒呮椂鏃堕棿锛堢锛� + */ + private static final int TASK_TIMEOUT_SECONDS = 300; // 5鍒嗛挓 + + /** + * 绉佹湁鏋勯�犲嚱鏁帮紝闃叉澶栭儴瀹炰緥鍖� + */ + private PdfDockerUtil() { + // 绉佹湁鏋勯�犲嚱鏁� + } + + /** + * 鑾峰彇鍗曚緥瀹炰緥 + * 浣跨敤鍙岄噸妫�鏌ラ攣瀹氱‘淇濈嚎绋嬪畨鍏� + * @return PdfDockerUtil瀹炰緥 + */ + public static PdfDockerUtil getInstance() { + if (instance == null) { + synchronized (PdfDockerUtil.class) { + if (instance == null) { + instance = new PdfDockerUtil(); + } + } + } + return instance; + } + + /** + * docker word杞琾df + * @param profile 閰嶇疆鏂囦欢璺緞 + * @param docx2pdfPath docker鍛戒护妯℃澘璺緞 + * @param fileName 鏂囦欢鍚� + */ + public void dockerConvertPDF(String profile, String docx2pdfPath, String fileName) { + FileLock lock = null; + Process proc = null; + + try { + // 1. 鑾峰彇鏂囦欢閿侊紝纭繚涓茶鎵ц + lock = acquireFileLock(); + if (lock == null) { + log.error("鏃犳硶鑾峰彇鏂囦欢閿侊紝鍙兘鏈夊叾浠栬浆鎹换鍔℃鍦ㄦ墽琛�"); + return; + } + + // 2. 鐢熸垚鍞竴瀹瑰櫒鍚嶇О + String containerName = CONTAINER_NAME_PREFIX + System.currentTimeMillis(); + + // 3. 娓呯悊鏃у鍣� + cleanupOldContainers(); + + // 4. 鏋勫缓Docker鍛戒护 + String command = MessageFormat.format(docx2pdfPath, profile, fileName); + log.info("docker鎵ц鍛戒护:{}", command); + + // 5. 鎵цDocker鍛戒护锛堝甫瓒呮椂锛� + proc = Runtime.getRuntime().exec(command); + + // 6. 寮傛璇诲彇杈撳嚭娴� + ProcessOutputReader outputReader = new ProcessOutputReader(proc.getInputStream(), "STDOUT"); + ProcessOutputReader errorReader = new ProcessOutputReader(proc.getErrorStream(), "STDERR"); + + outputReader.start(); + errorReader.start(); + + // 7. 绛夊緟杩涚▼瀹屾垚锛堝甫瓒呮椂锛� + boolean completed = proc.waitFor(TASK_TIMEOUT_SECONDS, TimeUnit.SECONDS); + + if (!completed) { + log.error("Docker浠诲姟鎵ц瓒呮椂锛坽}绉掞級锛屽己鍒剁粓姝㈣繘绋�", TASK_TIMEOUT_SECONDS); + forceKillProcess(proc); + return; + } + + int exitCode = proc.exitValue(); + log.info("Docker杩涚▼閫�鍑虹爜: {}", exitCode); + + // 8. 绛夊緟杈撳嚭璇诲彇瀹屾垚 + outputReader.join(5000); + errorReader.join(5000); + + if (exitCode != 0) { + log.error("Docker鍛戒护鎵ц澶辫触锛岄��鍑虹爜: {}", exitCode); + } else { + log.info("Docker鍛戒护鎵ц鎴愬姛"); + } + + } catch (Exception e) { + log.error("Docker杞崲PDF澶辫触", e); + } finally { + // 9. 娓呯悊璧勬簮 + cleanupResources(proc, lock); + } + } + + /** + * 鑾峰彇鏂囦欢閿� + */ + private FileLock acquireFileLock() { + FileChannel channel = null; + try { + Path lockPath = Paths.get(LOCK_FILE_PATH); + Files.createDirectories(lockPath.getParent()); + + if (!Files.exists(lockPath)) { + Files.createFile(lockPath); + } + + channel = new RandomAccessFile(lockPath.toFile(), "rw").getChannel(); + FileLock lock = channel.tryLock(); + + if (lock != null) { + log.info("鎴愬姛鑾峰彇鏂囦欢閿�"); + return lock; + } else { + log.warn("鏂囦欢閿佽鍗犵敤锛屾棤娉曡幏鍙�"); + if (channel != null) { + channel.close(); + } + return null; + } + } catch (Exception e) { + log.error("鑾峰彇鏂囦欢閿佸け璐�", e); + if (channel != null) { + try { + channel.close(); + } catch (IOException ex) { + log.error("鍏抽棴鏂囦欢閫氶亾澶辫触", ex); + } + } + return null; + } + } + + /** + * 娓呯悊鏃у鍣� + */ + private void cleanupOldContainers() { + try { + // 鏌ユ壘骞跺仠姝㈡墍鏈夌浉鍏冲鍣� + String findCommand = "docker ps -a --filter name=" + CONTAINER_NAME_PREFIX + "* --format '{{.Names}}'"; + Process findProc = Runtime.getRuntime().exec(findCommand); + + BufferedReader reader = new BufferedReader(new InputStreamReader(findProc.getInputStream())); + String containerName; + + while ((containerName = reader.readLine()) != null) { + if (!containerName.trim().isEmpty()) { + log.info("娓呯悊鏃у鍣�: {}", containerName); + + // 鍋滄瀹瑰櫒 + String stopCommand = "docker stop " + containerName; + Runtime.getRuntime().exec(stopCommand); + + // 鍒犻櫎瀹瑰櫒 + String rmCommand = "docker rm " + containerName; + Runtime.getRuntime().exec(rmCommand); + } + } + + reader.close(); + findProc.waitFor(10, TimeUnit.SECONDS); + + } catch (Exception e) { + log.warn("娓呯悊鏃у鍣ㄦ椂鍑虹幇寮傚父", e); + } + } + + /** + * 寮哄埗缁堟杩涚▼ + */ + private void forceKillProcess(Process proc) { + try { + if (proc != null) { + proc.destroy(); + + // 绛夊緟杩涚▼缁堟 + if (!proc.waitFor(5, TimeUnit.SECONDS)) { + proc.destroyForcibly(); + log.warn("寮哄埗缁堟杩涚▼"); + } + } + } catch (Exception e) { + log.error("寮哄埗缁堟杩涚▼澶辫触", e); + } + } + + /** + * 娓呯悊璧勬簮 + */ + private void cleanupResources(Process proc, FileLock lock) { + try { + if (proc != null) { + forceKillProcess(proc); + } + + if (lock != null) { + lock.release(); + log.info("閲婃斁鏂囦欢閿�"); + } + } catch (Exception e) { + log.error("娓呯悊璧勬簮澶辫触", e); + } + } + + /** + * 杩涚▼杈撳嚭璇诲彇鍣� + */ + private static class ProcessOutputReader extends Thread { + private final BufferedReader reader; + private final String streamType; + + public ProcessOutputReader(InputStream inputStream, String streamType) { + this.reader = new BufferedReader(new InputStreamReader(inputStream, java.nio.charset.StandardCharsets.UTF_8)); + this.streamType = streamType; + } + + @Override + public void run() { + try { + String line; + log.info("=== Docker {} ===", streamType); + while ((line = reader.readLine()) != null) { + if ("STDERR".equals(streamType)) { + log.error("{}: {}", streamType, line); + } else { + log.info("{}: {}", streamType, line); + } + } + } catch (IOException e) { + log.error("璇诲彇{}娴佸け璐�", streamType, e); + } finally { + try { + reader.close(); + } catch (IOException e) { + log.error("鍏抽棴{}娴佸け璐�", streamType, e); + } + } + } + } + + /** + * 闈欐�佹柟娉曡皟鐢紝鏂逛究浣跨敤 + * @param profile 閰嶇疆鏂囦欢璺緞 + * @param docx2pdfPath docker鍛戒护妯℃澘璺緞 + * @param fileName 鏂囦欢鍚� + * 鏂瑰紡1锛氶�氳繃闈欐�佹柟娉曡皟鐢紙鎺ㄨ崘锛� + * PdfDockerUtil.convertPDF(profile, docx2pdfPath, fileName); + * 鏂瑰紡2锛氶�氳繃瀹炰緥鏂规硶璋冪敤 + * PdfDockerUtil pdfDockerUtil = PdfDockerUtil.getInstance(); + * pdfDockerUtil.convertPDF(profile, docx2pdfPath, fileName); + */ + public static void convertPDF(String profile, String docx2pdfPath, String fileName) { + getInstance().dockerConvertPDF(profile, docx2pdfPath, fileName); + } +} diff --git a/src/main/java/com/ots/project/tool/PdfUtil.java b/src/main/java/com/ots/project/tool/PdfUtil.java index 39db254..20f9b63 100644 --- a/src/main/java/com/ots/project/tool/PdfUtil.java +++ b/src/main/java/com/ots/project/tool/PdfUtil.java @@ -84,6 +84,7 @@ * @param profile * @param docx2pdfPath * @param fileName + * 杩欎釜鏈夋椂鍊檇ocker杞寲浼氬崱姝伙紝2025.7.15鎷熼噰鐢╬dfDockerUtil鏂版柟娉曞鐞� */ public static void dockerConvertPDF(String profile,String docx2pdfPath,String fileName){ try { diff --git a/src/main/java/com/ots/project/tool/report/LAQ/chart/LAQChart.java b/src/main/java/com/ots/project/tool/report/LAQ/chart/LAQChart.java index 404d971..fe67dd3 100644 --- a/src/main/java/com/ots/project/tool/report/LAQ/chart/LAQChart.java +++ b/src/main/java/com/ots/project/tool/report/LAQ/chart/LAQChart.java @@ -48,17 +48,17 @@ public static void main(String[] args) throws Exception { - String dataPath = "D:\\娴嬭瘎绯荤粺\\闇�姹俓\LAQ\\report\\LAQ琛ㄥご鏁版嵁鏂囦欢.xlsx"; - // 鑾峰彇瀵煎叆鏁版嵁 - File file = new File(dataPath); - InputStream in = new FileInputStream(file); - ExcelUtil<LAQTemplate> util = new ExcelUtil<>(LAQTemplate.class); - List<LAQTemplate> laqTemplateList = util.importExcel(in); +// String dataPath = "D:\\娴嬭瘎绯荤粺\\闇�姹俓\LAQ\\report\\LAQ琛ㄥご鏁版嵁鏂囦欢.xlsx"; +// // 鑾峰彇瀵煎叆鏁版嵁 +// File file = new File(dataPath); +// InputStream in = new FileInputStream(file); +// ExcelUtil<LAQTemplate> util = new ExcelUtil<>(LAQTemplate.class); +// List<LAQTemplate> laqTemplateList = util.importExcel(in); // 鐢熸垚鏂囦欢闆嗗悎 List<String> fileNameList = new ArrayList<>(); List<String> deleteStrList = new ArrayList<>(); - for (int i = 0; i < laqTemplateList.size(); i++) { - LAQTemplate laqTemplate = laqTemplateList.get(i); + for (int i = 0; i < 1; i++) { +// LAQTemplate laqTemplate = laqTemplateList.get(i); //缁勮鎶ュ憡鎵�鐢ㄦ暟鎹� Map<String, Object> textMap = new HashMap<>(); // textMap.put("sendEmailFileName",laqTemplate.getName()); @@ -83,7 +83,7 @@ // String zipFileName = WordUtil.makeReportFile("D:\\娴嬭瘎绯荤粺\\闇�姹俓\LAQ\\report\\LAQ鑻辨枃鎶ュ憡-20230926.docx", template, textMap, new HashMap<>(), deleteStrList); // fileNameList.add(zipFileName); ZipSecureFile.setMinInflateRatio(0.001); - try (OutputStream os = new FileOutputStream("D:\\娴嬭瘎绯荤粺\\闇�姹俓\LAQ\\report\\LAQ鑻辨枃妯℃澘-wzp-淇敼鐗�-1.docx");XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage("D:\\娴嬭瘎绯荤粺\\闇�姹俓\LAQ\\report\\LAQ鑻辨枃妯℃澘-wzp-淇敼鐗�.docx"))){ + try (OutputStream os = new FileOutputStream("D:\\TaiOS\\LAQ-1.docx");XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage("D:\\TaiOS\\LAQ.docx"))){ Map<Integer,List<SeriesData>> seriesDatas = initData(textMap); changeChart(document,seriesDatas,textMap); document.write(os); -- Gitblit v1.9.1