From 466d488372f884883fa02cc3ca9877b073fe39c9 Mon Sep 17 00:00:00 2001 From: 杜洪波 <1074825718@qq.com> Date: 星期三, 18 六月 2025 15:43:46 +0800 Subject: [PATCH] 系统备份优化(附件增量备份,备份日志) --- src/main/java/com/product/system/backup/service/SystemBackupServiceV1.java | 244 ++++++++++++++++++------------------------------ 1 files changed, 90 insertions(+), 154 deletions(-) diff --git a/src/main/java/com/product/system/backup/service/SystemBackupService2.java b/src/main/java/com/product/system/backup/service/SystemBackupServiceV1.java similarity index 65% rename from src/main/java/com/product/system/backup/service/SystemBackupService2.java rename to src/main/java/com/product/system/backup/service/SystemBackupServiceV1.java index 4ff3122..3d4d430 100644 --- a/src/main/java/com/product/system/backup/service/SystemBackupService2.java +++ b/src/main/java/com/product/system/backup/service/SystemBackupServiceV1.java @@ -9,19 +9,12 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.text.SimpleDateFormat; import java.util.Date; -import java.util.List; -import java.util.Map; import java.util.Properties; -import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.alibaba.druid.util.StringUtils; @@ -33,17 +26,16 @@ import com.jcraft.jsch.SftpException; import com.jcraft.jsch.SftpProgressMonitor; import com.product.core.config.Global; -import com.product.core.dao.BaseDao; -import com.product.core.entity.DataTableEntity; -import com.product.core.entity.FieldSetEntity; -import com.product.core.service.support.AbstractBaseService; import com.product.system.backup.entity.BackupLogger; -@Service("systemBackService") -public class SystemBackupService2 extends AbstractBaseService{ - - @Autowired - BaseDao baseDao; +/** + * 绯荤粺澶囦唤 + * 鏁版嵁搴撳浠斤細姣忓ぉ鎵ц浠g爜澶囦唤 + * 闄勪欢澶囦唤锛氭瘡澶╂墽琛屼唬鐮佸浠藉綋澶╅檮浠� + * 閬楃暀闂锛氶檮浠惰淇敼锛屼笉鑳介攣瀹氶潪褰撳ぉ琚慨鏀圭殑闄勪欢 + */ +@Service("systemBackService1") +public class SystemBackupServiceV1 { // 澶囦唤閰嶇疆 Properties config; @@ -54,80 +46,29 @@ // 鏁板瓧鏃堕棿鍜屾暟瀛楁棩鏈燂紙鐢ㄥ仛鏂囦欢澶规垨鑰呮枃浠跺悕锛� String NUMBER_TIME; //渚嬪锛�20250428091001锛� String NUMBER_DATE; //渚嬪锛�20240428锛� - String STANDARD_START_TIME; // 渚嬪锛�2024-04-28 09:10:00锛� - String STANDARD_FINAL_TIME; // 渚嬪锛�2024-04-28 09:10:00锛� // 鏁板瓧鏃ユ湡鏍煎紡 - SimpleDateFormat numberTimeFormat = new SimpleDateFormat("yyyyMMddHHmm00"); + SimpleDateFormat numberTimeFormat = new SimpleDateFormat("yyyyMMddHHmmss"); SimpleDateFormat numberDateFormat = new SimpleDateFormat("yyyyMMdd"); - SimpleDateFormat standardTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:00"); // 澶囦唤閰嶇疆鏂囦欢 private static final String CONFIG_FILE_PATH = "systemBackup.properties"; /** - * 绯荤粺澶囦唤鍒ゅ畾 + * 绯荤粺澶囦唤鍏ュ彛 * 璋冪敤鍦扮偣锛氬畾鏃朵换鍔¢厤缃姛鑳�(bean) */ - public void systemBackupInit() { - // 鑾峰彇绯荤粺鏃堕棿 - Date finalTime = new Date(); - Date startTime = null; - // 鑾峰彇绯荤粺澶囦唤鍛ㄦ湡(鍒嗛挓) - int backupCycle = Integer.valueOf(Global.getSystemConfig("SYSTEM_BACK_CYCLE", "20")); - // 鑾峰彇绯荤粺鏈�澶у浠芥椂闂� - StringBuilder sbSql = new StringBuilder(); - sbSql.append("SELECT TIMESTAMPDIFF(MINUTE, end_time, ?) AS diff_minutes,end_time \n"); - sbSql.append("FROM product_sys_backup_log \n"); - sbSql.append("WHERE backup_status = 1 \n"); - sbSql.append("ORDER BY end_time DESC \n"); - sbSql.append("LIMIT 1 \n"); - FieldSetEntity fseMaxLogTime = baseDao.getFieldSetEntityBySQL(sbSql.toString(), new Object[] {standardTimeFormat.format(finalTime)}, false); - if(fseMaxLogTime != null && !StringUtils.isEmpty(fseMaxLogTime.getString("diff_minutes"))) { - Integer diffMinutes = fseMaxLogTime.getInteger("diff_minutes"); - if (diffMinutes < backupCycle) { - // 灏忎簬澶囦唤鍛ㄦ湡锛屼笉澶囦唤 - return ; - } - startTime = fseMaxLogTime.getDate("end_time"); - } - try { - // 鎵ц澶囦唤 - systemBackup(startTime, finalTime); - } catch (Exception e) { - e.printStackTrace(); - } - FieldSetEntity fseBackLog = new FieldSetEntity("product_sys_backup_log"); - fseBackLog.setValue("start_time", startTime); - fseBackLog.setValue("end_time", finalTime); - fseBackLog.setValue("backup_status", 1); - baseDao.saveFieldSetEntity(fseBackLog); - } - - /** - * 绯荤粺澶囦唤鍏ュ彛 - * - */ - public void systemBackup(Date startTime, Date finalTime){ - + public void systemBackupInit(){ // 鍒濆鏃ュ織鏂囦欢 log = new BackupLogger(); // 鍦ㄦ棩蹇椾腑璁板綍鎿嶄綔绯荤粺淇℃伅锛屼究浜庤皟璇� log.writeInfo("銆愮郴缁熷浠藉叆鍙c�戞搷浣滅郴缁�: " + System.getProperty("os.name"), BackupLogger.INFO_TYPE); log.writeInfo("銆愮郴缁熷浠藉叆鍙c�戞枃浠跺垎闅旂: " + File.separator, BackupLogger.INFO_TYPE); log.writeInfo("銆愮郴缁熷浠藉叆鍙c�戠郴缁熷浠藉紑濮�..................", BackupLogger.INFO_TYPE); - NUMBER_TIME = numberTimeFormat.format(finalTime); - NUMBER_DATE = numberDateFormat.format(finalTime); - if(startTime == null) { - STANDARD_START_TIME = "2000-01-01 00:00:00"; - } else { - STANDARD_START_TIME = standardTimeFormat.format(startTime); - } - STANDARD_FINAL_TIME = standardTimeFormat.format(finalTime); + NUMBER_TIME = numberTimeFormat.format(new Date()); + NUMBER_DATE = numberDateFormat.format(new Date()); log.writeInfo("銆愮郴缁熷浠藉叆鍙c�戠郴缁熸棩鏈燂細" + NUMBER_DATE, BackupLogger.INFO_TYPE); log.writeInfo("銆愮郴缁熷浠藉叆鍙c�戠郴缁熸椂闂达細" + NUMBER_TIME, BackupLogger.INFO_TYPE); - log.writeInfo("銆愮郴缁熸湰鍒嗗叆鍙c�戠郴缁熷浠藉紑濮嬫椂闂达細" + STANDARD_START_TIME, BackupLogger.INFO_TYPE); - log.writeInfo("銆愮郴缁熷浠藉叆鍙c�戠郴缁熷浠芥埅姝㈡椂闂达細" + STANDARD_FINAL_TIME, BackupLogger.INFO_TYPE); // 杩涘叆澶囦唤杩涚▼ backupProcess(); log.closeLogger(); @@ -153,7 +94,8 @@ if (!status) return; // 绗洓姝ワ細涓婁紶鍘嬬缉澶囦唤鏂囦欢鍒癋TP - status = sftpTransferService(); + status = sftpTransferService(true); +// uploadBackupMachine2(); if (!status) return; // 绗簲姝ワ細娓呴櫎鏁版嵁 @@ -179,8 +121,8 @@ // 鑾峰彇绯荤粺鏂囦欢璺緞 String systemFileFolder = Global.getSystemConfig("local.dir", ""); File newFile= new File(systemFileFolder); - // 绯荤粺闄勪欢瀛樻斁鐩綍 - config.setProperty("DOCUMENT_ROOT", newFile.getAbsolutePath() + File.separator + "00000000-0000-0000-0000-000000000000"); + // 绯荤粺闄勪欢瀛樻斁鐩綍(褰撳ぉ闄勪欢) + config.setProperty("DOCUMENT_ROOT", newFile.getAbsolutePath() + File.separator + "00000000-0000-0000-0000-000000000000" + File.separator + NUMBER_DATE); // 鏁版嵁搴撳浠界洰褰曪紙鏁版嵁搴撳浠芥牴鐩綍+鏃堕棿鏂囦欢鍚�+.sql锛� config.setProperty("DATABASE_BACKUP", config.getProperty("DATABASE_ROOT") + File.separator + NUMBER_TIME + ".sql"); // 澶囦唤鐩爣鏂囦欢锛圸IP澶囦唤鏍圭洰褰�+鏃堕棿鏂囦欢鍚�+.zip锛� @@ -279,6 +221,21 @@ return true; } + private static void addFolderToZip(File folder, String parentPath, ZipOutputStream zos) throws IOException { + File[] files = folder.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isDirectory()) { + // 閫掑綊澶勭悊瀛愮洰褰曪紝淇濇寔璺緞缁撴瀯 + addFolderToZip(file, parentPath + file.getName() + "/", zos); + } else { + // 娣诲姞鏂囦欢鍒癦IP锛屼繚鎸佽矾寰勭粨鏋� + addFileToZip(file, parentPath + file.getName(), zos); + } + } + } + } + private static void addFileToZip(File file, String entryName, ZipOutputStream zos) throws IOException { try (FileInputStream fis = new FileInputStream(file)) { zos.putNextEntry(new ZipEntry(entryName)); @@ -292,91 +249,55 @@ } /** - * 鍘嬬缉澧為噺闄勪欢 - * @param groupFolderFile 澧為噺鏂囦欢澶癸紝鏂囦欢鍚� - * @param baseDir 闄勪欢鏍圭洰褰� - * @param outputZipPath 鍘嬬缉鏂囦欢 - * @throws IOException + * 绗笁姝ワ細鍘嬬缉澶囦唤鏂囦欢 */ - public static void compressExistingFiles(Map<Integer, List<String>> groupFolderFile, String baseDir, ZipOutputStream zos) throws IOException { - for (Map.Entry<Integer, List<String>> entry : groupFolderFile.entrySet()) { - int folderName = entry.getKey(); // 鏂囦欢澶瑰悕锛堝 20250611锛� - List<String> files = entry.getValue(); // 璇ユ枃浠跺す涓嬬殑鏂囦欢鍚嶅垪琛� - Path folderPath = Paths.get(baseDir).resolve(String.valueOf(folderName)); - for (String fileName : files) { - Path filePath = folderPath.resolve(fileName); - // 妫�鏌ユ枃浠舵槸鍚﹀瓨鍦� - if (Files.exists(filePath) && !Files.isDirectory(filePath)) { - // 璁$畻 ZIP 鍐呯殑鐩稿璺緞锛堝 "20250611/file1.txt"锛� - ZipEntry zipEntry = new ZipEntry( - String.valueOf(folderName) + "/" + fileName - ); - zos.putNextEntry(zipEntry); - - // 鍐欏叆鏂囦欢鍐呭鍒� ZIP - Files.copy(filePath, zos); - zos.closeEntry(); - } else { - System.err.println("鏂囦欢涓嶅瓨鍦ㄦ垨涓嶆槸鏂囦欢: " + filePath); - } - } - } - } - - public boolean zipDataBackup() { - log.writeInfo("銆愬帇缂╁浠芥枃浠躲�戝紑濮嬪帇缂╁浠芥枃浠�..................", BackupLogger.INFO_TYPE); + public boolean zipDataBackup() { + log.writeInfo("銆愬帇缂╁浠芥枃浠躲�戝紑濮嬪帇缂╁浠芥枃浠�..................", BackupLogger.INFO_TYPE); String documentPath = config.getProperty("DOCUMENT_ROOT"); String databasePath = config.getProperty("DATABASE_BACKUP"); String zipFilePath = config.getProperty("ZIPFILE_BACKUP"); log.writeInfo("銆愬帇缂╁浠芥枃浠躲�戦檮浠跺瓨鍌ㄧ洰褰曡矾寰勶細" + documentPath, BackupLogger.INFO_TYPE); log.writeInfo("銆愬帇缂╁浠芥枃浠躲�戞暟鎹簱澶囦唤瀹屾暣璺緞锛�" + databasePath, BackupLogger.INFO_TYPE); log.writeInfo("銆愬帇缂╁浠芥枃浠躲�戝浠藉帇缂╂枃浠跺畬鏁磋矾寰勶細" + zipFilePath, BackupLogger.INFO_TYPE); - - try (FileOutputStream fos = new FileOutputStream(zipFilePath); - ZipOutputStream zos = new ZipOutputStream(fos)){ - StringBuilder sbSql = new StringBuilder(); - sbSql.append("SELECT SUBSTRING_INDEX(attachment_url, '/', -1) id,attachment_title AS uuid,attachment_url \n"); - sbSql.append("FROM product_sys_attachments \n"); - sbSql.append("WHERE (created_utc_datetime > ? AND created_utc_datetime <= ?) \n"); - sbSql.append("AND (updated_utc_datetime > ? AND updated_utc_datetime <= ?) \n"); - DataTableEntity dtTable = baseDao.listTable(sbSql.toString(), new Object[] {STANDARD_START_TIME, STANDARD_FINAL_TIME, STANDARD_START_TIME, STANDARD_FINAL_TIME}); - if(dtTable != null && dtTable.getRows() > 0) { - Map<Integer, List<String>> groupFolderFile = dtTable.getData().stream() - .collect(Collectors.groupingBy( - FieldSetEntity::getId, - Collectors.mapping( - FieldSetEntity::getUUID, - Collectors.toList() - ) - )); - log.writeInfo("銆愬帇缂╁浠芥枃浠躲�戝帇缂╃郴缁熷閲忛檮浠�", BackupLogger.INFO_TYPE); - compressExistingFiles(groupFolderFile, documentPath, zos); - } - - log.writeInfo("銆愬帇缂╁浠芥枃浠躲�戝帇缂╂暟鎹簱澶囦唤鏂囦欢", BackupLogger.INFO_TYPE); + try (FileOutputStream fos = new FileOutputStream(zipFilePath); + ZipOutputStream zos = new ZipOutputStream(fos)) { + + log.writeInfo("銆愬帇缂╁浠芥枃浠躲�戝帇缂╃郴缁熼檮浠�", BackupLogger.INFO_TYPE); + // 鍘嬬缉鏂囦欢澶癸紙淇濈暀瀹屾暣璺緞缁撴瀯锛� + // 娉ㄦ剰锛氳繖閲屾垜浠紶閫掍簡鏍圭洰褰曞悕绉颁綔涓哄垵濮媝arentPath + addFolderToZip(new File(documentPath), NUMBER_DATE + "/", zos); + + log.writeInfo("銆愬帇缂╁浠芥枃浠躲�戝帇缂╂暟鎹簱澶囦唤鏂囦欢", BackupLogger.INFO_TYPE); // 鍘嬬缉SQL鏂囦欢锛堟斁鍦ㄦ寚瀹氳矾寰勪笅锛� addFileToZip(new File(databasePath), "database/" + NUMBER_TIME + ".sql", zos); - log.writeInfo("銆愬帇缂╁浠芥枃浠躲�戝帇缂╁畬鎴�", BackupLogger.INFO_TYPE); - } catch (IOException e) { - e.printStackTrace(); - } finally { - File file = new File(databasePath); - file.delete(); - log.writeInfo("銆愬帇缂╁浠芥枃浠躲�戞竻鐞嗘暟鎹簱澶囦唤鏂囦欢瀹屾垚", BackupLogger.INFO_TYPE); - } - return false; - } + log.writeInfo("銆愬帇缂╁浠芥枃浠躲�戝帇缂╁畬鎴�", BackupLogger.INFO_TYPE); + } catch (IOException e) { + e.printStackTrace(); + log.writeInfo("銆愬帇缂╁浠芥枃浠躲�戝帇缂╁け璐ワ細" + e.getMessage(), BackupLogger.ERROR_TYPE); + return false; + } + return true; + } + /** * SFTP杩炴帴锛氶�氳繃SFTP灏嗗浠芥枃浠朵笂浼犲鐢ㄦ満 鎴� 浠巑ysql鏈嶅姟鍣ㄤ笂鑾峰彇澶囦唤鏂囦欢 * @param isUpload 鏄惁涓婁紶 * @return */ - public boolean sftpTransferService() { - String sftpTitle = "涓婁紶绯荤粺澶囦唤鏂囦欢";; - String localFilePath = config.getProperty("ZIPFILE_BACKUP"); // 鏈湴鏂囦欢璺緞 - String sftpFilePath = config.getProperty("UPLOAD_BACKUP_DIR") + NUMBER_TIME + ".zip"; // SFTP鏈嶅姟鏂囦欢璺緞; - + public boolean sftpTransferService(boolean isUpload) { + String sftpTitle = null; + String localFilePath = null; + String sftpFilePath = null; + if(isUpload) { + sftpTitle = "涓婁紶绯荤粺澶囦唤鏂囦欢"; + localFilePath = config.getProperty("ZIPFILE_BACKUP"); // 鏈湴鏂囦欢璺緞 + sftpFilePath = config.getProperty("UPLOAD_BACKUP_DIR") + NUMBER_TIME + ".zip"; // SFTP鏈嶅姟鏂囦欢璺緞 + } else { +// sftpTitle = "鑾峰彇鏁版嵁搴撳浠芥枃浠�"; +// localFilePath = config.getProperty("DATABASE_BACKUP"); // 鏈湴鏂囦欢璺緞 +// sftpFilePath = config.getProperty("DATABASE_BACKUP"); // SFTP鏈嶅姟鏂囦欢璺緞 + } String host = config.getProperty("UPLOAD_SFTP_HOST"); // SFTP鏈嶅姟IP鍦板潃 String port = config.getProperty("UPLOAD_SFTP_PORT"); // SSH绔彛 String user = config.getProperty("UPLOAD_SFTP_USER"); // SFTP鏈嶅姟鐨勭敤鎴峰悕 @@ -406,15 +327,30 @@ if (!remoteDir.startsWith("/")) { remoteDir = "/" + remoteDir; } - // 鍒涘缓瀵瑰簲鐩綍鏂囦欢澶� - createRemoteDirectory(sftpChannel, remoteDir); - sftpChannel.put(localFilePath, sftpFilePath, new SftpProgressMonitor() { - public void init(int op, String src, String dest, long max) { - log.writeInfo("銆愪笂浼犵郴缁熷浠芥枃浠躲�戝紑濮嬩紶杈�: " + src + " -> " + dest, BackupLogger.INFO_TYPE); + if(isUpload) { + // 鍒涘缓瀵瑰簲鐩綍鏂囦欢澶� + createRemoteDirectory(sftpChannel, remoteDir); + sftpChannel.put(localFilePath, sftpFilePath, new SftpProgressMonitor() { + public void init(int op, String src, String dest, long max) { + log.writeInfo("銆愪笂浼犵郴缁熷浠芥枃浠躲�戝紑濮嬩紶杈�: " + src + " -> " + dest, BackupLogger.INFO_TYPE); + } + public boolean count(long count) { return true; } + public void end() { log.writeInfo("銆愪笂浼犵郴缁熷浠芥枃浠躲�戜紶杈撳畬鎴�", BackupLogger.INFO_TYPE); } + }); + } else { + // 鍒涘缓瀵瑰簲鐩綍鏂囦欢澶� + File fileDirectory = new File(remoteDir); + if (!fileDirectory.exists()) { + fileDirectory.mkdirs(); } - public boolean count(long count) { return true; } - public void end() { log.writeInfo("銆愪笂浼犵郴缁熷浠芥枃浠躲�戜紶杈撳畬鎴�", BackupLogger.INFO_TYPE); } - }); + sftpChannel.get(localFilePath, sftpFilePath, new SftpProgressMonitor() { + public void init(int op, String src, String dest, long max) { + log.writeInfo("銆愯幏鍙栨暟鎹簱澶囦唤鏂囦欢銆戝紑濮嬩紶杈�: " + src + " -> " + dest, BackupLogger.INFO_TYPE); + } + public boolean count(long count) { return true; } + public void end() { log.writeInfo("銆愯幏鍙栨暟鎹簱澶囦唤鏂囦欢銆戜紶杈撳畬鎴�", BackupLogger.INFO_TYPE); } + }); + } sftpChannel.exit(); session.disconnect(); log.writeInfo(String.format("銆�%s銆�%s鎴愬姛", sftpTitle, sftpTitle), BackupLogger.INFO_TYPE); @@ -427,7 +363,7 @@ } /** - * SFTP閫掑綊鍒涘缓杩滅▼鐩綍 + * 閫掑綊鍒涘缓杩滅▼鐩綍 * @param sftpChannel * @param remoteDir * @throws SftpException -- Gitblit v1.9.2