增加frpc保活、状态上报方法
This commit is contained in:
@@ -100,7 +100,10 @@ public class AppInitializer implements CommandLineRunner {
|
|||||||
dynamicTaskService.scheduleTask("checkFirewall", businessTasks::checkFirewallTask, 15000, 600000);
|
dynamicTaskService.scheduleTask("checkFirewall", businessTasks::checkFirewallTask, 15000, 600000);
|
||||||
AssertLog.info("检测agent更新配置");
|
AssertLog.info("检测agent更新配置");
|
||||||
agentService.checkAgentUpdate();
|
agentService.checkAgentUpdate();
|
||||||
|
AssertLog.info("启动frpc保活定时任务 - 延迟: {}ms, 间隔: {}ms", 15000, 600000);
|
||||||
|
dynamicTaskService.scheduleTask("checkFrpc", businessTasks::checkFrpcTask, 15000, 600000);
|
||||||
|
AssertLog.info("启动frpc状态上报定时任务 - 延迟: {}ms, 间隔: {}ms", 15000, 300000);
|
||||||
|
dynamicTaskService.scheduleTask("upFrpcMsg", businessTasks::upFrpcMsgTask, 15000, 300000);
|
||||||
}else{
|
}else{
|
||||||
//未注册,发送注册
|
//未注册,发送注册
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ public class BusinessTasks {
|
|||||||
private final AtomicInteger connectionTask = new AtomicInteger(0);
|
private final AtomicInteger connectionTask = new AtomicInteger(0);
|
||||||
private final AtomicInteger networkDetectTask = new AtomicInteger(0);
|
private final AtomicInteger networkDetectTask = new AtomicInteger(0);
|
||||||
private final AtomicInteger checkFirewallTask = new AtomicInteger(0);
|
private final AtomicInteger checkFirewallTask = new AtomicInteger(0);
|
||||||
|
private final AtomicInteger checkFrpcTask = new AtomicInteger(0);
|
||||||
|
private final AtomicInteger upFrpcMsgTask = new AtomicInteger(0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -856,6 +858,10 @@ public class BusinessTasks {
|
|||||||
dynamicTaskService.scheduleTask("checkFirewall", businessTasks::checkFirewallTask, 15000, 600000);
|
dynamicTaskService.scheduleTask("checkFirewall", businessTasks::checkFirewallTask, 15000, 600000);
|
||||||
AssertLog.info("检测agent更新配置");
|
AssertLog.info("检测agent更新配置");
|
||||||
agentService.checkAgentUpdate();
|
agentService.checkAgentUpdate();
|
||||||
|
AssertLog.info("启动frpc保活定时任务 - 延迟: {}ms, 间隔: {}ms", 15000, 600000);
|
||||||
|
dynamicTaskService.scheduleTask("checkFrpc", businessTasks::checkFrpcTask, 15000, 600000);
|
||||||
|
AssertLog.info("启动frpc状态上报定时任务 - 延迟: {}ms, 间隔: {}ms", 15000, 300000);
|
||||||
|
dynamicTaskService.scheduleTask("upFrpcMsg", businessTasks::upFrpcMsgTask, 15000, 300000);
|
||||||
}else{
|
}else{
|
||||||
//未注册,发送注册
|
//未注册,发送注册
|
||||||
try {
|
try {
|
||||||
@@ -933,6 +939,36 @@ public class BusinessTasks {
|
|||||||
AssertLog.info("断开连接--监测防火墙策略定时任务执行 - task #{} completed", count);
|
AssertLog.info("断开连接--监测防火墙策略定时任务执行 - task #{} completed", count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 任务31:frpc保活机制
|
||||||
|
*/
|
||||||
|
@Async("taskExecutor")
|
||||||
|
public void checkFrpcTask() {
|
||||||
|
int count = checkFrpcTask.incrementAndGet();
|
||||||
|
AssertLog.info("frpc保活机制定时任务执行 - 时间: {},task #{}", LocalDateTime.now(), count);
|
||||||
|
// 判定客户端与服务端是否连接
|
||||||
|
if (Objects.nonNull(sessionManager.getSessionById(GlobalConfig.CLIENT_ID))) {
|
||||||
|
// frpc保活机制
|
||||||
|
agentService.checkFrpc();
|
||||||
|
}else{
|
||||||
|
AssertLog.info("断开连接--frpc保活机制定时任务执行 - task #{} completed", count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 任务32:frpc状态上报
|
||||||
|
*/
|
||||||
|
@Async("taskExecutor")
|
||||||
|
public void upFrpcMsgTask() {
|
||||||
|
int count = upFrpcMsgTask.incrementAndGet();
|
||||||
|
AssertLog.info("frpc状态上报定时任务执行 - 时间: {},task #{}", LocalDateTime.now(), count);
|
||||||
|
// 判定客户端与服务端是否连接
|
||||||
|
if (Objects.nonNull(sessionManager.getSessionById(GlobalConfig.CLIENT_ID))) {
|
||||||
|
// frpc状态上报
|
||||||
|
agentService.upFrpcMsg();
|
||||||
|
}else{
|
||||||
|
AssertLog.info("断开连接--frpc状态上报定时任务执行 - task #{} completed", count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -38,4 +38,8 @@ public interface AgentService {
|
|||||||
void checkAndAddFirewallPeriodically();
|
void checkAndAddFirewallPeriodically();
|
||||||
|
|
||||||
void checkAgentUpdate();
|
void checkAgentUpdate();
|
||||||
|
|
||||||
|
void checkFrpc();
|
||||||
|
|
||||||
|
void upFrpcMsg();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -315,6 +315,10 @@ public class AgentServiceImpl implements AgentService {
|
|||||||
dynamicTaskService.scheduleTask("checkFirewall", businessTasks::checkFirewallTask, 15000, 600000);
|
dynamicTaskService.scheduleTask("checkFirewall", businessTasks::checkFirewallTask, 15000, 600000);
|
||||||
AssertLog.info("检测agent更新配置");
|
AssertLog.info("检测agent更新配置");
|
||||||
checkAgentUpdate();
|
checkAgentUpdate();
|
||||||
|
AssertLog.info("启动frpc保活定时任务 - 延迟: {}ms, 间隔: {}ms", 15000, 600000);
|
||||||
|
dynamicTaskService.scheduleTask("checkFrpc", businessTasks::checkFrpcTask, 15000, 600000);
|
||||||
|
AssertLog.info("启动frpc状态上报定时任务 - 延迟: {}ms, 间隔: {}ms", 15000, 300000);
|
||||||
|
dynamicTaskService.scheduleTask("upFrpcMsg", businessTasks::upFrpcMsgTask, 15000, 300000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -904,21 +908,48 @@ public class AgentServiceImpl implements AgentService {
|
|||||||
String resMsg = "frpc.toml修改成功";
|
String resMsg = "frpc.toml修改成功";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 停止进程
|
// 停止
|
||||||
Runtime.getRuntime().exec("pkill -f frpc").waitFor();
|
ProcessBuilder killPb = new ProcessBuilder(
|
||||||
|
"bash", "-c",
|
||||||
|
"pkill -f 'frpc.*toml'"
|
||||||
|
);
|
||||||
|
killPb.start().waitFor();
|
||||||
|
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
|
|
||||||
// 启动进程
|
// 启动 - 使用完整的shell命令
|
||||||
String[] cmd = {frpPath + "/frpc", "-c", frpPath + "/frpc.toml"};
|
String startCommand = String.format(
|
||||||
new ProcessBuilder(cmd)
|
"nohup %s/frpc -c %s/frpc.toml > %s/frpc.log 2>&1 &",
|
||||||
.directory(new File(frpPath))
|
properties.getFrpPath(),
|
||||||
.redirectErrorStream(true)
|
properties.getFrpPath(),
|
||||||
.start();
|
properties.getFrpPath()
|
||||||
|
);
|
||||||
|
|
||||||
|
ProcessBuilder startPb = new ProcessBuilder(
|
||||||
|
"bash", "-c",
|
||||||
|
startCommand
|
||||||
|
);
|
||||||
|
startPb.start();
|
||||||
|
|
||||||
|
// 等待一小段时间确保进程启动
|
||||||
|
Thread.sleep(2000);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
resCode = 0;
|
resCode = 0;
|
||||||
resMsg = "操作失败: " + e.getMessage();
|
resMsg = "操作失败: " + e.getMessage();
|
||||||
}
|
}
|
||||||
|
// 上报状态
|
||||||
|
reportFrpcStatus(resCode, resMsg, frpPath);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 上报FRPC状态
|
||||||
|
* @param resCode 响应码
|
||||||
|
* @param resMsg 响应消息
|
||||||
|
* @param frpPath frp路径
|
||||||
|
*/
|
||||||
|
private void reportFrpcStatus(int resCode, String resMsg, String frpPath) {
|
||||||
|
long timestamp = System.currentTimeMillis() / 1000;
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
|
||||||
// 基本响应
|
// 基本响应
|
||||||
json.put("resCode", resCode);
|
json.put("resCode", resCode);
|
||||||
@@ -947,7 +978,6 @@ public class AgentServiceImpl implements AgentService {
|
|||||||
AssertLog.info("发送FRP配置文件更新应答={}", JSON.toJSONString(message));
|
AssertLog.info("发送FRP配置文件更新应答={}", JSON.toJSONString(message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从frpc.toml配置文件读取配置
|
* 从frpc.toml配置文件读取配置
|
||||||
*/
|
*/
|
||||||
@@ -999,12 +1029,18 @@ public class AgentServiceImpl implements AgentService {
|
|||||||
/**
|
/**
|
||||||
* 检查frpc进程是否在运行
|
* 检查frpc进程是否在运行
|
||||||
*/
|
*/
|
||||||
private boolean isFrpcRunning() {
|
public boolean isFrpcRunning() {
|
||||||
try {
|
try {
|
||||||
Process process = Runtime.getRuntime().exec(new String[]{"ps", "-ef"});
|
ProcessBuilder pb = new ProcessBuilder(
|
||||||
String output = new String(process.getInputStream().readAllBytes());
|
"bash", "-c", "pgrep -f 'frpc.*toml'"
|
||||||
return output.contains("frpc") && output.contains("-c");
|
);
|
||||||
} catch (IOException e) {
|
|
||||||
|
Process process = pb.start();
|
||||||
|
int exitCode = process.waitFor();
|
||||||
|
AssertLog.info("是否运行:{}",exitCode == 0);
|
||||||
|
return exitCode == 0;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1048,7 +1084,7 @@ public class AgentServiceImpl implements AgentService {
|
|||||||
|
|
||||||
// 写入配置文件
|
// 写入配置文件
|
||||||
Files.write(file.toPath(), newLines, StandardCharsets.UTF_8);
|
Files.write(file.toPath(), newLines, StandardCharsets.UTF_8);
|
||||||
|
AssertLog.info("frpc.toml配置文件修改成功");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("修改frpc配置失败: " + e.getMessage(), e);
|
throw new RuntimeException("修改frpc配置失败: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
@@ -1060,6 +1096,7 @@ public class AgentServiceImpl implements AgentService {
|
|||||||
try (ServerSocket serverSocket = new ServerSocket(port)) {
|
try (ServerSocket serverSocket = new ServerSocket(port)) {
|
||||||
return false; // 端口可用
|
return false; // 端口可用
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
AssertLog.error("端口已被占用或其他异常:{}", e.getMessage());
|
||||||
return true; // 端口已被占用或其他异常
|
return true; // 端口已被占用或其他异常
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1923,4 +1960,104 @@ public class AgentServiceImpl implements AgentService {
|
|||||||
AssertLog.debug("agent更新配置文件不存在: {}", agentUpdateFile.getPath());
|
AssertLog.debug("agent更新配置文件不存在: {}", agentUpdateFile.getPath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void upFrpcMsg() {
|
||||||
|
int resCode = 3;
|
||||||
|
String resMsg = "循环上报frpc状态";
|
||||||
|
String frpPath = properties.getFrpPath();
|
||||||
|
reportFrpcStatus(resCode, resMsg, frpPath);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void checkFrpc() {
|
||||||
|
if (hasConfig() && !isFrpcRunning()) {
|
||||||
|
AssertLog.info("检测到frpc未运行,尝试启动...");
|
||||||
|
startFrpc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private boolean hasConfig() {
|
||||||
|
try {
|
||||||
|
String frpPath = properties.getFrpPath();
|
||||||
|
if (StringUtils.isBlank(frpPath)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
File configFile = new File(frpPath + "/frpc.toml");
|
||||||
|
if (!configFile.exists() || !configFile.isFile()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> lines = Files.readAllLines(configFile.toPath());
|
||||||
|
for (String line : lines) {
|
||||||
|
// 移除行内注释
|
||||||
|
int commentIndex = line.indexOf('#');
|
||||||
|
if (commentIndex != -1) {
|
||||||
|
line = line.substring(0, commentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
line = line.trim();
|
||||||
|
if (line.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否包含 serverAddr
|
||||||
|
if (line.contains("serverAddr")) {
|
||||||
|
// 按等号分割
|
||||||
|
String[] parts = line.split("=", 2);
|
||||||
|
if (parts.length == 2) {
|
||||||
|
String value = parts[1].trim();
|
||||||
|
// 检查等号后面是否有值
|
||||||
|
if (!value.isEmpty()) {
|
||||||
|
// 如果是带引号的值,检查引号内是否有内容
|
||||||
|
if ((value.startsWith("\"") && value.endsWith("\"")) ||
|
||||||
|
(value.startsWith("'") && value.endsWith("'"))) {
|
||||||
|
String innerValue = value.substring(1, value.length() - 1);
|
||||||
|
if (!innerValue.trim().isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 不带引号的值
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public boolean startFrpc() {
|
||||||
|
try {
|
||||||
|
// 先停止可能残留的进程
|
||||||
|
new ProcessBuilder("pkill", "-f", "frpc.*toml").start().waitFor();
|
||||||
|
|
||||||
|
// 构建启动命令
|
||||||
|
String frpcPath = properties.getFrpPath() + "/frpc";
|
||||||
|
String configPath = properties.getFrpPath() + "/frpc.toml";
|
||||||
|
|
||||||
|
File frpcFile = new File(frpcPath);
|
||||||
|
if (!frpcFile.exists() || !frpcFile.canExecute()) {
|
||||||
|
AssertLog.error("frpc可执行文件不存在或无执行权限: {}", frpcPath);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
StringBuilder startCommandBuilder = new StringBuilder();
|
||||||
|
startCommandBuilder.append("nohup ").append(frpcPath).append(" -c ").append(configPath);
|
||||||
|
|
||||||
|
ProcessBuilder pb = new ProcessBuilder(
|
||||||
|
"bash", "-c",
|
||||||
|
startCommandBuilder.toString()
|
||||||
|
);
|
||||||
|
pb.start();
|
||||||
|
|
||||||
|
// 等待2秒后检查是否启动成功
|
||||||
|
Thread.sleep(2000);
|
||||||
|
return isFrpcRunning();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
AssertLog.error("启动frpc失败: {}", e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@@ -262,21 +259,19 @@ public class NetworkInterfaceUtil {
|
|||||||
reader.close();
|
reader.close();
|
||||||
process.waitFor();
|
process.waitFor();
|
||||||
|
|
||||||
// 补充父接口信息
|
// 第一步:收集所有实际存在的网卡名称
|
||||||
Map<String, String> interfaceNames = new HashMap<>();
|
Set<String> existingInterfaceNames = new HashSet<>();
|
||||||
for (NetworkInterfaceDetails iface : interfaces) {
|
for (NetworkInterfaceDetails iface : interfaces) {
|
||||||
interfaceNames.put(iface.name, iface.name);
|
existingInterfaceNames.add(iface.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确保所有父接口都存在
|
// 第二步:检查并清理父网卡设置
|
||||||
for (NetworkInterfaceDetails iface : interfaces) {
|
for (NetworkInterfaceDetails iface : interfaces) {
|
||||||
if (iface.parent != null && !interfaceNames.containsKey(iface.parent)) {
|
if (iface.parent != null) {
|
||||||
// 如果父接口不存在,可能是类似 eth0.203 的情况
|
// 如果父网卡不存在于实际网卡列表中,清空parent字段
|
||||||
if (iface.parent.contains(".")) {
|
if (!existingInterfaceNames.contains(iface.parent)) {
|
||||||
String[] parts = iface.parent.split("\\.");
|
iface.parent = null;
|
||||||
if (parts.length > 0) {
|
iface.realName = null;
|
||||||
iface.parent = parts[0];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user