diff --git a/server/src/main/java/io/wdd/func/controller/XrayController.java b/server/src/main/java/io/wdd/func/controller/XrayController.java index eaeaab0..1084875 100644 --- a/server/src/main/java/io/wdd/func/controller/XrayController.java +++ b/server/src/main/java/io/wdd/func/controller/XrayController.java @@ -16,7 +16,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import static io.wdd.func.xray.beans.node.ProxyNodeSet.*; +import static io.wdd.func.xray.persisit.cache.ProxyNodeCache.*; @RestController @RequestMapping("/server/func/xray") diff --git a/server/src/main/java/io/wdd/func/xray/beans/node/Edge.java b/server/src/main/java/io/wdd/func/xray/beans/node/Edge.java index 07a4e46..90c6f28 100644 --- a/server/src/main/java/io/wdd/func/xray/beans/node/Edge.java +++ b/server/src/main/java/io/wdd/func/xray/beans/node/Edge.java @@ -3,7 +3,6 @@ package io.wdd.func.xray.beans.node; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; @@ -22,7 +21,7 @@ public class Edge { @ApiModelProperty("权重值, 值的范围在0-100,数字越小表示阻力越小") int weight; - Edge(ProxyNode source, ProxyNode destination, int weight) { + public Edge(ProxyNode source, ProxyNode destination, int weight) { this.source = source; this.destination = destination; this.weight = weight; diff --git a/server/src/main/java/io/wdd/func/xray/beans/node/Graph.java b/server/src/main/java/io/wdd/func/xray/beans/node/Graph.java index 51d13f9..21ecc91 100644 --- a/server/src/main/java/io/wdd/func/xray/beans/node/Graph.java +++ b/server/src/main/java/io/wdd/func/xray/beans/node/Graph.java @@ -5,7 +5,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import static io.wdd.func.xray.beans.node.ProxyNodeSet.*; +import static io.wdd.func.xray.persisit.cache.ProxyNodeCache.ProxyNodeStaticMap; /** @@ -91,10 +91,10 @@ class Graph { for (int heigh = 0; heigh < height; heigh++) { List list = adj_matrix.get(heigh); - System.out.print("FROM [ " + ProxyNodeMap.get(heigh) + " ] ==> "); + System.out.print("FROM [ " + ProxyNodeStaticMap.get(heigh) + " ] ==> "); for (int width = 0; width < weight; width++) { if (list.get(width) != 0) { - System.out.print(ProxyNodeMap.get(width) + ": "+ list.get(width) + "\t"); + System.out.print(ProxyNodeStaticMap.get(width) + ": " + list.get(width) + "\t"); } } System.out.print("\n"); diff --git a/server/src/main/java/io/wdd/func/xray/beans/node/ProxyNode.java b/server/src/main/java/io/wdd/func/xray/beans/node/ProxyNode.java index 2cce0dc..857e16c 100644 --- a/server/src/main/java/io/wdd/func/xray/beans/node/ProxyNode.java +++ b/server/src/main/java/io/wdd/func/xray/beans/node/ProxyNode.java @@ -20,13 +20,12 @@ public class ProxyNode { String name; /** - * 用于定位在图中的 顺序位置 + * 用于定位在邻接图(有向加权图)中的 顺序位置 */ int num; String agentName; - String agentTopicName; String location; diff --git a/server/src/main/java/io/wdd/func/xray/beans/node/ProxyNodeType.java b/server/src/main/java/io/wdd/func/xray/beans/node/ProxyNodeType.java index 48368fe..aae30a6 100644 --- a/server/src/main/java/io/wdd/func/xray/beans/node/ProxyNodeType.java +++ b/server/src/main/java/io/wdd/func/xray/beans/node/ProxyNodeType.java @@ -1,13 +1,19 @@ package io.wdd.func.xray.beans.node; +/** + * 关系应该具备包含关系,即下一层的属性包含了上一层的功能 + * ProxyNode的功能层级划分 + */ public enum ProxyNodeType { + // 数据库中标记为0 INTERFACE, - + // 数据库中标记为1 RELAY, - // 关系应该具备包含关系,即下一层的属性包含了上一层的功能 + + // 数据库中标记为0 EXTERNAL } diff --git a/server/src/main/java/io/wdd/func/xray/persisit/XrayDBOperator.java b/server/src/main/java/io/wdd/func/xray/persisit/XrayDBOperator.java new file mode 100644 index 0000000..92baf00 --- /dev/null +++ b/server/src/main/java/io/wdd/func/xray/persisit/XrayDBOperator.java @@ -0,0 +1,134 @@ +package io.wdd.func.xray.persisit; + +import io.wdd.func.xray.beans.node.ProxyNode; +import io.wdd.func.xray.beans.node.XrayConfigInfo; +import io.wdd.server.beans.vo.ServerInfoVO; +import io.wdd.server.coreService.CoreServerService; +import io.wdd.server.service.AppInfoService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +import static io.wdd.func.xray.persisit.cache.ProxyNodeCache.ProxyNodeMap; +import static io.wdd.func.xray.persisit.cache.ProxyNodeCache.ProxyNodeStaticMap; +import static io.wdd.rpc.init.AcceptAgentInitInfo.ALL_SERVER_CITY_INDEX; + +/** + * 为Xray Config信息 操作数据库而创建 + */ +@Service +@Slf4j +public class XrayDBOperator { + + @Resource + CoreServerService coreServerService; + + @Resource + AppInfoService appInfoService; + + @PostConstruct + public void cache() { + + // 初始化就需要缓存相应的信息 + this.CacheAllProxyNodeInfo(); + + } + + + /** + * 从数据库中查询到所有 代理节点的信息,并且生成 ProxyNode然后缓存至 + */ + public void CacheAllProxyNodeInfo() { + + List serverInfoVOList = coreServerService.serverGetAll(); + + transferServerInfoToProxyNode(serverInfoVOList); + + + } + + private void transferServerInfoToProxyNode(List serverInfoVOList) { + + // 临时内容 + int[] bitmap = new int[ALL_SERVER_CITY_INDEX.size()]; + + // + int[] finalBitmap = bitmap; + List proxyNodeList = serverInfoVOList + .stream() + .map( + serverInfoVO -> { + + String serverCity = serverInfoVO + .getLocation() + .split(" ")[0]; + int cityBitMapBase = ALL_SERVER_CITY_INDEX.get(serverCity) * 10; + int serverGraphNum = cityBitMapBase; + for (int index = cityBitMapBase; index < cityBitMapBase + 10; index++) { + if (finalBitmap[index] == 0) { + finalBitmap[index] = 1; + serverGraphNum = index; + break; + } + } + + return ProxyNode + .builder() + .agentTopicName(serverInfoVO.getTopicName()) + .num(serverGraphNum) + .publicIPv4(serverInfoVO.getServerIpPbV4()) + .publicIPv6(serverInfoVO.getServerIpPbV6()) + .name(serverCity + serverGraphNum) + .agentName(serverInfoVO.getServerName()) + .location(serverCity) + .xrayConfigInfo(new XrayConfigInfo()) + .build(); + } + ) + .sorted( + Comparator.comparing( + ProxyNode::getNum + ) + ) + .collect(Collectors.toList()); + + // 收缩邻接表的Index + for (int realIndex = 0; realIndex < proxyNodeList.size(); realIndex++) { + proxyNodeList + .get(realIndex) + .setNum(realIndex); + } + + + // 缓存内容 + ProxyNodeMap.clear(); + ProxyNodeStaticMap.clear(); + + proxyNodeList + .stream() + .forEach( + proxyNode -> { + ProxyNodeMap.put( + proxyNode.getAgentTopicName(), + proxyNode + ); + ProxyNodeStaticMap.put( + proxyNode.getNum(), + proxyNode + ); + } + ); + + + //help gc + bitmap = null; + proxyNodeList = null; + + } + +} diff --git a/server/src/main/java/io/wdd/func/xray/beans/node/EdgeSet.java b/server/src/main/java/io/wdd/func/xray/persisit/cache/EdgeWeightCache.java similarity index 90% rename from server/src/main/java/io/wdd/func/xray/beans/node/EdgeSet.java rename to server/src/main/java/io/wdd/func/xray/persisit/cache/EdgeWeightCache.java index 76195e5..af846f4 100644 --- a/server/src/main/java/io/wdd/func/xray/beans/node/EdgeSet.java +++ b/server/src/main/java/io/wdd/func/xray/persisit/cache/EdgeWeightCache.java @@ -1,8 +1,10 @@ -package io.wdd.func.xray.beans.node; +package io.wdd.func.xray.persisit.cache; -import static io.wdd.func.xray.beans.node.ProxyNodeSet.*; +import io.wdd.func.xray.beans.node.Edge; -public class EdgeSet { +import static io.wdd.func.xray.persisit.cache.ProxyNodeCache.*; + +public class EdgeWeightCache { public static Edge chengduToShanghai; diff --git a/server/src/main/java/io/wdd/func/xray/beans/node/ProxyNodeSet.java b/server/src/main/java/io/wdd/func/xray/persisit/cache/ProxyNodeCache.java similarity index 86% rename from server/src/main/java/io/wdd/func/xray/beans/node/ProxyNodeSet.java rename to server/src/main/java/io/wdd/func/xray/persisit/cache/ProxyNodeCache.java index 7b4471b..c727fbc 100644 --- a/server/src/main/java/io/wdd/func/xray/beans/node/ProxyNodeSet.java +++ b/server/src/main/java/io/wdd/func/xray/persisit/cache/ProxyNodeCache.java @@ -1,10 +1,19 @@ -package io.wdd.func.xray.beans.node; +package io.wdd.func.xray.persisit.cache; + +import io.wdd.func.xray.beans.node.ProxyNode; +import io.wdd.func.xray.beans.node.ProxyNodeType; import java.util.HashMap; -public class ProxyNodeSet { +public class ProxyNodeCache { - public static final HashMap ProxyNodeMap = new HashMap<>(); + /** + * 保存 AgentTopicName - ProxyNode 的全局缓存 + */ + public static final HashMap ProxyNodeMap = new HashMap<>(); + + + public static final HashMap ProxyNodeStaticMap = new HashMap<>(); public static ProxyNode chengdu; public static ProxyNode shanghai; @@ -130,43 +139,43 @@ public class ProxyNodeSet { .agentTopicName("Seoul-arm64-02-oracle") .build(); - ProxyNodeMap.put( + ProxyNodeStaticMap.put( chengdu.getNum(), chengdu ); - ProxyNodeMap.put( + ProxyNodeStaticMap.put( hongkong.getNum(), hongkong ); - ProxyNodeMap.put( + ProxyNodeStaticMap.put( shanghai.getNum(), shanghai ); - ProxyNodeMap.put( + ProxyNodeStaticMap.put( seoul2.getNum(), seoul2 ); - ProxyNodeMap.put( + ProxyNodeStaticMap.put( tokyo2.getNum(), tokyo2 ); - ProxyNodeMap.put( + ProxyNodeStaticMap.put( phoenix2.getNum(), phoenix2 ); - ProxyNodeMap.put( + ProxyNodeStaticMap.put( london2.getNum(), london2 ); - ProxyNodeMap.put( + ProxyNodeStaticMap.put( chengduAgent.getNum(), chengduAgent ); - ProxyNodeMap.put( + ProxyNodeStaticMap.put( tokyoDev.getNum(), tokyoDev ); - ProxyNodeMap.put( + ProxyNodeStaticMap.put( seoul5.getNum(), seoul5 ); diff --git a/server/src/main/java/io/wdd/rpc/init/AcceptAgentInitInfo.java b/server/src/main/java/io/wdd/rpc/init/AcceptAgentInitInfo.java index ed2460c..aa20bd0 100644 --- a/server/src/main/java/io/wdd/rpc/init/AcceptAgentInitInfo.java +++ b/server/src/main/java/io/wdd/rpc/init/AcceptAgentInitInfo.java @@ -13,6 +13,7 @@ import io.wdd.server.utils.DaemonDatabaseOperator; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.core.Message; +import org.springframework.amqp.rabbit.annotation.Queue; import org.springframework.amqp.rabbit.annotation.*; import org.springframework.amqp.support.AmqpHeaders; import org.springframework.data.redis.core.RedisTemplate; @@ -22,10 +23,7 @@ import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.io.IOException; import java.time.LocalDateTime; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Optional; -import java.util.Set; +import java.util.*; import java.util.concurrent.TimeUnit; /** @@ -35,14 +33,31 @@ import java.util.concurrent.TimeUnit; @Slf4j(topic = "octopus agent init ") public class AcceptAgentInitInfo { - public static Set ALL_SERVER_CITY_INFO = new HashSet<>( - Arrays.asList( - "HongKong", "Tokyo", "Seoul", "Phoenix", "London", "Shanghai", "Chengdu" + public static final HashMap ALL_SERVER_CITY_INDEX = new HashMap<>( + Map.of( + "Chengdu", + 1, + "Shanghai", + 2, + "HongKong", + 3, + "Seoul", + 4, + "Tokyo", + 5, + "Phoenix", + 6, + "London", + 7 ) ); public static Set ALL_SERVER_ARCH_INFO = new HashSet<>( Arrays.asList( - "amd64", "arm64", "arm32", "xia32", "miples" + "amd64", + "arm64", + "arm32", + "xia32", + "miples" ) ); @Resource @@ -91,7 +106,10 @@ public class AcceptAgentInitInfo { try { - serverInfoVO = objectMapper.readValue(message.getBody(), ServerInfoVO.class); + serverInfoVO = objectMapper.readValue( + message.getBody(), + ServerInfoVO.class + ); // 1. check if information is correct if (!validateServerInfo(serverInfoVO)) { @@ -132,7 +150,11 @@ public class AcceptAgentInitInfo { // long deliveryTag, boolean multiple, boolean requeue - channel.basicNack(deliveryTag, false, true); + channel.basicNack( + deliveryTag, + false, + true + ); // long deliveryTag, boolean requeue // channel.basicReject(deliveryTag,true); @@ -158,8 +180,14 @@ public class AcceptAgentInitInfo { */ // ack the rabbitmq info // If all logic is successful - log.info("Agent [ {} ] has init successfully !", serverInfoVO.getTopicName()); - channel.basicAck(deliveryTag, false); + log.info( + "Agent [ {} ] has init successfully !", + serverInfoVO.getTopicName() + ); + channel.basicAck( + deliveryTag, + false + ); } private void generateAgentStatusRedisStreamConsumerGroup(String agentTopicName) { @@ -170,7 +198,12 @@ public class AcceptAgentInitInfo { log.debug(" not find the group, recreate"); // not find the group, recreate - redisTemplate.opsForStream().createGroup(statusStreamKey, "OctopusServer"); + redisTemplate + .opsForStream() + .createGroup( + statusStreamKey, + "OctopusServer" + ); } // check for octopus-server consumer group @@ -185,12 +218,18 @@ public class AcceptAgentInitInfo { redisTemplate.opsForStream().createGroup(statusStreamKey, "OctopusServer"); }*/ - log.debug("octopus agent [ {} ] status report stream key [ {} ] has been created !", agentTopicName, statusStreamKey); + log.debug( + "octopus agent [ {} ] status report stream key [ {} ] has been created !", + agentTopicName, + statusStreamKey + ); } private boolean checkAgentAlreadyRegister(String agentQueueTopic) { - Optional first = databaseOperator.getAllServerName().stream(). + Optional first = databaseOperator + .getAllServerName() + .stream(). filter(serverName -> agentQueueTopic.startsWith(serverName)) .findFirst(); @@ -199,7 +238,8 @@ public class AcceptAgentInitInfo { private boolean sendInitMessageToAgent(ServerInfoVO serverInfoVO) { - OctopusMessage octopusMessage = OctopusMessage.builder() + OctopusMessage octopusMessage = OctopusMessage + .builder() .type(OctopusMessageType.INIT) // should be the OctopusExchange Name .content(String.valueOf(initRabbitMQConfig.OCTOPUS_EXCHANGE)) @@ -230,17 +270,29 @@ public class AcceptAgentInitInfo { // topic generate strategy String serverName = serverInfoVO.getServerName(); - serverName.replace(" ", ""); + serverName.replace( + " ", + "" + ); serverInfoVO.setServerName(serverName); // validate serverName String[] split = serverName.split("-"); - if (split.length <= 2 || !ALL_SERVER_CITY_INFO.contains(split[0]) || !ALL_SERVER_ARCH_INFO.contains(split[1])) { - log.error("server info from agent are {}", serverInfoVO); + if (split.length <= 2 || !ALL_SERVER_CITY_INDEX.containsKey(split[0]) || !ALL_SERVER_ARCH_INFO.contains(split[1])) { + log.error( + "server info from agent are {}", + serverInfoVO + ); throw new MyRuntimeException("server name not validated !"); } - String machineIdPrefixSixBytes = String.valueOf(serverInfoVO.getMachineId().toCharArray(), 0, 6); + String machineIdPrefixSixBytes = String.valueOf( + serverInfoVO + .getMachineId() + .toCharArray(), + 0, + 6 + ); return serverName + "-" + machineIdPrefixSixBytes; }