1、修复虚拟网卡收益计算、流量图默认单位不正确问题。

2、联调告警阈值配置接口。
3、优化挂载点数据展示。
This commit is contained in:
gaoyutao
2026-01-26 18:52:52 +08:00
parent edddf77b6a
commit 5dd1b90acb
14 changed files with 227 additions and 129 deletions
@@ -5,6 +5,7 @@ import com.tongran.common.core.web.domain.BaseEntity;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
* 告警阈值配置对象 rm_alarm_threshold
@@ -35,4 +36,6 @@ public class RmAlarmThreshold extends BaseEntity
/** 阈值 */
@Excel(name = "阈值")
private BigDecimal thresholdValue;
/** 告警阈值列表 */
private List<RmAlarmThreshold> thresholdList;
}
@@ -948,7 +948,7 @@ public class MessageHandler {
cpus.forEach(iface -> {
iface.setClientId(message.getClientId());
iface.setCreateTime(createTime);
if(iface.getTemperature() == 0L){
if(iface.getTemperature() != null && iface.getTemperature() == 0L){
iface.setTemperature(null);
}
});
@@ -973,74 +973,77 @@ public class MessageHandler {
long timestamp = disks.get(0).getTimestamp();
long millis = timestamp * 1000;
Date createTime = new Date(millis / 1000 * 1000);
// 关键:每个clientId有自己独立的key
String diskCountKey = DISK_COUNT_PREFIX + clientId;
// 1. 给这个客户端的所有磁盘次数+1
Map<Object, Object> diskCountMap = redisTemplate.opsForHash().entries(diskCountKey);
for (Map.Entry<Object, Object> entry : diskCountMap.entrySet()) {
String diskName = (String) entry.getKey();
String countStr = (String) entry.getValue();
try {
int count = Integer.parseInt(countStr) + 1;
redisTemplate.opsForHash().put(diskCountKey, diskName, String.valueOf(count));
} catch (NumberFormatException e) {
redisTemplate.opsForHash().put(diskCountKey, diskName, "1");
}
}
// 2. 处理本次上报的磁盘
Set<String> reportedDisks = new HashSet<>();
disks.forEach(disk -> {
String diskName = disk.getName();
reportedDisks.add(diskName);
// 本次上报的磁盘,次数重置为0
redisTemplate.opsForHash().put(diskCountKey, diskName, "0");
disk.setClientId(clientId);
disk.setCreateTime(createTime);
});
// 3. 检查次数≥3的磁盘
diskCountMap = redisTemplate.opsForHash().entries(diskCountKey);
List<String> disksToRemove = new ArrayList<>();
for (Map.Entry<Object, Object> entry : diskCountMap.entrySet()) {
String diskName = (String) entry.getKey();
String countStr = (String) entry.getValue();
try {
int count = Integer.parseInt(countStr);
// 如果次数≥3且本次没上报
if (count >= 3 && !reportedDisks.contains(diskName)) {
AllDiskName allDiskName = new AllDiskName();
allDiskName.setStatus(0);
allDiskName.setClientId(clientId);
allDiskName.setName(diskName);
allDiskNameService.updateAllDiskName(allDiskName);
disksToRemove.add(diskName);
// 磁盘缺失,触发告警
RmAlarmLog rmAlarmLog = new RmAlarmLog();
rmAlarmLog.setClientId(clientId);
rmAlarmLog.setAlarmTime(DateUtils.getNowDate());
rmAlarmLog.setAlarmType(AlarmTypeEnum.磁盘缺失.getCode());
rmAlarmLog.setAlarmContent("服务器" + clientId + "磁盘缺失,磁盘名称:" + diskName);
rmAlarmLogService.insertRmAlarmLog(rmAlarmLog);
sendAlarmPushUtil.sendAlarmPush(rmAlarmLog);
}
} catch (NumberFormatException e) {
disksToRemove.add(diskName);
}
}
// 4. 删除已处理的磁盘记录
if (!disksToRemove.isEmpty()) {
redisTemplate.opsForHash().delete(diskCountKey, disksToRemove.toArray());
}
// // 关键:每个clientId有自己独立的key
// String diskCountKey = DISK_COUNT_PREFIX + clientId;
//
// // 1. 给这个客户端的所有磁盘次数+1
// Map<Object, Object> diskCountMap = redisTemplate.opsForHash().entries(diskCountKey);
// for (Map.Entry<Object, Object> entry : diskCountMap.entrySet()) {
// String diskName = (String) entry.getKey();
// String countStr = (String) entry.getValue();
//
// try {
// int count = Integer.parseInt(countStr) + 1;
// redisTemplate.opsForHash().put(diskCountKey, diskName, String.valueOf(count));
// } catch (NumberFormatException e) {
// redisTemplate.opsForHash().put(diskCountKey, diskName, "1");
// }
// }
//
// // 2. 处理本次上报的磁盘
// Set<String> reportedDisks = new HashSet<>();
// disks.forEach(disk -> {
// String diskName = disk.getName();
// reportedDisks.add(diskName);
//
// // 本次上报的磁盘,次数重置为0
// redisTemplate.opsForHash().put(diskCountKey, diskName, "0");
//
// disk.setClientId(clientId);
// disk.setCreateTime(createTime);
// });
//
// // 3. 检查次数≥3的磁盘
// diskCountMap = redisTemplate.opsForHash().entries(diskCountKey);
// List<String> disksToRemove = new ArrayList<>();
//
// for (Map.Entry<Object, Object> entry : diskCountMap.entrySet()) {
// String diskName = (String) entry.getKey();
// String countStr = (String) entry.getValue();
//
// try {
// int count = Integer.parseInt(countStr);
// // 如果次数≥3且本次没上报
// if (count >= 3 && !reportedDisks.contains(diskName)) {
// AllDiskName allDiskName = new AllDiskName();
// allDiskName.setStatus(0);
// allDiskName.setClientId(clientId);
// allDiskName.setName(diskName);
// allDiskNameService.updateAllDiskName(allDiskName);
// disksToRemove.add(diskName);
// // 磁盘缺失,触发告警
// RmAlarmLog rmAlarmLog = new RmAlarmLog();
// rmAlarmLog.setClientId(clientId);
// rmAlarmLog.setAlarmTime(DateUtils.getNowDate());
// rmAlarmLog.setAlarmType(AlarmTypeEnum.磁盘缺失.getCode());
// rmAlarmLog.setAlarmContent("服务器" + clientId + "磁盘缺失,磁盘名称:" + diskName);
// rmAlarmLogService.insertRmAlarmLog(rmAlarmLog);
// sendAlarmPushUtil.sendAlarmPush(rmAlarmLog);
//
// }
// } catch (NumberFormatException e) {
// disksToRemove.add(diskName);
// }
// }
//
// // 4. 删除已处理的磁盘记录
// if (!disksToRemove.isEmpty()) {
// redisTemplate.opsForHash().delete(diskCountKey, disksToRemove.toArray());
// }
// 5. 数据入库
initialDiskInfoService.batchInsertInitialDiskInfo(disks, createTime);
@@ -1,8 +1,9 @@
package com.tongran.rocketmq.mapper;
import java.util.List;
import com.tongran.rocketmq.domain.RmAlarmThreshold;
import java.util.List;
/**
* 告警阈值配置Mapper接口
*
@@ -58,4 +59,6 @@ public interface RmAlarmThresholdMapper
* @return 结果
*/
public int deleteRmAlarmThresholdByIds(Long[] ids);
void truncateAlarmThreshold();
}
@@ -258,7 +258,9 @@ public class InitialBandwidthTrafficServiceImpl implements IInitialBandwidthTraf
showRealation.put(name+"netOutTraffic", name+"出站流量" + " IPv4: "+ipv4);
boolean hasSubInterface = false;
boolean needAddIpv4Ipv6 = false; // 标记是否需要添加IPv4和IPv6数据
// 收集所有需要计算单位的流量数据
List<InitialBandwidthTraffic> allTrafficData = new ArrayList<>();
allTrafficData.addAll(mainList);
// 如果是Ethernet类型,查询子网卡
if(isEthernetInterface(name)){
RmNetworkInterfaceChild query = new RmNetworkInterfaceChild();
@@ -274,6 +276,7 @@ public class InitialBandwidthTrafficServiceImpl implements IInitialBandwidthTraf
List<InitialBandwidthTraffic> childTrafficList = getListByTableName(childTraffic);
if(childTrafficList != null && !childTrafficList.isEmpty()){
allTrafficData.addAll(childTrafficList);
interfaceDataMap.put(child.getInterfaceName(), childTrafficList);
showRealation.put(child.getInterfaceName()+"netInTraffic", child.getInterfaceName() + "入站流量" + " IPv4: "+child.getIpv4Address());
showRealation.put(child.getInterfaceName()+"netOutTraffic", child.getInterfaceName() + "出站流量" + " IPv4: "+child.getIpv4Address());
@@ -290,8 +293,10 @@ public class InitialBandwidthTrafficServiceImpl implements IInitialBandwidthTraf
}
try {
// 计算单位 - 基于所有相关数据
String unit;
// 计算单位
String unit = SpeedUtils.calculateUnitWithStringTraffic(mainList, "inSpeed", "outSpeed");
unit = SpeedUtils.calculateUnitWithStringTraffic(allTrafficData, "inSpeed", "outSpeed");
if(initialBandwidthTraffic.getUnit() != null){
unit = initialBandwidthTraffic.getUnit();
}
@@ -442,7 +447,9 @@ public class InitialBandwidthTrafficServiceImpl implements IInitialBandwidthTraf
showRealation.put(name + "netInTraffic", name + "IPv4入站流量" + " IPv4: "+ipv4);
showRealation.put(name + "netOutTraffic", name + "IPv4出站流量" + " IPv4: "+ipv4);
boolean hasSubInterface = false;
// 收集所有需要计算单位的流量数据
List<InitialBandwidthTraffic> allTrafficData = new ArrayList<>();
allTrafficData.addAll(mainList);
// 如果是Ethernet类型,查询子网卡
if (isEthernetInterface(name)) {
RmNetworkInterfaceChild query = new RmNetworkInterfaceChild();
@@ -458,6 +465,7 @@ public class InitialBandwidthTrafficServiceImpl implements IInitialBandwidthTraf
List<InitialBandwidthTraffic> childTrafficList = getListByTableName(childTraffic);
if (childTrafficList != null && !childTrafficList.isEmpty()) {
allTrafficData.addAll(childTrafficList);
interfaceDataMap.put(child.getInterfaceName(), childTrafficList);
showRealation.put(child.getInterfaceName() + "netInTraffic", child.getInterfaceName() + "IPv4入站流量" + " IPv4: "+child.getIpv4Address());
showRealation.put(child.getInterfaceName() + "netOutTraffic", child.getInterfaceName() + "IPv4出站流量" + " IPv4: "+child.getIpv4Address());
@@ -469,7 +477,7 @@ public class InitialBandwidthTrafficServiceImpl implements IInitialBandwidthTraf
try {
// 计算单位
String unit = SpeedUtils.calculateUnitWithStringTraffic(mainList, "ipv4InSpeed", "ipv4OutSpeed");
String unit = SpeedUtils.calculateUnitWithStringTraffic(allTrafficData, "ipv4InSpeed", "ipv4OutSpeed");
if (initialBandwidthTraffic.getUnit() != null) {
unit = initialBandwidthTraffic.getUnit();
}
@@ -527,7 +535,9 @@ public class InitialBandwidthTrafficServiceImpl implements IInitialBandwidthTraf
showRealation.put(name + "netInTraffic", name + "IPv6入站流量" + " IPv4: "+ipv4);
showRealation.put(name + "netOutTraffic", name + "IPv6出站流量" + " IPv4: "+ipv4);
boolean hasSubInterface = false;
// 收集所有需要计算单位的流量数据
List<InitialBandwidthTraffic> allTrafficData = new ArrayList<>();
allTrafficData.addAll(mainList);
// 如果是Ethernet类型,查询子网卡
if (isEthernetInterface(name)) {
RmNetworkInterfaceChild query = new RmNetworkInterfaceChild();
@@ -543,6 +553,7 @@ public class InitialBandwidthTrafficServiceImpl implements IInitialBandwidthTraf
List<InitialBandwidthTraffic> childTrafficList = getListByTableName(childTraffic);
if (childTrafficList != null && !childTrafficList.isEmpty()) {
allTrafficData.addAll(childTrafficList);
interfaceDataMap.put(child.getInterfaceName(), childTrafficList);
showRealation.put(child.getInterfaceName() + "netInTraffic", child.getInterfaceName() + "IPv6入站流量" + " IPv4: "+child.getIpv4Address());
showRealation.put(child.getInterfaceName() + "netOutTraffic", child.getInterfaceName() + "IPv6出站流量" + " IPv4: "+child.getIpv4Address());
@@ -553,7 +564,7 @@ public class InitialBandwidthTrafficServiceImpl implements IInitialBandwidthTraf
try {
// 计算单位
String unit = SpeedUtils.calculateUnitWithStringTraffic(mainList, "ipv6InSpeed", "ipv6OutSpeed");
String unit = SpeedUtils.calculateUnitWithStringTraffic(allTrafficData, "ipv6InSpeed", "ipv6OutSpeed");
if (initialBandwidthTraffic.getUnit() != null) {
unit = initialBandwidthTraffic.getUnit();
}
@@ -684,7 +695,9 @@ public class InitialBandwidthTrafficServiceImpl implements IInitialBandwidthTraf
showRealation.put(name + "netInTraffic", name + "入站流量" + " IPv4: "+ipv4);
showRealation.put(name + "netOutTraffic", name + "出站流量" + " IPv4: "+ipv4);
boolean hasSubInterface = false;
// 收集所有需要计算单位的流量数据
List<InitialBandwidthTraffic> allTrafficData = new ArrayList<>();
allTrafficData.addAll(mainList);
// 如果是Ethernet类型,查询子网卡
if (isEthernetInterface(name)) {
RmNetworkInterfaceChild query = new RmNetworkInterfaceChild();
@@ -700,6 +713,7 @@ public class InitialBandwidthTrafficServiceImpl implements IInitialBandwidthTraf
List<InitialBandwidthTraffic> childTrafficList = getListByTableName(childTraffic);
if (childTrafficList != null && !childTrafficList.isEmpty()) {
allTrafficData.addAll(childTrafficList);
interfaceDataMap.put(child.getInterfaceName(), childTrafficList);
showRealation.put(child.getInterfaceName() + "netInTraffic", child.getInterfaceName() + "入站流量" + " IPv4: "+child.getIpv4Address());
showRealation.put(child.getInterfaceName() + "netOutTraffic", child.getInterfaceName() + "出站流量" + " IPv4: "+child.getIpv4Address());
@@ -710,7 +724,7 @@ public class InitialBandwidthTrafficServiceImpl implements IInitialBandwidthTraf
try {
// 计算单位
String unit = SpeedUtils.calculateUnitWithStringTraffic(mainList, "inSpeed", "outSpeed");
String unit = SpeedUtils.calculateUnitWithStringTraffic(allTrafficData, "inSpeed", "outSpeed");
if (initialBandwidthTraffic.getUnit() != null) {
unit = initialBandwidthTraffic.getUnit();
}
@@ -3,10 +3,6 @@ package com.tongran.rocketmq.service.impl;
import com.tongran.common.core.utils.DateUtils;
import com.tongran.common.core.utils.EchartsDataUtils;
import com.tongran.rocketmq.domain.InitialCpuInfo;
import com.tongran.rocketmq.domain.RmAlarmLog;
import com.tongran.rocketmq.domain.RmAlarmThreshold;
import com.tongran.rocketmq.enums.AlarmTypeEnum;
import com.tongran.rocketmq.enums.ConditionItemEnum;
import com.tongran.rocketmq.mapper.InitialCpuInfoMapper;
import com.tongran.rocketmq.mapper.RmAlarmLogMapper;
import com.tongran.rocketmq.mapper.RmAlarmThresholdMapper;
@@ -18,7 +14,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -131,47 +126,47 @@ public class InitialCpuInfoServiceImpl implements IInitialCpuInfoService
public int batchInsertInitialCpuInfo(List<InitialCpuInfo> list) {
try {
// 查询告警阈值
RmAlarmThreshold thresholdQuery = new RmAlarmThreshold();
thresholdQuery.setAlarmType(AlarmTypeEnum.CPU使用率高.getCode());
thresholdQuery.setConditionItem(ConditionItemEnum.服务器CPU使用率.getCode());
List<RmAlarmThreshold> rmAlarmThresholdList = rmAlarmThresholdMapper.selectRmAlarmThresholdList(thresholdQuery);
if(rmAlarmThresholdList != null && !rmAlarmThresholdList.isEmpty()){
String operator = rmAlarmThresholdList.get(0).getCompareOperator();
BigDecimal threshold = rmAlarmThresholdList.get(0).getThresholdValue();
for (InitialCpuInfo initialCpuInfo : list) {
BigDecimal cpuUti = new BigDecimal(initialCpuInfo.getUti());
if(operator != null){
// 根据运算符1大于,2小于,3等于 判断是否进行告警
boolean shouldAlarm = false;
// 根据运算符判断是否进行告警
switch (operator) {
case "1": // 大于
shouldAlarm = cpuUti.compareTo(threshold) > 0;
break;
case "2": // 小于
shouldAlarm = cpuUti.compareTo(threshold) < 0;
break;
case "3": // 等于
shouldAlarm = cpuUti.compareTo(threshold) == 0;
break;
default:
log.warn("未知的运算符: {}", operator);
continue; // 跳过未知运算符的处理
}
if(shouldAlarm){
RmAlarmLog rmAlarmLog = new RmAlarmLog();
rmAlarmLog.setAlarmType(AlarmTypeEnum.CPU使用率高.getCode());
rmAlarmLog.setClientId(initialCpuInfo.getClientId());
rmAlarmLog.setAlarmTime(DateUtils.getNowDate());
rmAlarmLog.setAlarmContent("服务器" + initialCpuInfo.getClientId() + "的CPU使用率高");
rmAlarmLogMapper.insertRmAlarmLog(rmAlarmLog);
// 推送消息
sendAlarmPushUtil.sendAlarmPush(rmAlarmLog);
}
}
}
}
// RmAlarmThreshold thresholdQuery = new RmAlarmThreshold();
// thresholdQuery.setAlarmType(AlarmTypeEnum.CPU使用率高.getCode());
// thresholdQuery.setConditionItem(ConditionItemEnum.服务器CPU使用率.getCode());
// List<RmAlarmThreshold> rmAlarmThresholdList = rmAlarmThresholdMapper.selectRmAlarmThresholdList(thresholdQuery);
// if(rmAlarmThresholdList != null && !rmAlarmThresholdList.isEmpty()){
// String operator = rmAlarmThresholdList.get(0).getCompareOperator();
// BigDecimal threshold = rmAlarmThresholdList.get(0).getThresholdValue();
// for (InitialCpuInfo initialCpuInfo : list) {
// BigDecimal cpuUti = new BigDecimal(initialCpuInfo.getUti());
// if(operator != null){
// // 根据运算符1大于,2小于,3等于 判断是否进行告警
// boolean shouldAlarm = false;
//
// // 根据运算符判断是否进行告警
// switch (operator) {
// case "1": // 大于
// shouldAlarm = cpuUti.compareTo(threshold) > 0;
// break;
// case "2": // 小于
// shouldAlarm = cpuUti.compareTo(threshold) < 0;
// break;
// case "3": // 等于
// shouldAlarm = cpuUti.compareTo(threshold) == 0;
// break;
// default:
// log.warn("未知的运算符: {}", operator);
// continue; // 跳过未知运算符的处理
// }
// if(shouldAlarm){
// RmAlarmLog rmAlarmLog = new RmAlarmLog();
// rmAlarmLog.setAlarmType(AlarmTypeEnum.CPU使用率高.getCode());
// rmAlarmLog.setClientId(initialCpuInfo.getClientId());
// rmAlarmLog.setAlarmTime(DateUtils.getNowDate());
// rmAlarmLog.setAlarmContent("服务器" + initialCpuInfo.getClientId() + "的CPU使用率高");
// rmAlarmLogMapper.insertRmAlarmLog(rmAlarmLog);
// // 推送消息
// sendAlarmPushUtil.sendAlarmPush(rmAlarmLog);
// }
// }
// }
// }
return initialCpuInfoMapper.batchInsertInitialCpuInfo(list);
}catch (Exception e){
log.error("批量插入CPU信息失败,失败数量:{}", list.size(), e);
@@ -136,7 +136,7 @@ public class InitialMountPointInfoServiceImpl implements IInitialMountPointInfoS
Map<String, Function<InitialMountPointInfo, ?>> extractors = new LinkedHashMap<>();
extractors.put("vfsFreeData", info -> UnitChangeUtil.bytesToGb(info.getVfsFree()));
extractors.put("vfsTotalData", info -> UnitChangeUtil.bytesToGb(info.getVfsTotal()));
return EchartsDataUtils.buildEchartsData(list,InitialMountPointInfo::getCreateTime, extractors);
return EchartsDataUtils.buildEchartsDataAutoPadding(list,InitialMountPointInfo::getCreateTime, extractors, initialMountPointInfo.getStartTime(), initialMountPointInfo.getEndTime());
}
/**
@@ -149,7 +149,7 @@ public class InitialMountPointInfoServiceImpl implements IInitialMountPointInfoS
List<InitialMountPointInfo> list = initialMountPointInfoMapper.selectInitialMountPointInfoList(initialMountPointInfo);
Map<String, Function<InitialMountPointInfo, ?>> extractors = new LinkedHashMap<>();
extractors.put("vfsUtilData", InitialMountPointInfo::getVfsUtil);
return EchartsDataUtils.buildEchartsData(list,InitialMountPointInfo::getCreateTime, extractors);
return EchartsDataUtils.buildEchartsDataAutoPadding(list,InitialMountPointInfo::getCreateTime, extractors, initialMountPointInfo.getStartTime(), initialMountPointInfo.getEndTime());
}
/**
@@ -7,6 +7,7 @@ import com.tongran.rocketmq.service.IRmAlarmThresholdService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@@ -53,11 +54,19 @@ public class RmAlarmThresholdServiceImpl implements IRmAlarmThresholdService
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int insertRmAlarmThreshold(RmAlarmThreshold rmAlarmThreshold)
{
// 新增前先删除
rmAlarmThresholdMapper.truncateAlarmThreshold();
rmAlarmThreshold.setCreateTime(DateUtils.getNowDate());
try {
int rows = rmAlarmThresholdMapper.insertRmAlarmThreshold(rmAlarmThreshold);
List<RmAlarmThreshold> list = rmAlarmThreshold.getThresholdList();
if(list != null){
for (RmAlarmThreshold threshold : list) {
rmAlarmThresholdMapper.insertRmAlarmThreshold(threshold);
}
}
}catch (DuplicateKeyException e){
return -1;
}