networkPathList) {
diff --git a/server/src/main/java/io/wdd/func/xray/service/XrayConfigPersistor.java b/server/src/main/java/io/wdd/func/xray/service/XrayConfigPersistor.java
index a136af5..100a8ec 100644
--- a/server/src/main/java/io/wdd/func/xray/service/XrayConfigPersistor.java
+++ b/server/src/main/java/io/wdd/func/xray/service/XrayConfigPersistor.java
@@ -1,7 +1,17 @@
package io.wdd.func.xray.service;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.util.DefaultIndenter;
+import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectWriter;
import io.wdd.common.handler.MyRuntimeException;
+import io.wdd.common.utils.TimeUtils;
+import io.wdd.func.xray.beans.node.ProxyNode;
+import io.wdd.func.xray.beans.node.XrayConfigInfo;
+import io.wdd.func.xray.beans.xray.XrayConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.core.io.ClassPathResource;
@@ -15,22 +25,79 @@ import java.util.concurrent.atomic.AtomicInteger;
/**
* 获取rerouces目录 https://blog.csdn.net/pengpengpeng85/article/details/84785575
- *
+ *
* 写入文件的教程 https://cloud.tencent.com/developer/article/1895274
*/
@Slf4j
@Service
public class XrayConfigPersistor {
- private static String XrayResultPath = "xrayResult/";
-
-
+ // 参考 https://github.com/FasterXML/jackson-databind/issues/585
+ private static final ObjectWriter objectWriter = new ObjectMapper()
+ // 忽略掉 null的字段
+ .setSerializationInclusion(JsonInclude.Include.NON_NULL)
+ // 写的文件必须是unix类型的分隔符号
+ .writer(
+ new DefaultPrettyPrinter()
+ .withObjectIndenter(
+ new DefaultIndenter()
+ .withLinefeed("\n")
+ ));
+ private static final String XrayResultPath = "xrayResult/";
public static AtomicInteger cleanVersion = new AtomicInteger(0);
+ /**
+ * 执行Xray生成配置文件的持久化工作,沈成伟临时文件保存至当前目录中
+ *
+ * @param xrayConfig
+ * @param currentVersion
+ * @param proxyNode
+ * @return
+ */
+ public XrayConfigInfo persist(XrayConfig xrayConfig, int currentVersion, ProxyNode proxyNode) {
+ try {
+ // 将生成的xrayConfig直接写为字符串
+ String resultContent = objectWriter
+ .writeValueAsString(xrayConfig);
- public File write(String fileName , String content, int currentVersion) {
+ // 获得到文件名称
+ String timeString = TimeUtils.currentFormatTimeString();
+ String fileName = buildXrayConfigFileName(
+ proxyNode,
+ timeString
+ );
- System.out.println("currentVersion = " + currentVersion);
+ // 文件持久化!
+ File xrayConfigFile = write(
+ fileName,
+ resultContent,
+ currentVersion
+ );
+
+ // 文件写入完成,保存文件信息
+ XrayConfigInfo xrayConfigInfo = new XrayConfigInfo();
+ xrayConfigInfo.setXrayConfigFile(xrayConfigFile);
+ xrayConfigInfo.setXrayConfigFileName(fileName);
+
+ return xrayConfigInfo;
+
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private String buildXrayConfigFileName(ProxyNode proxyNode, String timeString) {
+
+ return proxyNode.getNum() + "-" + proxyNode.getAgentName() + "-" + timeString + ".json";
+
+ }
+
+ private File write(String fileName, String content, int currentVersion) {
+
+ log.debug(
+ "currentVersion = {}",
+ currentVersion
+ );
if (cleanVersion.get() == currentVersion) {
// 清除旧的内容
@@ -41,29 +108,51 @@ public class XrayConfigPersistor {
// 构造对象开始写入, 生成文件
File resultFile = getResultFile(fileName);
- try {
- log.debug("开始写入XrayConfig进入文件中,文件名为 => {}",fileName);
- FileWriter fileWriter = new FileWriter(
+ FileWriter fileWriter = null;
+ BufferedWriter bufferedWriter = null;
+
+ try {
+ log.debug(
+ "开始写入XrayConfig进入文件中,文件名为 => {}",
+ fileName
+ );
+ fileWriter = new FileWriter(
resultFile
);
- BufferedWriter bufferedWriter = new BufferedWriter(
+ bufferedWriter = new BufferedWriter(
fileWriter
);
- log.debug("文件内容为 => {}", content);
+ log.debug(
+ "文件内容为 => {}",
+ content
+ );
bufferedWriter.write(content);
- // must close
- bufferedWriter.close();
- fileWriter.close();
-
-
return resultFile;
} catch (IOException e) {
- log.error("打开文件失败,写入tmp文件失败! 文件为 => {}", resultFile.getName());
+ log.error(
+ "打开文件失败,写入tmp文件失败! 文件为 => {}",
+ resultFile.getName()
+ );
throw new MyRuntimeException(e);
+ } finally {
+
+ try {
+ // must close
+ bufferedWriter.close();
+ fileWriter.close();
+
+ } catch (IOException e) {
+ log.error(
+ "关闭文件写入流失败!, 请检查 文件为 => [ {} ], 内容为 => {}",
+ fileName,
+ content
+ );
+ throw new MyRuntimeException(e);
+ }
}
}
@@ -82,11 +171,12 @@ public class XrayConfigPersistor {
}
/**
- * 根据文件名,需要创建一个文件
+ * 根据文件名,需要创建一个文件
+ *
* @param fileName 文件名,如 xxx.json
* @return
*/
- private File getResultFile(String fileName ){
+ private File getResultFile(String fileName) {
ClassPathResource classPathResource = new ClassPathResource(XrayResultPath);
@@ -99,7 +189,10 @@ public class XrayConfigPersistor {
);
} catch (IOException e) {
- log.error("获取文件失败请检查! fileName is => {}", fileName);
+ log.error(
+ "获取文件失败请检查! fileName is => {}",
+ fileName
+ );
throw new MyRuntimeException(e);
}
diff --git a/server/src/main/java/io/wdd/func/xray/service/XrayCoreServiceImpl.java b/server/src/main/java/io/wdd/func/xray/service/XrayCoreServiceImpl.java
index e2ecd42..0e15ff0 100644
--- a/server/src/main/java/io/wdd/func/xray/service/XrayCoreServiceImpl.java
+++ b/server/src/main/java/io/wdd/func/xray/service/XrayCoreServiceImpl.java
@@ -1,9 +1,5 @@
package io.wdd.func.xray.service;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import io.wdd.common.utils.TimeUtils;
import io.wdd.func.xray.beans.node.ProxyNode;
import io.wdd.func.xray.beans.node.XrayConfigInfo;
import io.wdd.func.xray.beans.xray.RoutingObject;
@@ -20,7 +16,6 @@ import org.apache.commons.beanutils.BeanUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
-import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
@@ -36,13 +31,9 @@ import static io.wdd.func.xray.service.XrayConfigPersistor.cleanVersion;
@Slf4j
public class XrayCoreServiceImpl implements XrayCoreService {
- @Resource
- ObjectMapper objectMapper;
-
@Resource
XrayConfigPersistor xrayConfigPersistor;
-
@Override
public void generateXrayJsonFromNodeList(ArrayList> allNetworkPathList) {
@@ -81,9 +72,6 @@ public class XrayCoreServiceImpl implements XrayCoreService {
private void generateXrayJsonSinglePath(ArrayList networkPathList) {
int pathLength = networkPathList.size();
- // 忽略掉 null的字段
- objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
-
// 采用 VMESS + websocket的形式形成 链状代理
// 由于 Vlss+XTLS的形式形成 链状结构
String tag = generatePathTag(networkPathList);
@@ -97,7 +85,8 @@ public class XrayCoreServiceImpl implements XrayCoreService {
.builder()
.id(uuid)
.level(0)
- .alterId(23)
+ // 为了进一步防止被探测,一个用户可以在主 ID 的基础上,再额外生成多个 ID。这里只需要指定额外的 ID 的数量,推荐值为 0 代表启用 VMessAEAD
+ .alterId(0)
.email(tag + "@octopus.io")
.build();
@@ -123,46 +112,19 @@ public class XrayCoreServiceImpl implements XrayCoreService {
pos
);
- // 持久化
- try {
- String resultContent = objectMapper
- .writerWithDefaultPrettyPrinter()
- .writeValueAsString(xrayConfig);
+ // 持久化 Xray生成的文件信息
+ XrayConfigInfo xrayConfigInfo = xrayConfigPersistor.persist(
+ xrayConfig,
+ currentVersion,
+ proxyNode
+ );
- // 获得到文件名称
- String timeString = TimeUtils.currentFormatTimeString();
- String fileName = buildXrayConfigFileName(
- proxyNode,
- timeString
- );
-
- // 文件持久化!
- File xrayConfigFile = xrayConfigPersistor.write(
- fileName,
- resultContent,
- currentVersion
- );
-
- // 文件写入完成,保存文件信息
- XrayConfigInfo xrayConfigInfo = new XrayConfigInfo();
- xrayConfigInfo.setXrayConfigFile(xrayConfigFile);
- xrayConfigInfo.setXrayConfigFileName(fileName);
-
- proxyNode.setXrayConfigInfo(xrayConfigInfo);
-
- } catch (JsonProcessingException e) {
- throw new RuntimeException(e);
- }
+ proxyNode.setXrayConfigInfo(xrayConfigInfo);
}
-
}
- private String buildXrayConfigFileName(ProxyNode proxyNode, String timeString) {
- return proxyNode.getNum() + "-" + proxyNode.getAgentName() + "-" + timeString + ".json";
-
- }
private XrayConfig doBuildXrayConfig(boolean isOutBoundFree, String tag, ClientObject clientObject, int port, ArrayList networkPathList, int pos) {
diff --git a/server/src/main/java/io/wdd/rpc/agent/OctopusAgentServiceImpl.java b/server/src/main/java/io/wdd/rpc/agent/OctopusAgentServiceImpl.java
index 6de5c49..408d47a 100644
--- a/server/src/main/java/io/wdd/rpc/agent/OctopusAgentServiceImpl.java
+++ b/server/src/main/java/io/wdd/rpc/agent/OctopusAgentServiceImpl.java
@@ -19,7 +19,6 @@ import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDateTime;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -31,7 +30,6 @@ import java.util.stream.Collectors;
import static io.wdd.rpc.init.ServerCacheAgentStatus.ALL_AGENT_TOPIC_NAME_SET;
import static io.wdd.rpc.init.ServerCacheAgentStatus.ALL_HEALTHY_AGENT_TOPIC_NAME_LIST;
-import static io.wdd.rpc.message.handler.AsyncWaitOMResult.REPLAY_CACHE_MAP;
import static io.wdd.rpc.message.handler.OMessageHandlerServer.AGENT_LATEST_VERSION;
import static io.wdd.rpc.message.handler.OMessageHandlerServer.OCTOPUS_MESSAGE_FROM_AGENT;
@@ -67,7 +65,6 @@ public class OctopusAgentServiceImpl implements OctopusAgentService {
// 组装信息至集合中
LocalDateTime currentTime = TimeUtils.currentFormatTime();
-
// 发送OctopusMessage-Agent
buildOMessageAndSendToAllHealthyAgent(
AgentOperationType.VERSION,
@@ -75,21 +72,14 @@ public class OctopusAgentServiceImpl implements OctopusAgentService {
);
// 构造 异步结果监听内容
- CountDownLatch countDownLatch = new CountDownLatch(ALL_HEALTHY_AGENT_TOPIC_NAME_LIST.size());
- ArrayList replayOMList = new ArrayList<>();
- OMReplayContend omReplayContend = OMReplayContend
- .builder()
- .initTime(currentTime)
- .countDownLatch(countDownLatch)
- .replayOMList(replayOMList)
- .replayMatchKey(
- OMReplayContend.generateMatchKey(
- CurrentAppOctopusMessageType,
- currentTime
- )
- )
- .type(CurrentAppOctopusMessageType)
- .build();
+ OMReplayContend omReplayContend = OMReplayContend.build(
+ ALL_HEALTHY_AGENT_TOPIC_NAME_LIST.size(),
+ CurrentAppOctopusMessageType,
+ currentTime
+ );
+
+ CountDownLatch countDownLatch = omReplayContend.getCountDownLatch();
+
// 调用后台接收处理所有的Replay信息
asyncWaitOMResult.waitFor(omReplayContend);
@@ -101,21 +91,24 @@ public class OctopusAgentServiceImpl implements OctopusAgentService {
countDownLatch
);*/
+
+ boolean isAllHealthyAgentReport = false;
try {
// 超时等待5秒钟, 或者所有的Agent均已经完成上报
- countDownLatch.await(
+ isAllHealthyAgentReport = countDownLatch.await(
5,
TimeUnit.SECONDS
);
} catch (InterruptedException e) {
- log.warn("存在部分Agent没有上报 版本信息!");
+
} finally {
// 超时,或者 全部信息已经收集
+ if (!isAllHealthyAgentReport) {
+ log.warn("存在部分Agent没有上报 版本信息!");
+ }
// 此处调用,即可中断 异步任务的收集工作
- REPLAY_CACHE_MAP.remove(
- omReplayContend.getReplayMatchKey()
- );
+ asyncWaitOMResult.stopWaiting(omReplayContend);
// 处理结果
omReplayContend
@@ -132,7 +125,6 @@ public class OctopusAgentServiceImpl implements OctopusAgentService {
// help gc
omReplayContend = null;
-
}
return result;
@@ -165,21 +157,14 @@ public class OctopusAgentServiceImpl implements OctopusAgentService {
currentTime
);
- CountDownLatch countDownLatch = new CountDownLatch(ALL_HEALTHY_AGENT_TOPIC_NAME_LIST.size());
- ArrayList replayOMList = new ArrayList<>();
- OMReplayContend omReplayContend = OMReplayContend
- .builder()
- .initTime(currentTime)
- .countDownLatch(countDownLatch)
- .replayOMList(replayOMList)
- .replayMatchKey(
- OMReplayContend.generateMatchKey(
- CurrentAppOctopusMessageType,
- currentTime
- )
- )
- .type(CurrentAppOctopusMessageType)
- .build();
+ // 构造结果
+ OMReplayContend omReplayContend = OMReplayContend.build(
+ ALL_HEALTHY_AGENT_TOPIC_NAME_LIST.size(),
+ CurrentAppOctopusMessageType,
+ currentTime
+ );
+
+ CountDownLatch countDownLatch = omReplayContend.getCountDownLatch();
// 调用后台接收处理所有的Replay信息
asyncWaitOMResult.waitFor(omReplayContend);
@@ -202,9 +187,7 @@ public class OctopusAgentServiceImpl implements OctopusAgentService {
// 超时,或者 全部信息已经收集
// 此处调用,即可中断 异步任务的收集工作
- REPLAY_CACHE_MAP.remove(
- omReplayContend.getReplayMatchKey()
- );
+ asyncWaitOMResult.stopWaiting(omReplayContend);
// 处理结果
omReplayContend
diff --git a/server/src/main/java/io/wdd/rpc/controller/AgentController.java b/server/src/main/java/io/wdd/rpc/controller/AgentController.java
index 4e946b4..ed1c9c4 100644
--- a/server/src/main/java/io/wdd/rpc/controller/AgentController.java
+++ b/server/src/main/java/io/wdd/rpc/controller/AgentController.java
@@ -14,21 +14,21 @@ import java.util.Map;
@RestController
@RequestMapping("/octopus/server/agent")
-@Api("处理Agent核心内容的Controller")
+@Api(value = "处理Agent核心内容的Controller", tags = "Agent")
public class AgentController {
@Resource
OctopusAgentService octopusAgentService;
@GetMapping("/version")
- @ApiOperation("[版本]-所有OctopusAgent")
+ @ApiOperation("[版本] - 所有OctopusAgent")
public R