1、优化子网卡流量图形展示。
2、优化接口名称存储逻辑,减少死锁。 3、增加cpu利用率内存利用率字段。
This commit is contained in:
+15
@@ -17,6 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -153,6 +154,20 @@ public class RmResourceRegistrationController extends BaseController
|
||||
List<RmResourceRegistration> list = rmResourceRegistrationService.selectRmResourceRegistrationList(rmResourceRegistration);
|
||||
return success(list);
|
||||
}
|
||||
@GetMapping("/getAlarmFlag")
|
||||
public AjaxResult getAlarmFlag()
|
||||
{
|
||||
List<RmResourceRegistration> list = rmResourceRegistrationService.selectRmResourceRegistrationList(new RmResourceRegistration());
|
||||
for (RmResourceRegistration item : list) {
|
||||
boolean isAlarm = (item.getCpuUtil() != null && item.getCpuUtil().compareTo(BigDecimal.valueOf(80)) >= 0) ||
|
||||
(item.getMemUtil() != null && item.getMemUtil().compareTo(BigDecimal.valueOf(60)) >= 0);
|
||||
|
||||
if (isAlarm) {
|
||||
return success(true); // 只要有一个告警就返回
|
||||
}
|
||||
}
|
||||
return success(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动注册服务器
|
||||
|
||||
+2
@@ -81,5 +81,7 @@ public class AllInterfaceName extends BaseEntity
|
||||
private String label;
|
||||
/** 是否需要展开 */
|
||||
private boolean expand;
|
||||
/** 是否业务网卡 */
|
||||
private boolean businessFlag;
|
||||
|
||||
}
|
||||
|
||||
+6
@@ -257,4 +257,10 @@ public class RmResourceRegistration extends BaseEntity
|
||||
private String bandwidthRate;
|
||||
/** 昨日95值排序 1正序 2倒叙 3不排序 */
|
||||
private Integer bandwidthResultSort;
|
||||
/** cpu利用率 */
|
||||
private BigDecimal cpuUtil;
|
||||
/** 内存使用率 */
|
||||
private BigDecimal memUtil;
|
||||
/** 是否告警 */
|
||||
private boolean alarmFlag;
|
||||
}
|
||||
+4
@@ -122,4 +122,8 @@ public interface RmResourceRegistrationMapper
|
||||
*/
|
||||
int countChildNetwork(@Param("clientId") String clientId,
|
||||
@Param("interfaceName") String interfaceName);
|
||||
|
||||
List<RmResourceRegistration> getCpuUtil(@Param("clientIdsStr") String clientIdsStr);
|
||||
|
||||
List<RmResourceRegistration> getMemUtil(@Param("clientIdsStr") String clientIdsStr);
|
||||
}
|
||||
|
||||
+19
-6
@@ -15,7 +15,9 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -58,6 +60,7 @@ public class AllInterfaceNameServiceImpl implements IAllInterfaceNameService
|
||||
if (allInterfaceNameList == null || allInterfaceNameList.isEmpty()) {
|
||||
return allInterfaceNameList;
|
||||
}
|
||||
|
||||
// 用于存储非子网卡的接口
|
||||
List<AllInterfaceName> nonSubInterfaces = new ArrayList<>();
|
||||
for (AllInterfaceName interfaceName : allInterfaceNameList) {
|
||||
@@ -77,21 +80,31 @@ public class AllInterfaceNameServiceImpl implements IAllInterfaceNameService
|
||||
if (nonSubInterfaces.isEmpty()) {
|
||||
return nonSubInterfaces;
|
||||
}
|
||||
|
||||
// 缓存匹配结果,避免重复计算
|
||||
Map<AllInterfaceName, Boolean> matchStatusMap = new HashMap<>();
|
||||
for (AllInterfaceName interfaceName : nonSubInterfaces) {
|
||||
boolean isMatched = isInterfaceMatched(interfaceName);
|
||||
matchStatusMap.put(interfaceName, isMatched);
|
||||
|
||||
// 只设置服务器类型的businessFlag
|
||||
if ("1".equals(interfaceName.getResourceType())) {
|
||||
interfaceName.setBusinessFlag(isMatched);
|
||||
}
|
||||
}
|
||||
|
||||
// 使用自定义排序
|
||||
return nonSubInterfaces.stream()
|
||||
.sorted((a, b) -> {
|
||||
// 根据实际业务逻辑判断是否匹配
|
||||
// 这里用接口名不为null且包含特定字符作为示例
|
||||
boolean aMatched = a.getInterfaceName() != null && a.getInterfaceName().contains("eth");
|
||||
boolean bMatched = b.getInterfaceName() != null && b.getInterfaceName().contains("eth");
|
||||
boolean aMatched = matchStatusMap.get(a);
|
||||
boolean bMatched = matchStatusMap.get(b);
|
||||
|
||||
// 匹配的排在前面(返回-1),不匹配的排在后面(返回1)
|
||||
if (aMatched && !bMatched) {
|
||||
return -1;
|
||||
} else if (!aMatched && bMatched) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0; // 都匹配或都不匹配,保持原有顺序
|
||||
return 0;
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
+3
@@ -647,6 +647,9 @@ public class EpsInitialTrafficDataServiceImpl implements EpsInitialTrafficDataSe
|
||||
}
|
||||
deoloyDevice = clientIds.toString();
|
||||
}
|
||||
if(deoloyDevice == null){
|
||||
return null;
|
||||
}
|
||||
String clientIds = deoloyDevice.replace("\n",",");
|
||||
EpsInitialTrafficData queryParam = new EpsInitialTrafficData();
|
||||
queryParam.setStartTime(startTime);
|
||||
|
||||
+10
-26
@@ -16,6 +16,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -256,34 +257,17 @@ public class EpsServerRevenueConfigServiceImpl implements IEpsServerRevenueConfi
|
||||
}
|
||||
|
||||
if (!records.isEmpty()) {
|
||||
try {
|
||||
allInterfaceNameMapper.batchInsert(records);
|
||||
log.info("批量处理接口名称完成,记录数: {}", records.size());
|
||||
}catch (Exception e){
|
||||
// 处理死锁异常
|
||||
if (isDeadlockException(e)) {
|
||||
// 找到第一个非null的clientId
|
||||
String deadlockClientId = records.stream()
|
||||
.map(AllInterfaceName::getClientId)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.findFirst()
|
||||
.orElse("unknown");
|
||||
log.error("检测到死锁,涉及的clientId: {}", deadlockClientId);
|
||||
} else {
|
||||
// 非死锁异常,重新抛出
|
||||
log.error("批量处理接口名称失败:{}", e.getMessage());
|
||||
}
|
||||
}
|
||||
// 排序防止死锁
|
||||
records.sort(Comparator
|
||||
.comparing(AllInterfaceName::getInterfaceName)
|
||||
.thenComparing(AllInterfaceName::getClientId)
|
||||
.thenComparing(AllInterfaceName::getSwitchIp)
|
||||
.thenComparing(AllInterfaceName::getResourceType));
|
||||
|
||||
allInterfaceNameMapper.batchInsert(records);
|
||||
log.info("批量处理完成,记录数: {}", records.size());
|
||||
}
|
||||
}
|
||||
private boolean isDeadlockException(Exception e) {
|
||||
String message = e.getMessage();
|
||||
return message != null && (
|
||||
message.contains("deadlock") ||
|
||||
message.contains("Deadlock") ||
|
||||
message.contains("1213") // MySQL死锁错误码
|
||||
);
|
||||
}
|
||||
private boolean isValidData(EpsInitialTrafficData data) {
|
||||
return StringUtils.isNotBlank(data.getName())
|
||||
&& StringUtils.isNotBlank(data.getMac())
|
||||
|
||||
+9
-18
@@ -368,24 +368,15 @@ public class InitialSwitchInfoDetailsServiceImpl implements IInitialSwitchInfoDe
|
||||
}
|
||||
|
||||
if (!records.isEmpty()) {
|
||||
try {
|
||||
allInterfaceNameMapper.batchInsert(records);
|
||||
log.info("批量处理交换机接口名称完成,记录数: {}", records.size());
|
||||
}catch (Exception e){
|
||||
// 处理死锁异常
|
||||
if (isDeadlockException(e)) {
|
||||
// 找到第一个非null的clientId
|
||||
String deadlockClientId = records.stream()
|
||||
.map(AllInterfaceName::getClientId)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.findFirst()
|
||||
.orElse("unknown");
|
||||
log.error("检测到死锁,涉及的clientId: {}", deadlockClientId);
|
||||
} else {
|
||||
// 非死锁异常,重新抛出
|
||||
log.error("批量处理交换机接口名称失败:{}", e.getMessage());
|
||||
}
|
||||
}
|
||||
// 排序防止死锁
|
||||
records.sort(Comparator
|
||||
.comparing(AllInterfaceName::getInterfaceName)
|
||||
.thenComparing(AllInterfaceName::getClientId)
|
||||
.thenComparing(AllInterfaceName::getSwitchIp)
|
||||
.thenComparing(AllInterfaceName::getResourceType));
|
||||
|
||||
allInterfaceNameMapper.batchInsert(records);
|
||||
log.info("批量处理完成,记录数: {}", records.size());
|
||||
}
|
||||
}
|
||||
private boolean isDeadlockException(Exception e) {
|
||||
|
||||
+102
-23
@@ -25,6 +25,7 @@ import org.springframework.util.CollectionUtils;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.tongran.common.core.utils.PageUtils.startPage;
|
||||
@@ -128,7 +129,6 @@ public class RmResourceRegistrationServiceImpl implements IRmResourceRegistratio
|
||||
|
||||
// 3. 内存分页
|
||||
int total = filteredList.size();
|
||||
// 注意:这里要用copy,因为后续要修改数据
|
||||
List<RmResourceRegistration> pageList = applyPagination(filteredList, pageNum, pageSize);
|
||||
List<RmResourceRegistration> currentPageData = new ArrayList<>(pageList);
|
||||
|
||||
@@ -255,12 +255,51 @@ public class RmResourceRegistrationServiceImpl implements IRmResourceRegistratio
|
||||
RmResourceRegistration::getBandwidthResult,
|
||||
Comparator.nullsLast(Comparator.reverseOrder())
|
||||
);
|
||||
} else if (sortType == 4) { // 告警优先排序
|
||||
comparator = (a, b) -> {
|
||||
// 设置告警标志
|
||||
boolean aAlarm = isAlarm(a);
|
||||
boolean bAlarm = isAlarm(b);
|
||||
a.setAlarmFlag(aAlarm);
|
||||
b.setAlarmFlag(bAlarm);
|
||||
|
||||
// 告警优先级最高
|
||||
if (aAlarm && !bAlarm) return -1;
|
||||
if (!aAlarm && bAlarm) return 1;
|
||||
|
||||
if (aAlarm && bAlarm) {
|
||||
// 告警内按最大资源使用率倒序
|
||||
BigDecimal aMax = getMaxUtilization(a);
|
||||
BigDecimal bMax = getMaxUtilization(b);
|
||||
if (aMax == null && bMax == null) return 0;
|
||||
if (aMax == null) return 1;
|
||||
if (bMax == null) return -1;
|
||||
return bMax.compareTo(aMax);
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
if (comparator != null) {
|
||||
list.sort(comparator);
|
||||
}
|
||||
}
|
||||
private boolean isAlarm(RmResourceRegistration item) {
|
||||
return (item.getCpuUtil() != null && item.getCpuUtil().compareTo(BigDecimal.valueOf(80)) >= 0) ||
|
||||
(item.getMemUtil() != null && item.getMemUtil().compareTo(BigDecimal.valueOf(60)) >= 0);
|
||||
}
|
||||
|
||||
private BigDecimal getMaxUtilization(RmResourceRegistration item) {
|
||||
BigDecimal max = BigDecimal.ZERO;
|
||||
if (item.getCpuUtil() != null && item.getCpuUtil().compareTo(max) > 0) {
|
||||
max = item.getCpuUtil();
|
||||
}
|
||||
if (item.getMemUtil() != null && item.getMemUtil().compareTo(max) > 0) {
|
||||
max = item.getMemUtil();
|
||||
}
|
||||
return max.equals(BigDecimal.ZERO) ? null : max;
|
||||
}
|
||||
/**
|
||||
* 内存分页
|
||||
*/
|
||||
@@ -286,64 +325,92 @@ public class RmResourceRegistrationServiceImpl implements IRmResourceRegistratio
|
||||
}
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
// 设置每批大小
|
||||
int batchSize = 200;
|
||||
int totalBatches = (int) Math.ceil((double) pageList.size() / batchSize);
|
||||
|
||||
|
||||
for (int batchNum = 0; batchNum < totalBatches; batchNum++) {
|
||||
int fromIndex = batchNum * batchSize;
|
||||
int toIndex = Math.min(fromIndex + batchSize, pageList.size());
|
||||
List<RmResourceRegistration> batchList = pageList.subList(fromIndex, toIndex);
|
||||
|
||||
|
||||
// 收集当前批次需要查询的clientId
|
||||
String clientIdsStr = batchList.stream()
|
||||
String clientIdsStr = batchList.parallelStream()
|
||||
.map(RmResourceRegistration::getClientId)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.joining(","));
|
||||
|
||||
if (StringUtils.isBlank(clientIdsStr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
// 使用批量查询接口
|
||||
RmNetworkInterfaceRemote queryParam = new RmNetworkInterfaceRemote();
|
||||
queryParam.setClientIds(clientIdsStr);
|
||||
queryParam.setNewFlag(1);
|
||||
// 并行查询
|
||||
CompletableFuture<List<RmResourceRegistration>> cpuFuture = CompletableFuture
|
||||
.supplyAsync(() -> rmResourceRegistrationMapper.getCpuUtil(clientIdsStr));
|
||||
|
||||
R<List<RmNetworkInterfaceRemote>> result = remoteRocketMqService.getNetworkInterfaceList(queryParam, SecurityConstants.INNER);
|
||||
CompletableFuture<List<RmResourceRegistration>> memFuture = CompletableFuture
|
||||
.supplyAsync(() -> rmResourceRegistrationMapper.getMemUtil(clientIdsStr));
|
||||
|
||||
if (result == null || result.getData() == null || result.getData().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
CompletableFuture<List<RmNetworkInterfaceRemote>> networkFuture = CompletableFuture
|
||||
.supplyAsync(() -> {
|
||||
RmNetworkInterfaceRemote queryParam = new RmNetworkInterfaceRemote();
|
||||
queryParam.setClientIds(clientIdsStr);
|
||||
queryParam.setNewFlag(1);
|
||||
R<List<RmNetworkInterfaceRemote>> result = remoteRocketMqService.getNetworkInterfaceList(queryParam, SecurityConstants.INNER);
|
||||
return result != null ? result.getData() : Collections.emptyList();
|
||||
});
|
||||
|
||||
List<RmNetworkInterfaceRemote> networkList = result.getData();
|
||||
CompletableFuture.allOf(cpuFuture, memFuture, networkFuture).join();
|
||||
|
||||
List<RmResourceRegistration> cpuUtilList = cpuFuture.get();
|
||||
List<RmResourceRegistration> memUtilList = memFuture.get();
|
||||
List<RmNetworkInterfaceRemote> networkList = networkFuture.get();
|
||||
|
||||
// 构建查找Map
|
||||
Map<String, BigDecimal> cpuUtilMap = cpuUtilList.stream()
|
||||
.filter(item -> item.getClientId() != null && item.getCpuUtil() != null)
|
||||
.collect(Collectors.toMap(
|
||||
RmResourceRegistration::getClientId,
|
||||
RmResourceRegistration::getCpuUtil
|
||||
));
|
||||
|
||||
Map<String, BigDecimal> memUtilMap = memUtilList.stream()
|
||||
.filter(item -> item.getClientId() != null && item.getMemUtil() != null)
|
||||
.collect(Collectors.toMap(
|
||||
RmResourceRegistration::getClientId,
|
||||
RmResourceRegistration::getMemUtil
|
||||
));
|
||||
|
||||
// 按clientId分组
|
||||
Map<String, List<RmNetworkInterfaceRemote>> networkMap = networkList.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(item -> item.getClientId() != null)
|
||||
.collect(Collectors.groupingBy(RmNetworkInterfaceRemote::getClientId));
|
||||
|
||||
// 批量设置当前批次
|
||||
for (RmResourceRegistration registration : batchList) {
|
||||
// 并行处理
|
||||
batchList.parallelStream().forEach(registration -> {
|
||||
String clientId = registration.getClientId();
|
||||
if (clientId != null) {
|
||||
BigDecimal cpuUtil = cpuUtilMap.get(clientId);
|
||||
if (cpuUtil != null) {
|
||||
registration.setCpuUtil(cpuUtil);
|
||||
}
|
||||
|
||||
BigDecimal memUtil = memUtilMap.get(clientId);
|
||||
if (memUtil != null) {
|
||||
registration.setMemUtil(memUtil);
|
||||
}
|
||||
|
||||
List<RmNetworkInterfaceRemote> clientNetworks = networkMap.get(clientId);
|
||||
if (clientNetworks != null && !clientNetworks.isEmpty()) {
|
||||
setNetWorkMsgWithNetworkList(registration, clientNetworks);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("第{}批查询网络信息异常", batchNum + 1, e);
|
||||
log.error("第{}批查询资源信息异常", batchNum + 1, e);
|
||||
}
|
||||
|
||||
// 添加小延迟,避免对下游服务造成压力
|
||||
if (batchNum < totalBatches - 1) {
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
@@ -352,6 +419,8 @@ public class RmResourceRegistrationServiceImpl implements IRmResourceRegistratio
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.info("批量设置资源信息完成,耗时: {}ms", System.currentTimeMillis() - startTime);
|
||||
}
|
||||
/**
|
||||
* 使用批量查询的结果设置网络信息
|
||||
@@ -446,6 +515,16 @@ public class RmResourceRegistrationServiceImpl implements IRmResourceRegistratio
|
||||
*/
|
||||
public void setNetWorkMsg(RmResourceRegistration registration) {
|
||||
String clientId = registration.getClientId();
|
||||
// 根据clientId查询cpu利用率
|
||||
List<RmResourceRegistration> cpuUtilList = rmResourceRegistrationMapper.getCpuUtil(clientId);
|
||||
// 根据clientId查询mem利用率
|
||||
List<RmResourceRegistration> memUtilList = rmResourceRegistrationMapper.getMemUtil(clientId);
|
||||
if(cpuUtilList != null && !cpuUtilList.isEmpty()){
|
||||
registration.setCpuUtil(cpuUtilList.get(0).getCpuUtil());
|
||||
}
|
||||
if(memUtilList != null && !memUtilList.isEmpty()){
|
||||
registration.setMemUtil(memUtilList.get(0).getMemUtil());
|
||||
}
|
||||
// 根据clientId查询网卡信息
|
||||
RmNetworkInterfaceRemote queryParam = new RmNetworkInterfaceRemote();
|
||||
queryParam.setClientId(clientId);
|
||||
|
||||
+38
@@ -279,4 +279,42 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
select count(1) from rm_network_interface_child
|
||||
where client_id = #{clientId} and parent_interface = #{interfaceName}
|
||||
</select>
|
||||
<select id="getCpuUtil" resultType="RmResourceRegistration">
|
||||
SELECT
|
||||
d.client_id as clientId,
|
||||
d.uti as cpuUtil
|
||||
FROM initial_cpu_info d
|
||||
INNER JOIN (
|
||||
SELECT
|
||||
client_id,
|
||||
MAX(create_time) as latest_time
|
||||
FROM initial_cpu_info
|
||||
WHERE client_id in
|
||||
<foreach collection="clientIdsStr.split(',')" item="clientId" open="(" separator="," close=")">
|
||||
#{clientId}
|
||||
</foreach>
|
||||
GROUP BY client_id
|
||||
) latest ON d.client_id = latest.client_id
|
||||
AND d.create_time = latest.latest_time
|
||||
</select>
|
||||
<select id="getMemUtil" resultType="RmResourceRegistration">
|
||||
SELECT
|
||||
d.client_id as clientId,
|
||||
ROUND(d.collect_value, 1) as memUtil
|
||||
FROM initial_system_other_collect_data d
|
||||
INNER JOIN (
|
||||
SELECT
|
||||
client_id,
|
||||
MAX(create_time) as max_time
|
||||
FROM initial_system_other_collect_data
|
||||
WHERE collect_type='memoryUtilizationCollect'
|
||||
AND client_id in
|
||||
<foreach collection="clientIdsStr.split(',')" item="clientId" open="(" separator="," close=")">
|
||||
#{clientId}
|
||||
</foreach>
|
||||
GROUP BY client_id
|
||||
) latest ON d.client_id = latest.client_id
|
||||
AND d.create_time = latest.max_time
|
||||
AND d.collect_type='memoryUtilizationCollect'
|
||||
</select>
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user