优化agent本地存储流量数据处理

This commit is contained in:
gaoyutao
2026-01-29 12:00:05 +08:00
parent 29a30b1f52
commit 1dab9b1cf4
15 changed files with 465 additions and 89 deletions
@@ -133,4 +133,11 @@ public interface RemoteRevenueConfigService
@GetMapping("/businessScript/inner/{id}")
public R<EpsBusinessScriptRemote> getBusinessScriptMsgByScriptId(@PathVariable("id") Long id, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 保存流量数据
* @param queryParam 流量数据列表
* @return 操作结果
*/
@PostMapping("/revenueConfig/autoSaveServiceRecoverTrafficData")
public R<String> autoSaveServiceRecoverTrafficData(@RequestBody EpsInitialTrafficDataRemote queryParam, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
}
@@ -96,6 +96,11 @@ public class RemoteRevenueConfigFallbackFactory implements FallbackFactory<Remot
public R<EpsBusinessScriptRemote> getBusinessScriptMsgByScriptId(Long id, String source) {
return R.fail("获取错误关键词失败:" + throwable.getMessage());
}
@Override
public R<String> autoSaveServiceRecoverTrafficData(EpsInitialTrafficDataRemote queryParam, String source) {
return R.fail("保存重试流量数据失败:" + throwable.getMessage());
}
};
}
}
@@ -118,7 +118,6 @@ public class EchartsDataUtils {
// 准备X轴和Y轴数据
List<String> xAxisData = new ArrayList<>();
Map<String, Object> yData = new LinkedHashMap<>();
// 初始化Y轴数据结构
dataExtractors.keySet().forEach(name ->
yData.put(name, new ArrayList<>()));
@@ -152,7 +151,7 @@ public class EchartsDataUtils {
seriesData.add(getDefaultValue(name, fixedPercentile95Value, xAxisData.size()-1, hasRealData));
} else {
// 在数据时间范围外
seriesData.add(getEmptyDataDefaultValue(name, xAxisData.size()-1));
seriesData.add(getEmptyDataDefaultValue(name, xAxisData.size()-1, hasRealData));
}
}
}
@@ -338,13 +337,23 @@ public class EchartsDataUtils {
/**
* 获取空数据默认值(用于数据时间范围外的点)
*/
private static Object getEmptyDataDefaultValue(String metricName, int timeIndex) {
private static Object getEmptyDataDefaultValue(String metricName, int timeIndex, boolean hasRealData) {
// deployDevice特殊处理:始终补空字符串
if ("deployDevice".equals(metricName)) {
return "";
}
return null;
// 智能补全策略
if (hasRealData) {
// 数据集中有真实数据:所有缺失点都补null
return null;
} else {
// 数据集中没有真实数据:第一个点补0,其他点补null
if (timeIndex == 0) {
return 0;
} else {
return null;
}
}
}
/**
@@ -79,5 +79,14 @@ public class EpsServerRevenueConfigController extends BaseController
{
return epsServerRevenueConfigService.autoSaveServiceTrafficData(epsServerRevenueConfig);
}
/**
* 流量相关数据入库
*/
@InnerAuth
@PostMapping("/autoSaveServiceRecoverTrafficData")
public R<String> autoSaveServiceRecoverTrafficData(@RequestBody EpsServerRevenueConfig epsServerRevenueConfig)
{
return epsServerRevenueConfigService.autoSaveServiceRecoverTrafficData(epsServerRevenueConfig);
}
}
@@ -74,4 +74,6 @@ public interface EpsInitialTrafficDataMapper {
void createSwitchOpMdTable(String tableName);
void createDiskInfo(String tableName);
void batchInsertRecoverDetailTraffic(EpsInitialTrafficData batchData);
}
@@ -36,6 +36,7 @@ public interface EpsInitialTrafficDataService {
* @param dataList 流量数据列表
*/
void saveBatch(EpsInitialTrafficData dataList);
void saveBatchRecoverTraffic(EpsInitialTrafficData dataList);
/**
* 查询流量数据
@@ -67,6 +67,7 @@ public interface IEpsServerRevenueConfigService
* @param epsServerRevenueConfig
*/
R<String> autoSaveServiceTrafficData(EpsServerRevenueConfig epsServerRevenueConfig);
R<String> autoSaveServiceRecoverTrafficData(EpsServerRevenueConfig epsServerRevenueConfig);
/**
* 当前在线服务器的流量相关的业务数
* @return
@@ -245,6 +245,73 @@ public class EpsInitialTrafficDataServiceImpl implements EpsInitialTrafficDataSe
}
});
}
/**
* 批量保存数据到对应分表
* @param epsInitialTrafficData 流量数据表
*/
@Override
@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
public void saveBatchRecoverTraffic(EpsInitialTrafficData epsInitialTrafficData) {
if (epsInitialTrafficData == null || epsInitialTrafficData.getDataList().isEmpty()) {
return;
}
// 内存去重(基于唯一键)
List<EpsInitialTrafficData> distinctList = epsInitialTrafficData.getDataList().stream()
.filter(Objects::nonNull)
.map(data -> {
EpsInitialTrafficData processed = new EpsInitialTrafficData();
BeanUtils.copyProperties(data, processed);
if (data.getCreateTime() == null) {
processed.setCreateTime(DateUtils.getNowDate());
}
return processed;
})
.collect(Collectors.collectingAndThen(
// 使用TreeSet按唯一键去重
Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(
d -> String.join("|",
d.getClientId(),
d.getMac(),
d.getName(),
d.getCreateTime().toString()
)
))),
ArrayList::new
));
// 按表名分组
Map<String, List<EpsInitialTrafficData>> groupedData = distinctList.stream()
.map(data -> {
data.setTableName(TableRouterUtil.getTableName(
data.getCreateTime().toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDateTime()
));
return data;
})
.collect(Collectors.groupingBy(
EpsInitialTrafficData::getTableName,
LinkedHashMap::new,
Collectors.toList()
));
// 分表插入(带冲突降级)
groupedData.forEach((tableName, list) -> {
try {
EpsInitialTrafficData batchData = new EpsInitialTrafficData();
BeanUtils.copyProperties(epsInitialTrafficData, batchData);
batchData.setTableName(tableName);
batchData.setDataList(list);
// 优先尝试批量插入
epsInitialTrafficDataMapper.batchInsertRecoverDetailTraffic(batchData);
} catch (Exception e) {
log.error("表 {} 插入失败", tableName, e);
throw new RuntimeException("数据入库失败", e);
}
});
}
/**
* 查询流量数据
*/
@@ -259,6 +259,102 @@ public class EpsServerRevenueConfigServiceImpl implements IEpsServerRevenueConfi
return R.fail("数据保存失败:" + e.getMessage() + ",已成功保存" + successCount + "");
}
}
/**
* 保存流量信息
* @param epsServerRevenueConfig
*/
@Override
public R<String> autoSaveServiceRecoverTrafficData(EpsServerRevenueConfig epsServerRevenueConfig) {
// 查询初始流量数据
EpsInitialTrafficData epsInitialTrafficData = new EpsInitialTrafficData();
epsInitialTrafficData.setStartTime(epsServerRevenueConfig.getStartTime());
epsInitialTrafficData.setEndTime(epsServerRevenueConfig.getEndTime());
List<EpsInitialTrafficData> dataList = epsInitialTrafficDataService.getAllTraficMsg(epsInitialTrafficData);
if (dataList == null || dataList.isEmpty()) {
return R.ok("没有需要处理的数据");
}
List<EpsInitialTrafficData> batchList = new ArrayList<>();
int batchSize = 1000; // 每批处理数量
int totalCount = 0;
int successCount = 0;
int batchNumber = 0;
try {
for (EpsInitialTrafficData initialTrafficData : dataList) {
// 根据clientId查询业务名称
RmResourceRegistration rmResourceRegistration = new RmResourceRegistration();
rmResourceRegistration.setClientId(initialTrafficData.getClientId());
List<RmResourceRegistration> registerLst = rmResourceRegistrationMapper.selectRmResourceRegistrationList(rmResourceRegistration);
if(registerLst != null && !registerLst.isEmpty()){
RmResourceRegistration registerMsg = registerLst.get(0);
// 赋值
if(registerMsg != null){
String businessName = registerMsg.getBusinessName();
if(businessName != null){
initialTrafficData.setBusinessName(businessName);
// 根据业务名称查询业务代码
EpsBusiness epsBusiness = epsBusinessMapper.selectEpsBusinessByName(businessName);
if(epsBusiness != null){
initialTrafficData.setBusinessId(epsBusiness.getId());
}
}
initialTrafficData.setServiceSn(registerMsg.getHardwareSn());
initialTrafficData.setRevenueMethod("1");
}
}
// id自增
initialTrafficData.setId(null);
batchList.add(initialTrafficData);
// 达到批次大小时保存
if (batchList.size() >= batchSize) {
batchNumber++;
totalCount += batchList.size();
epsInitialTrafficData.setDataList(batchList);
epsInitialTrafficDataService.saveBatchRecoverTraffic(epsInitialTrafficData);
log.info("第{}批流量数据批量入库成功,数据量:{}", batchNumber, batchList.size());
// 处理接口名称
processInterfaceNames(batchList);
successCount += batchList.size();
// 清空当前批次,准备下一批
batchList = new ArrayList<>();
}
}
// 处理最后一批不足1000条的数据
if (!batchList.isEmpty()) {
batchNumber++;
totalCount += batchList.size();
epsInitialTrafficData.setDataList(batchList);
epsInitialTrafficDataService.saveBatchRecoverTraffic(epsInitialTrafficData);
log.info("第{}批流量数据批量入库成功,数据量:{}", batchNumber, batchList.size());
// 处理最后一批的接口名称
processInterfaceNames(batchList);
successCount += batchList.size();
}
log.info("流量数据批量入库完成,总批次数:{},总数据量:{},成功数量:{}",
batchNumber, totalCount, successCount);
if (successCount == totalCount) {
return R.ok("数据保存成功,共处理" + successCount + "条数据");
} else {
return R.fail("数据保存部分成功,应处理" + totalCount + "条,实际成功" + successCount + "");
}
} catch (Exception e) {
log.error("流量数据入库失败,已处理批次:{},成功数量:{},当前批次数量:{},错误原因:{}",
batchNumber, successCount, batchList.size(), e.getMessage(), e);
return R.fail("数据保存失败:" + e.getMessage() + ",已成功保存" + successCount + "");
}
}
/**
* 当前在线服务器的流量相关的业务数
* @return
@@ -377,6 +377,91 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
)
</foreach>
</insert>
<insert id="batchInsertRecoverDetailTraffic">
INSERT INTO ${tableName} (
id,
`name`,
`mac`,
`status`,
`type`,
ipV4,
`in_dropped`,
`out_dropped`,
`in_speed`,
`out_speed`,
`total_in_speed`,
`total_out_speed`,
`speed`,
`duplex`,
business_id,
business_name,
service_sn,
node_name,
revenue_method,
package_bandwidth,
create_time,
update_time,
create_by,
update_by,
client_id,
ipv4_in_speed,
ipv4_out_speed,
ipv6_in_speed,
ipv6_out_speed,
total_ipv4_in_speed,
total_ipv4_out_speed,
total_ipv6_in_speed,
total_ipv6_out_speed,
ipV6,
ping_dropped
) VALUES
<foreach collection="dataList" item="data" separator=",">
(
#{data.id,jdbcType=BIGINT},
#{data.name,jdbcType=VARCHAR},
#{data.mac,jdbcType=VARCHAR},
#{data.status,jdbcType=VARCHAR},
#{data.type,jdbcType=VARCHAR},
#{data.ipV4,jdbcType=VARCHAR},
#{data.inDropped,jdbcType=DECIMAL},
#{data.outDropped,jdbcType=DECIMAL},
#{data.inSpeed,jdbcType=VARCHAR},
#{data.outSpeed,jdbcType=VARCHAR},
#{data.totalInSpeed,jdbcType=VARCHAR},
#{data.totalOutSpeed,jdbcType=VARCHAR},
#{data.speed,jdbcType=VARCHAR},
#{data.duplex,jdbcType=VARCHAR},
#{data.businessId,jdbcType=VARCHAR},
#{data.businessName,jdbcType=VARCHAR},
#{data.serviceSn,jdbcType=VARCHAR},
#{data.nodeName,jdbcType=VARCHAR},
#{data.revenueMethod,jdbcType=VARCHAR},
#{data.packageBandwidth,jdbcType=DECIMAL},
#{data.createTime,jdbcType=TIMESTAMP},
#{data.updateTime,jdbcType=TIMESTAMP},
#{data.createBy,jdbcType=VARCHAR},
#{data.updateBy,jdbcType=VARCHAR},
#{data.clientId,jdbcType=VARCHAR},
#{data.ipv4InSpeed,jdbcType=VARCHAR},
#{data.ipv4OutSpeed,jdbcType=VARCHAR},
#{data.ipv6InSpeed,jdbcType=VARCHAR},
#{data.ipv6OutSpeed,jdbcType=VARCHAR},
#{data.totalIpv4InSpeed,jdbcType=VARCHAR},
#{data.totalIpv4OutSpeed,jdbcType=VARCHAR},
#{data.totalIpv6InSpeed,jdbcType=VARCHAR},
#{data.totalIpv6OutSpeed,jdbcType=VARCHAR},
#{data.ipV6,jdbcType=VARCHAR},
#{data.pingDropped,jdbcType=DECIMAL}
)
</foreach>
ON DUPLICATE KEY UPDATE
`in_speed` = IF(VALUES(`in_speed`) IS NOT NULL, VALUES(`in_speed`), `in_speed`),
`out_speed` = IF(VALUES(`out_speed`) IS NOT NULL, VALUES(`out_speed`), `out_speed`),
`ipv4_in_speed` = IF(VALUES(`ipv4_in_speed`) IS NOT NULL, VALUES(`ipv4_in_speed`), `ipv4_in_speed`),
`ipv4_out_speed` = IF(VALUES(`ipv4_out_speed`) IS NOT NULL, VALUES(`ipv4_out_speed`), `ipv4_out_speed`),
`ipv6_in_speed` = IF(VALUES(`ipv6_in_speed`) IS NOT NULL, VALUES(`ipv6_in_speed`), `ipv6_in_speed`),
`ipv6_out_speed` = IF(VALUES(`ipv6_out_speed`) IS NOT NULL, VALUES(`ipv6_out_speed`), `ipv6_out_speed`)
</insert>
<!-- 条件查询 -->
<select id="selectByCondition" resultType="EpsInitialTrafficData">
@@ -721,23 +721,31 @@ public class MessageHandler {
long millis = timestamp * 1000;
Date createTime = new Date(millis / 1000 * 1000); // 去除毫秒
String timeStr = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",createTime);
// 判断数据库中是否已存在数据
InitialBandwidthTraffic countQuery = new InitialBandwidthTraffic();
countQuery.setClientId(clientId);
countQuery.setCreateTime(createTime);
countQuery.setStartTime(timeStr);
int exitsCount = initialBandwidthTrafficService.countByClientIdAndTime(countQuery);
// 即使数据已存在,也需要处理临时表逻辑,确保后续计算正确
if(exitsCount > 0){
return;
// 不直接返回,继续执行临时表处理逻辑
// 但跳过最终的数据入库操作
System.out.println("数据已存在,跳过入库操作,但继续处理临时表逻辑");
}
// 创建比timestamp少5分钟的时间
long fiveMinutesEarlier = millis - (5 * 60 * 1000); // 减去5分钟的毫秒数
Date fiveMinutesEarlierDate = new Date(fiveMinutesEarlier / 1000 * 1000); // 同样去除毫秒
// 查询临时表信息,计算实际流量值
InitialBandwidthTrafficTemp temp = new InitialBandwidthTrafficTemp();
temp.setCreateTime(fiveMinutesEarlierDate);
temp.setClientId(clientId);
List<InitialBandwidthTrafficTemp> tempList = initialBandwidthTrafficTempService.selectInitialBandwidthTrafficRecoverTempList(temp);
if(!tempList.isEmpty()){
// 1. 构建快速查找的Map,使用MAC地址+网卡名称作为唯一键
Map<String, InitialBandwidthTrafficTemp> tempMap = tempList.stream()
@@ -834,7 +842,7 @@ public class MessageHandler {
delQuery.setClientId(clientId);
delQuery.setCreateTime(fiveMinutesEarlierDate);
initialBandwidthTrafficTempService.deleteTempMsgByClientIdAndTime(delQuery);
}else{
} else {
interfaces.forEach(iface -> {
iface.setClientId(clientId);
iface.setCreateTime(createTime);
@@ -855,19 +863,26 @@ public class MessageHandler {
iface.setIpv6OutSpeed(null);
});
}
InitialBandwidthTraffic data = new InitialBandwidthTraffic();
// 批量入库集合
data.setList(interfaces);
// 临时表 用来计算流量速率
initialBandwidthTrafficTempService.batchInsertServerRecoverTemp(interfaces);
// 初始流量数据入库
initialBandwidthTrafficService.batchInsert(data);
EpsInitialTrafficDataRemote epsInitialTrafficDataRemote = new EpsInitialTrafficDataRemote();
epsInitialTrafficDataRemote.setStartTime(timeStr);
epsInitialTrafficDataRemote.setEndTime(timeStr);
// 复制到业务初始库
remoteRevenueConfigService.autoSaveServiceTrafficData(epsInitialTrafficDataRemote, SecurityConstants.INNER);
}else{
// 只有在数据不存在时才执行入库操作
if (exitsCount == 0) {
InitialBandwidthTraffic data = new InitialBandwidthTraffic();
// 批量入库集合
data.setList(interfaces);
// 临时表 用来计算流量速率
initialBandwidthTrafficTempService.batchInsertServerRecoverTemp(interfaces);
// 初始流量数据入库
initialBandwidthTrafficService.batchInsertRecoverTraffic(data);
EpsInitialTrafficDataRemote epsInitialTrafficDataRemote = new EpsInitialTrafficDataRemote();
epsInitialTrafficDataRemote.setStartTime(timeStr);
epsInitialTrafficDataRemote.setEndTime(timeStr);
// 复制到业务初始库
remoteRevenueConfigService.autoSaveServiceRecoverTrafficData(epsInitialTrafficDataRemote, SecurityConstants.INNER);
} else {
// 数据已存在时,只更新临时表,确保后续计算正确
initialBandwidthTrafficTempService.batchInsertServerRecoverTemp(interfaces);
}
} else {
throw new RuntimeException("NET流量data数据为空");
}
}
@@ -971,77 +986,77 @@ public class MessageHandler {
long timestamp = disks.get(0).getTimestamp();
long millis = timestamp * 1000;
Date createTime = new Date(millis / 1000 * 1000);
disks.forEach(disk -> {
disk.setClientId(clientId);
disk.setCreateTime(createTime);
});
// 关键:每个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, AlarmTypeEnum.磁盘缺失.getMsg());
//
// }
// } 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, AlarmTypeEnum.磁盘缺失.getMsg());
}
} catch (NumberFormatException e) {
disksToRemove.add(diskName);
}
}
// 4. 删除已处理的磁盘记录
if (!disksToRemove.isEmpty()) {
redisTemplate.opsForHash().delete(diskCountKey, disksToRemove.toArray());
}
// 5. 数据入库
initialDiskInfoService.batchInsertInitialDiskInfo(disks, createTime);
@@ -1961,7 +1976,7 @@ public class MessageHandler {
* 查询IP地址归属地信息,返回运营商和省份
*/
private Map<String, String> queryIpLocation(String ip) {
String apiUrl = "http://172.16.15.51:10000/?ip=" + ip;
String apiUrl = "http://172.16.15.103:10000/?ip=" + ip;
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(apiUrl);
@@ -71,6 +71,7 @@ public interface InitialBandwidthTrafficMapper
* @param data 流量数据实体类
*/
int batchInsert(InitialBandwidthTraffic data);
int batchInsertRecoverTraffic(InitialBandwidthTraffic data);
/**
* 网络接口基础信息
* @param initialBandwidthTraffic
@@ -71,6 +71,7 @@ public interface IInitialBandwidthTrafficService
* @param data 流量数据
*/
void batchInsert(InitialBandwidthTraffic data);
void batchInsertRecoverTraffic(InitialBandwidthTraffic data);
/**
* 网络接口基础信息
* @param initialBandwidthTraffic
@@ -183,6 +183,56 @@ public class InitialBandwidthTrafficServiceImpl implements IInitialBandwidthTraf
}
});
}
/**
* 保存多条数据到对应分表
* @param initialBandwidthTraffic 流量数据
*/
@Override
@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
public void batchInsertRecoverTraffic(InitialBandwidthTraffic initialBandwidthTraffic) {
if (initialBandwidthTraffic == null) {
return;
}
List<InitialBandwidthTraffic> dataList = initialBandwidthTraffic.getList();
if (dataList.isEmpty()){
return;
}
// 按表名分组批量插入
Map<String, List<InitialBandwidthTraffic>> groupedData = dataList.stream()
.map(data -> {
try {
InitialBandwidthTraffic processed = new InitialBandwidthTraffic();
BeanUtils.copyProperties(data,processed);
if (data.getCreateTime() == null) {
data.setCreateTime(DateUtils.getNowDate());
}
LocalDateTime createTime = data.getCreateTime().toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDateTime();
processed.setTableName(TableRouterUtil.getTableName(createTime));
return processed;
} catch (Exception e){
log.error("数据处理失败",e.getMessage());
return null;
}
}).collect(Collectors.groupingBy(
InitialBandwidthTraffic::getTableName,
LinkedHashMap::new, // 保持插入顺序
Collectors.toList()));
groupedData.forEach((tableName, list) -> {
try {
InitialBandwidthTraffic data = new InitialBandwidthTraffic();
BeanUtils.copyProperties(initialBandwidthTraffic,data);
data.setTableName(tableName);
data.setList(list);
initialBandwidthTrafficMapper.batchInsertRecoverTraffic(data);
} catch (Exception e) {
log.error("表{}插入失败", tableName, e);
throw new RuntimeException("批量插入失败", e);
}
});
}
/**
* 网络接口基础信息
* @param initialBandwidthTraffic
@@ -143,7 +143,33 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
)
</foreach>
</insert>
<insert id="batchInsertRecoverTraffic" parameterType="InitialBandwidthTraffic">
INSERT INTO ${tableName} (
`name`, `mac`, `status`, `type`, ipV4, `in_dropped`, `out_dropped`,
`in_speed`, `out_speed`, `total_in_speed`, `total_out_speed`, duplex, speed,
create_by, update_by, client_id, create_time,
ipv4_in_speed, ipv4_out_speed, ipv6_in_speed, ipv6_out_speed,
total_ipv4_in_speed, total_ipv4_out_speed, total_ipv6_in_speed, total_ipv6_out_speed,
ipV6, ping_dropped
) VALUES
<foreach collection="list" item="item" separator=",">
(
#{item.name}, #{item.mac}, #{item.status}, #{item.type}, #{item.ipV4}, #{item.inDropped}, #{item.outDropped},
#{item.inSpeed}, #{item.outSpeed}, #{item.totalInSpeed}, #{item.totalOutSpeed}, #{item.duplex}, #{item.speed},
#{item.createBy}, #{item.updateBy}, #{item.clientId}, #{item.createTime},
#{item.ipv4InSpeed}, #{item.ipv4OutSpeed}, #{item.ipv6InSpeed}, #{item.ipv6OutSpeed},
#{item.totalIpv4InSpeed}, #{item.totalIpv4OutSpeed}, #{item.totalIpv6InSpeed}, #{item.totalIpv6OutSpeed},
#{item.ipV6}, #{item.pingDropped}
)
</foreach>
ON DUPLICATE KEY UPDATE
`in_speed` = IF(VALUES(`in_speed`) IS NOT NULL, VALUES(`in_speed`), `in_speed`),
`out_speed` = IF(VALUES(`out_speed`) IS NOT NULL, VALUES(`out_speed`), `out_speed`),
`ipv4_in_speed` = IF(VALUES(`ipv4_in_speed`) IS NOT NULL, VALUES(`ipv4_in_speed`), `ipv4_in_speed`),
`ipv4_out_speed` = IF(VALUES(`ipv4_out_speed`) IS NOT NULL, VALUES(`ipv4_out_speed`), `ipv4_out_speed`),
`ipv6_in_speed` = IF(VALUES(`ipv6_in_speed`) IS NOT NULL, VALUES(`ipv6_in_speed`), `ipv6_in_speed`),
`ipv6_out_speed` = IF(VALUES(`ipv6_out_speed`) IS NOT NULL, VALUES(`ipv6_out_speed`), `ipv6_out_speed`)
</insert>
<select id="getNetInterfaceDetailsMsg" parameterType="InitialBandwidthTraffic" resultType="InitialBandwidthTraffic">
select
id,
@@ -229,6 +255,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<where>
<if test="clientId != null and clientId != ''"> and client_id = #{clientId}</if>
<if test="startTime != null"> and create_time = #{startTime}</if>
and in_speed is not null
</where>
</select>
</mapper>