fix:排除资源备份表
This commit is contained in:
@@ -2,12 +2,19 @@ package com.cisd.tms.modules.backup.config;
|
||||
|
||||
import com.cisd.tms.modules.backup.dto.support.ConfiguredFileBackupResource;
|
||||
import com.cisd.tms.modules.backup.dto.support.ConfiguredRestoreCommand;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties(prefix = "tms.backup")
|
||||
public class ResourceBackupProperties {
|
||||
|
||||
private static final List<String> MANDATORY_TMS_DB_EXCLUDED_TABLES = List.of(
|
||||
"tms_resource_backup_task",
|
||||
"tms_resource_restore_task"
|
||||
);
|
||||
|
||||
private String outputDir = "/home/tms/tmp/resource-backup-packages";
|
||||
private String precheckStoreDir = "/home/tms/tmp/resource-restore-precheck";
|
||||
private String restoreTaskRootDir = "/home/tms/tmp/resource-restore";
|
||||
@@ -16,6 +23,7 @@ public class ResourceBackupProperties {
|
||||
private int mysqldumpTimeoutSeconds = 300;
|
||||
private String mysqlPath = "mysql";
|
||||
private String restoreDbScriptPath = "/home/tms/bin/resource-restore/restore-db.sh";
|
||||
private int restoreDbTimeoutSeconds = 300;
|
||||
private String mqReplayScriptPath = "/home/tms/bin/resource-restore/replay-mq.sh";
|
||||
private String tmsDatabaseName = "";
|
||||
private List<String> tmsDbExcludedTables = List.of(
|
||||
@@ -25,7 +33,9 @@ public class ResourceBackupProperties {
|
||||
"tms_auth_session",
|
||||
"tms_auth_challenge",
|
||||
"tms_auth_audit_log",
|
||||
"tms_operation_audit_log"
|
||||
"tms_operation_audit_log",
|
||||
"tms_resource_backup_task",
|
||||
"tms_resource_restore_task"
|
||||
);
|
||||
private String cmepDatabaseName = "CMEP";
|
||||
private String healthCheckUrl = "http://127.0.0.1:8080/actuator/health";
|
||||
@@ -107,6 +117,14 @@ public class ResourceBackupProperties {
|
||||
this.restoreDbScriptPath = restoreDbScriptPath;
|
||||
}
|
||||
|
||||
public int getRestoreDbTimeoutSeconds() {
|
||||
return restoreDbTimeoutSeconds;
|
||||
}
|
||||
|
||||
public void setRestoreDbTimeoutSeconds(int restoreDbTimeoutSeconds) {
|
||||
this.restoreDbTimeoutSeconds = restoreDbTimeoutSeconds;
|
||||
}
|
||||
|
||||
public String getMqReplayScriptPath() {
|
||||
return mqReplayScriptPath;
|
||||
}
|
||||
@@ -124,7 +142,12 @@ public class ResourceBackupProperties {
|
||||
}
|
||||
|
||||
public List<String> getTmsDbExcludedTables() {
|
||||
return tmsDbExcludedTables;
|
||||
LinkedHashSet<String> values = new LinkedHashSet<>();
|
||||
if (tmsDbExcludedTables != null) {
|
||||
values.addAll(tmsDbExcludedTables);
|
||||
}
|
||||
values.addAll(MANDATORY_TMS_DB_EXCLUDED_TABLES);
|
||||
return new ArrayList<>(values);
|
||||
}
|
||||
|
||||
public void setTmsDbExcludedTables(List<String> tmsDbExcludedTables) {
|
||||
|
||||
+39
-22
@@ -79,45 +79,40 @@ public class MysqlDatabaseBackupCollector implements DatabaseBackupCollector {
|
||||
command.add(target.databaseName());
|
||||
|
||||
try {
|
||||
Process process = new ProcessBuilder(command)
|
||||
.redirectErrorStream(true)
|
||||
.start();
|
||||
AtomicReference<byte[]> outputRef = new AtomicReference<>(new byte[0]);
|
||||
AtomicReference<IOException> outputErrorRef = new AtomicReference<>();
|
||||
Thread outputReader = new Thread(() -> {
|
||||
try {
|
||||
outputRef.set(readAllBytes(process.getInputStream()));
|
||||
} catch (IOException ex) {
|
||||
outputErrorRef.set(ex);
|
||||
}
|
||||
}, "resource-backup-mysqldump-output-reader");
|
||||
outputReader.setDaemon(true);
|
||||
outputReader.start();
|
||||
Process process = new ProcessBuilder(command).start();
|
||||
StreamReadResult stdout = readStreamAsync(process.getInputStream(), "resource-backup-mysqldump-stdout-reader");
|
||||
StreamReadResult stderr = readStreamAsync(process.getErrorStream(), "resource-backup-mysqldump-stderr-reader");
|
||||
int timeoutSeconds = Math.max(1, resourceBackupProperties.getMysqldumpTimeoutSeconds());
|
||||
boolean finished = process.waitFor(timeoutSeconds, java.util.concurrent.TimeUnit.SECONDS);
|
||||
if (!finished) {
|
||||
process.destroyForcibly();
|
||||
joinOutputReader(outputReader);
|
||||
joinOutputReader(stdout.thread());
|
||||
joinOutputReader(stderr.thread());
|
||||
throw new IllegalStateException("mysqldump执行超时 after " + timeoutSeconds + "s");
|
||||
}
|
||||
joinOutputReader(outputReader);
|
||||
if (outputErrorRef.get() != null) {
|
||||
throw new IllegalStateException("读取mysqldump输出失败", outputErrorRef.get());
|
||||
joinOutputReader(stdout.thread());
|
||||
joinOutputReader(stderr.thread());
|
||||
if (stdout.error().get() != null) {
|
||||
throw new IllegalStateException("读取mysqldump标准输出失败", stdout.error().get());
|
||||
}
|
||||
byte[] stdout = outputRef.get();
|
||||
if (stderr.error().get() != null) {
|
||||
throw new IllegalStateException("读取mysqldump错误输出失败", stderr.error().get());
|
||||
}
|
||||
byte[] stdoutBytes = stdout.bytes().get();
|
||||
byte[] stderrBytes = stderr.bytes().get();
|
||||
int exitCode = process.exitValue();
|
||||
if (exitCode != 0) {
|
||||
String error = new String(stdout, StandardCharsets.UTF_8).trim();
|
||||
String error = new String(stderrBytes, StandardCharsets.UTF_8).trim();
|
||||
throw new IllegalStateException("mysqldump 执行失败 with exitCode=" + exitCode
|
||||
+ (error.isEmpty() ? "" : ", error=" + error));
|
||||
}
|
||||
if (stdout.length == 0) {
|
||||
if (stdoutBytes.length == 0) {
|
||||
throw new IllegalStateException("mysqldump输出为空");
|
||||
}
|
||||
CollectedDatabaseDump dump = new CollectedDatabaseDump();
|
||||
dump.setDatabaseName(target.databaseName());
|
||||
dump.setFileName(fileName);
|
||||
dump.setContent(stdout);
|
||||
dump.setContent(stdoutBytes);
|
||||
return dump;
|
||||
} catch (InterruptedException ex) {
|
||||
Thread.currentThread().interrupt();
|
||||
@@ -131,6 +126,21 @@ public class MysqlDatabaseBackupCollector implements DatabaseBackupCollector {
|
||||
outputReader.join(1000L);
|
||||
}
|
||||
|
||||
private static StreamReadResult readStreamAsync(InputStream inputStream, String threadName) {
|
||||
AtomicReference<byte[]> bytes = new AtomicReference<>(new byte[0]);
|
||||
AtomicReference<IOException> error = new AtomicReference<>();
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
bytes.set(readAllBytes(inputStream));
|
||||
} catch (IOException ex) {
|
||||
error.set(ex);
|
||||
}
|
||||
}, threadName);
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
return new StreamReadResult(thread, bytes, error);
|
||||
}
|
||||
|
||||
private MysqlConnectionTarget resolveTarget(String configuredDatabaseName, String fallbackDatabaseName) {
|
||||
String url = trim(datasourceUrl);
|
||||
if (url.isEmpty()) {
|
||||
@@ -187,4 +197,11 @@ public class MysqlDatabaseBackupCollector implements DatabaseBackupCollector {
|
||||
|
||||
private record MysqlConnectionTarget(String host, int port, String username, String password, String databaseName) {
|
||||
}
|
||||
|
||||
private record StreamReadResult(
|
||||
Thread thread,
|
||||
AtomicReference<byte[]> bytes,
|
||||
AtomicReference<IOException> error
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -113,6 +113,7 @@ public class LightweightRestoreApplierLauncher {
|
||||
// 脚本读取这些变量后执行停服务、导库、MQ replay、健康检查等现场动作。
|
||||
values.put("TMS_SCRIPT_PATH", trim(properties.getTmsScriptPath()));
|
||||
values.put("DB_RESTORE_SCRIPT_PATH", trim(properties.getRestoreDbScriptPath()));
|
||||
values.put("RESTORE_DB_TIMEOUT_SECONDS", String.valueOf(properties.getRestoreDbTimeoutSeconds()));
|
||||
values.put("MQ_REPLAY_SCRIPT_PATH", trim(properties.getMqReplayScriptPath()));
|
||||
values.put("MYSQL_PATH", trim(properties.getMysqlPath()).isEmpty() ? "mysql" : trim(properties.getMysqlPath()));
|
||||
values.put("DB_HOST", target.host());
|
||||
|
||||
Reference in New Issue
Block a user