diff --git a/tongran-api/tongran-api-system/src/main/java/com/tongran/system/api/domain/RmResourceRegistrationRemote.java b/tongran-api/tongran-api-system/src/main/java/com/tongran/system/api/domain/RmResourceRegistrationRemote.java index 1f1e468..8356fb0 100644 --- a/tongran-api/tongran-api-system/src/main/java/com/tongran/system/api/domain/RmResourceRegistrationRemote.java +++ b/tongran-api/tongran-api-system/src/main/java/com/tongran/system/api/domain/RmResourceRegistrationRemote.java @@ -180,5 +180,11 @@ public class RmResourceRegistrationRemote extends BaseEntity private Date onboardTime; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date delAlarmTime; + /** FRP连接地址生成状态(0-未生成,1-生成中,2已生成) */ + private String frpcConnectionStatus; + /** FRPC远程端口 */ + private String frpcRemotePort; + /** FRPC服务器地址 */ + private String frpcServerAddr; } diff --git a/tongran-modules/tongran-system/src/main/java/com/tongran/system/domain/RmResourceRegistration.java b/tongran-modules/tongran-system/src/main/java/com/tongran/system/domain/RmResourceRegistration.java index 3b4a1aa..34c9e81 100644 --- a/tongran-modules/tongran-system/src/main/java/com/tongran/system/domain/RmResourceRegistration.java +++ b/tongran-modules/tongran-system/src/main/java/com/tongran/system/domain/RmResourceRegistration.java @@ -266,4 +266,10 @@ public class RmResourceRegistration extends BaseEntity /** 取消告警时间 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date delAlarmTime; + /** FRP连接地址生成状态(0-未生成,1-生成中,2已生成) */ + private String frpcConnectionStatus; + /** FRPC远程端口 */ + private String frpcRemotePort; + /** FRPC服务器地址 */ + private String frpcServerAddr; } \ No newline at end of file diff --git a/tongran-modules/tongran-system/src/main/resources/mapper/system/RmResourceRegistrationMapper.xml b/tongran-modules/tongran-system/src/main/resources/mapper/system/RmResourceRegistrationMapper.xml index bfbf72e..afd242f 100644 --- a/tongran-modules/tongran-system/src/main/resources/mapper/system/RmResourceRegistrationMapper.xml +++ b/tongran-modules/tongran-system/src/main/resources/mapper/system/RmResourceRegistrationMapper.xml @@ -25,6 +25,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + + @@ -239,11 +242,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" a.reported_bandwidth as reportedBandwidth, a.del_alarm_time as delAlarmTime, b.machine_code as machineCode, + c.frpc_connection_status frpcConnectionStatus, + c.frpc_remote_port frpcRemotePort, + c.frpc_server_addr frpcServerAddr, (select bandwidth_result from eps_node_bandwidth where client_id=a.client_id and calculation_mode='1000' and bandwidth_type='1' AND create_time = DATE(DATE_SUB(NOW(), INTERVAL 1 DAY)) limit 1) as bandwidthResult from rm_resource_registration a left join rm_registration_machine b on a.client_id = b.client_id + left join rm_frpc_config_manage c on a.client_id=c.client_id and a.hardware_sn = #{hardwareSn} and a.resource_type = #{resourceType} diff --git a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/controller/RmFrpcConfigManageController.java b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/controller/RmFrpcConfigManageController.java index 98231f3..c67cea6 100644 --- a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/controller/RmFrpcConfigManageController.java +++ b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/controller/RmFrpcConfigManageController.java @@ -47,7 +47,6 @@ public class RmFrpcConfigManageController extends BaseController /** * 导出FRPC配置管理列表 */ - @RequiresPermissions("rocketmq:frpcConfigManage:export") @Log(title = "FRPC配置管理", businessType = BusinessType.EXPORT) @PostMapping("/export") public void export(HttpServletResponse response, @RequestBody RmFrpcConfigManage rmFrpcConfigManage) @@ -61,7 +60,6 @@ public class RmFrpcConfigManageController extends BaseController /** * 获取FRPC配置管理详细信息 */ - @RequiresPermissions("rocketmq:frpcConfigManage:query") @GetMapping(value = "/{id}") public AjaxResult getInfo(@PathVariable("id") Long id) { @@ -71,7 +69,6 @@ public class RmFrpcConfigManageController extends BaseController /** * 新增FRPC配置管理 */ - @RequiresPermissions("rocketmq:frpcConfigManage:add") @Log(title = "FRPC配置管理", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@RequestBody RmFrpcConfigManage rmFrpcConfigManage) @@ -82,7 +79,6 @@ public class RmFrpcConfigManageController extends BaseController /** * 修改FRPC配置管理 */ - @RequiresPermissions("rocketmq:frpcConfigManage:edit") @Log(title = "FRPC配置管理", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit(@RequestBody RmFrpcConfigManage rmFrpcConfigManage) @@ -93,7 +89,6 @@ public class RmFrpcConfigManageController extends BaseController /** * 删除FRPC配置管理 */ - @RequiresPermissions("rocketmq:frpcConfigManage:remove") @Log(title = "FRPC配置管理", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") public AjaxResult remove(@PathVariable Long[] ids) diff --git a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/controller/RmFrpcPortMappingController.java b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/controller/RmFrpcPortMappingController.java index 5ffc89a..58ae6dd 100644 --- a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/controller/RmFrpcPortMappingController.java +++ b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/controller/RmFrpcPortMappingController.java @@ -20,6 +20,7 @@ import java.util.List; */ @RestController @RequestMapping("/frpcPortMapping") +@RequiresPermissions("rocketmq:frpcConfigManage") public class RmFrpcPortMappingController extends BaseController { @Autowired @@ -28,7 +29,6 @@ public class RmFrpcPortMappingController extends BaseController /** * 查询FRPC端口映射配置列表 */ - @RequiresPermissions("rocketmq:frpcPortMapping:list") @PostMapping("/list") public AjaxResult list(@RequestBody RmFrpcPortMapping rmFrpcPortMapping) { diff --git a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/domain/vo/FrpRspVo.java b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/domain/vo/FrpRspVo.java index e3d037b..dc564de 100644 --- a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/domain/vo/FrpRspVo.java +++ b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/domain/vo/FrpRspVo.java @@ -9,7 +9,7 @@ import java.time.Instant; @JsonIgnoreProperties(ignoreUnknown = true) public class FrpRspVo { /** - * 状态码,0、失败;1、成功 + * 状态码,0、失败;1、成功;2、端口冲突;3、frpc状态上报; */ private Integer resCode; /** diff --git a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/handler/MessageHandler.java b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/handler/MessageHandler.java index 8ff9eb3..a243a12 100644 --- a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/handler/MessageHandler.java +++ b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/handler/MessageHandler.java @@ -53,6 +53,9 @@ public class MessageHandler { String HEARTBEAT_RECOVERY_COUNT_PREFIX = "heartbeat:recovery:count:"; String HEARTBEAT_COUNT_PREFIX = "heartbeat:count:"; + + // Redis key定义 + private static final String USED_PORTS_KEY = "frpc:used_ports"; private static final long HEARTBEAT_TIMEOUT = 30000; // 3分钟超时 @@ -149,12 +152,44 @@ public class MessageHandler { RmFrpcConfigManage configManage = new RmFrpcConfigManage(); configManage.setFrpcRemotePort(rsp.getRemotePort()); rmFrpcConfigManageService.addFrpConnect(configManage); + } else if(rsp.getResCode() == 3){ + // frpc状态上报 + RmFrpcConfigManage frpcData = new RmFrpcConfigManage(); + frpcData.setClientId(message.getClientId()); + frpcData.setFrpcName(rsp.getName()); + frpcData.setFrpcStatus(rsp.getIsRunning()); + frpcData.setFrpcLocalPort(rsp.getLocalPort()); + frpcData.setFrpcLocalIp(rsp.getLocalIP()); + frpcData.setFrpcCreateTime(createTime); + frpcData.setFrpcRemotePort(rsp.getRemotePort()); + frpcData.setFrpcServerAddr(rsp.getServerAddr()); + frpcData.setFrpcServerPort(rsp.getServerPort()); + rmFrpcConfigManageService.insertRmFrpcConfigManage(frpcData); } else{ + if(rsp.getRemotePort() != null){ + // 生成失败 ,释放端口资源 + removeUsedPort(Integer.parseInt(rsp.getRemotePort())); + } log.error("生成连接失败:{}",rsp.getResMsg()); } } } + /** + * 添加端口到已用集合 + */ + public boolean addUsedPort(int port) { + Long result = redisTemplate.opsForSet().add(USED_PORTS_KEY, String.valueOf(port)); + return result != null && result > 0; + } + + /** + * 从已用集合中移除端口 + */ + public boolean removeUsedPort(int port) { + Long result = redisTemplate.opsForSet().remove(USED_PORTS_KEY, String.valueOf(port)); + return result != null && result > 0; + } /** * 保存网卡信息 * @param message @@ -1070,6 +1105,20 @@ public class MessageHandler { } boolean isSingleInterface = networkInfoList.size() == 1; + boolean isMultiInterface = networkInfoList.size() > 1; + + // 查询数据库中当前的网卡数量 + RmNetworkInterface countQuery = new RmNetworkInterface(); + countQuery.setClientId(clientId); + countQuery.setNewFlag(1); + List currentInterfaces = rmNetworkInterfaceService.selectRmNetworkInterfaceList(countQuery); + int currentInterfaceCount = currentInterfaces.size(); + + // 判断网卡数量是否发生变化 + boolean interfaceCountChanged = false; + if (!isRegister && currentInterfaceCount != networkInfoList.size()) { + interfaceCountChanged = true; + } for (NetworkInfo networkInfo : networkInfoList) { List childList = networkInfo.getSubInterfaces(); @@ -1101,13 +1150,20 @@ public class MessageHandler { rmNetworkInterfaceChildService.insertRmNetworkInterfaceChild(insertChild); } } + // 如果网卡数量有变动,需要更新网卡绑定状态 + if (!isRegister && interfaceCountChanged) { + RmResourceRegistrationRemote updateParam = new RmResourceRegistrationRemote(); + updateParam.setClientId(clientId); + updateParam.setMultiPublicIpStatus("0"); + remoteRevenueConfigService.updateStatusByResource(updateParam, SecurityConstants.INNER); + } } else { // 更新网卡信息 RmNetworkInterface oldInterfaceMsg = exits.get(0); cleanChildOldRecords(clientId, networkInfo.getMac()); // 判断是否需要创建新记录 - boolean needCreateNew = !StringUtils.equals(networkInfo.getName(), oldInterfaceMsg.getInterfaceName()) - || !StringUtils.equals(networkInfo.getGateway(), oldInterfaceMsg.getGateway()); + boolean needCreateNew = (!StringUtils.equals(networkInfo.getName(), oldInterfaceMsg.getInterfaceName()) + || !StringUtils.equals(networkInfo.getGateway(), oldInterfaceMsg.getGateway())) && StringUtils.equals(networkInfo.getMac(), oldInterfaceMsg.getMacAddress()); if(childList != null && !childList.isEmpty()){ for (NetworkInfo info : childList) { RmNetworkInterfaceChild insertChild = new RmNetworkInterfaceChild(); @@ -1130,6 +1186,13 @@ public class MessageHandler { RmNetworkInterface insertData = new RmNetworkInterface(); setNetworkInterfaceData(insertData, networkInfo, clientId); rmNetworkInterfaceService.insertRmNetworkInterface(insertData); + // 如果网卡名称有变化,需要更新网卡绑定状态 + if(!isRegister && !StringUtils.equals(networkInfo.getName(), oldInterfaceMsg.getInterfaceName())){ + RmResourceRegistrationRemote updateParam = new RmResourceRegistrationRemote(); + updateParam.setClientId(clientId); + updateParam.setMultiPublicIpStatus("0"); + remoteRevenueConfigService.updateStatusByResource(updateParam, SecurityConstants.INNER); + } } else { // 更新现有记录 updateNetworkInterface(networkInfo, clientId, oldInterfaceMsg, isSingleInterface, isRegister); diff --git a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/RmFrpcConfigManageServiceImpl.java b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/RmFrpcConfigManageServiceImpl.java index 6c4f181..3bf4410 100644 --- a/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/RmFrpcConfigManageServiceImpl.java +++ b/tongran-rocketmq/src/main/java/com/tongran/rocketmq/service/impl/RmFrpcConfigManageServiceImpl.java @@ -159,10 +159,12 @@ public class RmFrpcConfigManageServiceImpl implements IRmFrpcConfigManageService @Override public int addFrpConnect(RmFrpcConfigManage rmFrpcConfigManage) { + rmFrpcConfigManage.setFrpcConnectionStatus(1L); + int rows = rmFrpcConfigManageMapper.insertRmFrpcConfigManage(rmFrpcConfigManage); // 查询frps配置 List portMappingList = rmFrpcPortMappingMapper.selectRmFrpcPortMappingList(new RmFrpcPortMapping()); - Integer startRemotePort = rmFrpcConfigManage.getStartRemotePort(); - Integer endRemotePort = rmFrpcConfigManage.getEndRemotePort(); + Integer startRemotePort = null; + Integer endRemotePort = null; String serverPort = null; String serverAddr = null; if(portMappingList != null && !portMappingList.isEmpty()){ @@ -181,7 +183,7 @@ public class RmFrpcConfigManageServiceImpl implements IRmFrpcConfigManageService addUsedPort(Integer.parseInt(rmFrpcConfigManage.getFrpcRemotePort())); } // 获取一个可用的随机端口 - int availablePort = getRandomAvailablePort(startRemotePort, endRemotePort); + int availablePort = getRandomAvailablePort(clientId, startRemotePort, endRemotePort); if (availablePort != -1) { // 将端口标记为已使用 @@ -243,6 +245,35 @@ public class RmFrpcConfigManageServiceImpl implements IRmFrpcConfigManageService return -1; // 没有可用端口 } + public int getRandomAvailablePort(String clientId, int startPort, int endPort) { + // 1. 先清理这个客户端可能存在的旧端口 + cleanupClientOldPorts(clientId); + + // 2. 获取新端口 + int newPort = getRandomAvailablePort(startPort, endPort); + + // 3. 记录客户端与端口的关联 + if (newPort != -1) { + redisTemplate.opsForHash().put( + "client:port:mapping", + clientId, + String.valueOf(newPort) + ); + } + + return newPort; + } + + /** + * 清理客户端旧端口 + */ + private void cleanupClientOldPorts(String clientId) { + Object oldPortObj = redisTemplate.opsForHash().get("client:port:mapping", clientId); + if (oldPortObj != null) { + int oldPort = Integer.parseInt(oldPortObj.toString()); + removeUsedPort(oldPort); + } + } /** * 判断端口是否可用(只检查Redis中是否存在) diff --git a/tongran-rocketmq/src/main/resources/mapper/rocketmq/RmNetworkInterfaceMapper.xml b/tongran-rocketmq/src/main/resources/mapper/rocketmq/RmNetworkInterfaceMapper.xml index d2e87ea..bcbeb8f 100644 --- a/tongran-rocketmq/src/main/resources/mapper/rocketmq/RmNetworkInterfaceMapper.xml +++ b/tongran-rocketmq/src/main/resources/mapper/rocketmq/RmNetworkInterfaceMapper.xml @@ -149,7 +149,6 @@ city = #{city}, public_ip = #{publicIp}, interface_name = #{interfaceName}, - mac_address = #{macAddress}, interface_type = #{interfaceType}, ipv4_address = #{ipv4Address}, ipv6_address = #{ipv6Address},