优化agent本地存储流量数据处理
This commit is contained in:
+7
@@ -133,4 +133,11 @@ public interface RemoteRevenueConfigService
|
|||||||
@GetMapping("/businessScript/inner/{id}")
|
@GetMapping("/businessScript/inner/{id}")
|
||||||
public R<EpsBusinessScriptRemote> getBusinessScriptMsgByScriptId(@PathVariable("id") Long id, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -96,6 +96,11 @@ public class RemoteRevenueConfigFallbackFactory implements FallbackFactory<Remot
|
|||||||
public R<EpsBusinessScriptRemote> getBusinessScriptMsgByScriptId(Long id, String source) {
|
public R<EpsBusinessScriptRemote> getBusinessScriptMsgByScriptId(Long id, String source) {
|
||||||
return R.fail("获取错误关键词失败:" + throwable.getMessage());
|
return R.fail("获取错误关键词失败:" + throwable.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public R<String> autoSaveServiceRecoverTrafficData(EpsInitialTrafficDataRemote queryParam, String source) {
|
||||||
|
return R.fail("保存重试流量数据失败:" + throwable.getMessage());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-5
@@ -118,7 +118,6 @@ public class EchartsDataUtils {
|
|||||||
// 准备X轴和Y轴数据
|
// 准备X轴和Y轴数据
|
||||||
List<String> xAxisData = new ArrayList<>();
|
List<String> xAxisData = new ArrayList<>();
|
||||||
Map<String, Object> yData = new LinkedHashMap<>();
|
Map<String, Object> yData = new LinkedHashMap<>();
|
||||||
|
|
||||||
// 初始化Y轴数据结构
|
// 初始化Y轴数据结构
|
||||||
dataExtractors.keySet().forEach(name ->
|
dataExtractors.keySet().forEach(name ->
|
||||||
yData.put(name, new ArrayList<>()));
|
yData.put(name, new ArrayList<>()));
|
||||||
@@ -152,7 +151,7 @@ public class EchartsDataUtils {
|
|||||||
seriesData.add(getDefaultValue(name, fixedPercentile95Value, xAxisData.size()-1, hasRealData));
|
seriesData.add(getDefaultValue(name, fixedPercentile95Value, xAxisData.size()-1, hasRealData));
|
||||||
} else {
|
} 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特殊处理:始终补空字符串
|
// deployDevice特殊处理:始终补空字符串
|
||||||
if ("deployDevice".equals(metricName)) {
|
if ("deployDevice".equals(metricName)) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
// 智能补全策略
|
||||||
return null;
|
if (hasRealData) {
|
||||||
|
// 数据集中有真实数据:所有缺失点都补null
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
// 数据集中没有真实数据:第一个点补0,其他点补null
|
||||||
|
if (timeIndex == 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+9
@@ -79,5 +79,14 @@ public class EpsServerRevenueConfigController extends BaseController
|
|||||||
{
|
{
|
||||||
return epsServerRevenueConfigService.autoSaveServiceTrafficData(epsServerRevenueConfig);
|
return epsServerRevenueConfigService.autoSaveServiceTrafficData(epsServerRevenueConfig);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 流量相关数据入库
|
||||||
|
*/
|
||||||
|
@InnerAuth
|
||||||
|
@PostMapping("/autoSaveServiceRecoverTrafficData")
|
||||||
|
public R<String> autoSaveServiceRecoverTrafficData(@RequestBody EpsServerRevenueConfig epsServerRevenueConfig)
|
||||||
|
{
|
||||||
|
return epsServerRevenueConfigService.autoSaveServiceRecoverTrafficData(epsServerRevenueConfig);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -74,4 +74,6 @@ public interface EpsInitialTrafficDataMapper {
|
|||||||
void createSwitchOpMdTable(String tableName);
|
void createSwitchOpMdTable(String tableName);
|
||||||
|
|
||||||
void createDiskInfo(String tableName);
|
void createDiskInfo(String tableName);
|
||||||
|
|
||||||
|
void batchInsertRecoverDetailTraffic(EpsInitialTrafficData batchData);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -36,6 +36,7 @@ public interface EpsInitialTrafficDataService {
|
|||||||
* @param dataList 流量数据列表
|
* @param dataList 流量数据列表
|
||||||
*/
|
*/
|
||||||
void saveBatch(EpsInitialTrafficData dataList);
|
void saveBatch(EpsInitialTrafficData dataList);
|
||||||
|
void saveBatchRecoverTraffic(EpsInitialTrafficData dataList);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询流量数据
|
* 查询流量数据
|
||||||
|
|||||||
+1
@@ -67,6 +67,7 @@ public interface IEpsServerRevenueConfigService
|
|||||||
* @param epsServerRevenueConfig
|
* @param epsServerRevenueConfig
|
||||||
*/
|
*/
|
||||||
R<String> autoSaveServiceTrafficData(EpsServerRevenueConfig epsServerRevenueConfig);
|
R<String> autoSaveServiceTrafficData(EpsServerRevenueConfig epsServerRevenueConfig);
|
||||||
|
R<String> autoSaveServiceRecoverTrafficData(EpsServerRevenueConfig epsServerRevenueConfig);
|
||||||
/**
|
/**
|
||||||
* 当前在线服务器的流量相关的业务数
|
* 当前在线服务器的流量相关的业务数
|
||||||
* @return
|
* @return
|
||||||
|
|||||||
+67
@@ -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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 查询流量数据
|
* 查询流量数据
|
||||||
*/
|
*/
|
||||||
|
|||||||
+96
@@ -259,6 +259,102 @@ public class EpsServerRevenueConfigServiceImpl implements IEpsServerRevenueConfi
|
|||||||
return R.fail("数据保存失败:" + e.getMessage() + ",已成功保存" + successCount + "条");
|
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
|
* @return
|
||||||
|
|||||||
+85
@@ -377,6 +377,91 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
)
|
)
|
||||||
</foreach>
|
</foreach>
|
||||||
</insert>
|
</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">
|
<select id="selectByCondition" resultType="EpsInitialTrafficData">
|
||||||
|
|||||||
@@ -721,23 +721,31 @@ public class MessageHandler {
|
|||||||
long millis = timestamp * 1000;
|
long millis = timestamp * 1000;
|
||||||
Date createTime = new Date(millis / 1000 * 1000); // 去除毫秒
|
Date createTime = new Date(millis / 1000 * 1000); // 去除毫秒
|
||||||
String timeStr = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",createTime);
|
String timeStr = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",createTime);
|
||||||
|
|
||||||
// 判断数据库中是否已存在数据
|
// 判断数据库中是否已存在数据
|
||||||
InitialBandwidthTraffic countQuery = new InitialBandwidthTraffic();
|
InitialBandwidthTraffic countQuery = new InitialBandwidthTraffic();
|
||||||
countQuery.setClientId(clientId);
|
countQuery.setClientId(clientId);
|
||||||
countQuery.setCreateTime(createTime);
|
countQuery.setCreateTime(createTime);
|
||||||
countQuery.setStartTime(timeStr);
|
countQuery.setStartTime(timeStr);
|
||||||
int exitsCount = initialBandwidthTrafficService.countByClientIdAndTime(countQuery);
|
int exitsCount = initialBandwidthTrafficService.countByClientIdAndTime(countQuery);
|
||||||
|
|
||||||
|
// 即使数据已存在,也需要处理临时表逻辑,确保后续计算正确
|
||||||
if(exitsCount > 0){
|
if(exitsCount > 0){
|
||||||
return;
|
// 不直接返回,继续执行临时表处理逻辑
|
||||||
|
// 但跳过最终的数据入库操作
|
||||||
|
System.out.println("数据已存在,跳过入库操作,但继续处理临时表逻辑");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建比timestamp少5分钟的时间
|
// 创建比timestamp少5分钟的时间
|
||||||
long fiveMinutesEarlier = millis - (5 * 60 * 1000); // 减去5分钟的毫秒数
|
long fiveMinutesEarlier = millis - (5 * 60 * 1000); // 减去5分钟的毫秒数
|
||||||
Date fiveMinutesEarlierDate = new Date(fiveMinutesEarlier / 1000 * 1000); // 同样去除毫秒
|
Date fiveMinutesEarlierDate = new Date(fiveMinutesEarlier / 1000 * 1000); // 同样去除毫秒
|
||||||
|
|
||||||
// 查询临时表信息,计算实际流量值
|
// 查询临时表信息,计算实际流量值
|
||||||
InitialBandwidthTrafficTemp temp = new InitialBandwidthTrafficTemp();
|
InitialBandwidthTrafficTemp temp = new InitialBandwidthTrafficTemp();
|
||||||
temp.setCreateTime(fiveMinutesEarlierDate);
|
temp.setCreateTime(fiveMinutesEarlierDate);
|
||||||
temp.setClientId(clientId);
|
temp.setClientId(clientId);
|
||||||
List<InitialBandwidthTrafficTemp> tempList = initialBandwidthTrafficTempService.selectInitialBandwidthTrafficRecoverTempList(temp);
|
List<InitialBandwidthTrafficTemp> tempList = initialBandwidthTrafficTempService.selectInitialBandwidthTrafficRecoverTempList(temp);
|
||||||
|
|
||||||
if(!tempList.isEmpty()){
|
if(!tempList.isEmpty()){
|
||||||
// 1. 构建快速查找的Map,使用MAC地址+网卡名称作为唯一键
|
// 1. 构建快速查找的Map,使用MAC地址+网卡名称作为唯一键
|
||||||
Map<String, InitialBandwidthTrafficTemp> tempMap = tempList.stream()
|
Map<String, InitialBandwidthTrafficTemp> tempMap = tempList.stream()
|
||||||
@@ -834,7 +842,7 @@ public class MessageHandler {
|
|||||||
delQuery.setClientId(clientId);
|
delQuery.setClientId(clientId);
|
||||||
delQuery.setCreateTime(fiveMinutesEarlierDate);
|
delQuery.setCreateTime(fiveMinutesEarlierDate);
|
||||||
initialBandwidthTrafficTempService.deleteTempMsgByClientIdAndTime(delQuery);
|
initialBandwidthTrafficTempService.deleteTempMsgByClientIdAndTime(delQuery);
|
||||||
}else{
|
} else {
|
||||||
interfaces.forEach(iface -> {
|
interfaces.forEach(iface -> {
|
||||||
iface.setClientId(clientId);
|
iface.setClientId(clientId);
|
||||||
iface.setCreateTime(createTime);
|
iface.setCreateTime(createTime);
|
||||||
@@ -855,19 +863,26 @@ public class MessageHandler {
|
|||||||
iface.setIpv6OutSpeed(null);
|
iface.setIpv6OutSpeed(null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
InitialBandwidthTraffic data = new InitialBandwidthTraffic();
|
|
||||||
// 批量入库集合
|
// 只有在数据不存在时才执行入库操作
|
||||||
data.setList(interfaces);
|
if (exitsCount == 0) {
|
||||||
// 临时表 用来计算流量速率
|
InitialBandwidthTraffic data = new InitialBandwidthTraffic();
|
||||||
initialBandwidthTrafficTempService.batchInsertServerRecoverTemp(interfaces);
|
// 批量入库集合
|
||||||
// 初始流量数据入库
|
data.setList(interfaces);
|
||||||
initialBandwidthTrafficService.batchInsert(data);
|
// 临时表 用来计算流量速率
|
||||||
EpsInitialTrafficDataRemote epsInitialTrafficDataRemote = new EpsInitialTrafficDataRemote();
|
initialBandwidthTrafficTempService.batchInsertServerRecoverTemp(interfaces);
|
||||||
epsInitialTrafficDataRemote.setStartTime(timeStr);
|
// 初始流量数据入库
|
||||||
epsInitialTrafficDataRemote.setEndTime(timeStr);
|
initialBandwidthTrafficService.batchInsertRecoverTraffic(data);
|
||||||
// 复制到业务初始库
|
EpsInitialTrafficDataRemote epsInitialTrafficDataRemote = new EpsInitialTrafficDataRemote();
|
||||||
remoteRevenueConfigService.autoSaveServiceTrafficData(epsInitialTrafficDataRemote, SecurityConstants.INNER);
|
epsInitialTrafficDataRemote.setStartTime(timeStr);
|
||||||
}else{
|
epsInitialTrafficDataRemote.setEndTime(timeStr);
|
||||||
|
// 复制到业务初始库
|
||||||
|
remoteRevenueConfigService.autoSaveServiceRecoverTrafficData(epsInitialTrafficDataRemote, SecurityConstants.INNER);
|
||||||
|
} else {
|
||||||
|
// 数据已存在时,只更新临时表,确保后续计算正确
|
||||||
|
initialBandwidthTrafficTempService.batchInsertServerRecoverTemp(interfaces);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
throw new RuntimeException("NET流量data数据为空");
|
throw new RuntimeException("NET流量data数据为空");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -971,77 +986,77 @@ public class MessageHandler {
|
|||||||
long timestamp = disks.get(0).getTimestamp();
|
long timestamp = disks.get(0).getTimestamp();
|
||||||
long millis = timestamp * 1000;
|
long millis = timestamp * 1000;
|
||||||
Date createTime = new Date(millis / 1000 * 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 -> {
|
// disks.forEach(disk -> {
|
||||||
// String diskName = disk.getName();
|
|
||||||
// reportedDisks.add(diskName);
|
|
||||||
//
|
|
||||||
// // 本次上报的磁盘,次数重置为0
|
|
||||||
// redisTemplate.opsForHash().put(diskCountKey, diskName, "0");
|
|
||||||
//
|
|
||||||
// disk.setClientId(clientId);
|
// disk.setClientId(clientId);
|
||||||
// disk.setCreateTime(createTime);
|
// disk.setCreateTime(createTime);
|
||||||
// });
|
// });
|
||||||
//
|
// 关键:每个clientId有自己独立的key
|
||||||
// // 3. 检查次数≥3的磁盘
|
String diskCountKey = DISK_COUNT_PREFIX + clientId;
|
||||||
// diskCountMap = redisTemplate.opsForHash().entries(diskCountKey);
|
|
||||||
// List<String> disksToRemove = new ArrayList<>();
|
// 1. 给这个客户端的所有磁盘次数+1
|
||||||
//
|
Map<Object, Object> diskCountMap = redisTemplate.opsForHash().entries(diskCountKey);
|
||||||
// for (Map.Entry<Object, Object> entry : diskCountMap.entrySet()) {
|
for (Map.Entry<Object, Object> entry : diskCountMap.entrySet()) {
|
||||||
// String diskName = (String) entry.getKey();
|
String diskName = (String) entry.getKey();
|
||||||
// String countStr = (String) entry.getValue();
|
String countStr = (String) entry.getValue();
|
||||||
//
|
|
||||||
// try {
|
try {
|
||||||
// int count = Integer.parseInt(countStr);
|
int count = Integer.parseInt(countStr) + 1;
|
||||||
// // 如果次数≥3且本次没上报
|
redisTemplate.opsForHash().put(diskCountKey, diskName, String.valueOf(count));
|
||||||
// if (count >= 3 && !reportedDisks.contains(diskName)) {
|
} catch (NumberFormatException e) {
|
||||||
// AllDiskName allDiskName = new AllDiskName();
|
redisTemplate.opsForHash().put(diskCountKey, diskName, "1");
|
||||||
// allDiskName.setStatus(0);
|
}
|
||||||
// allDiskName.setClientId(clientId);
|
}
|
||||||
// allDiskName.setName(diskName);
|
|
||||||
// allDiskNameService.updateAllDiskName(allDiskName);
|
// 2. 处理本次上报的磁盘
|
||||||
// disksToRemove.add(diskName);
|
Set<String> reportedDisks = new HashSet<>();
|
||||||
// // 磁盘缺失,触发告警
|
disks.forEach(disk -> {
|
||||||
// RmAlarmLog rmAlarmLog = new RmAlarmLog();
|
String diskName = disk.getName();
|
||||||
// rmAlarmLog.setClientId(clientId);
|
reportedDisks.add(diskName);
|
||||||
// rmAlarmLog.setAlarmTime(DateUtils.getNowDate());
|
|
||||||
// rmAlarmLog.setAlarmType(AlarmTypeEnum.磁盘缺失.getCode());
|
// 本次上报的磁盘,次数重置为0
|
||||||
// rmAlarmLog.setAlarmContent("服务器" + clientId + "磁盘缺失,磁盘名称:" + diskName);
|
redisTemplate.opsForHash().put(diskCountKey, diskName, "0");
|
||||||
// rmAlarmLogService.insertRmAlarmLog(rmAlarmLog);
|
|
||||||
// sendAlarmPushUtil.sendAlarmPush(rmAlarmLog, AlarmTypeEnum.磁盘缺失.getMsg());
|
disk.setClientId(clientId);
|
||||||
//
|
disk.setCreateTime(createTime);
|
||||||
// }
|
});
|
||||||
// } catch (NumberFormatException e) {
|
|
||||||
// disksToRemove.add(diskName);
|
// 3. 检查次数≥3的磁盘
|
||||||
// }
|
diskCountMap = redisTemplate.opsForHash().entries(diskCountKey);
|
||||||
// }
|
List<String> disksToRemove = new ArrayList<>();
|
||||||
//
|
|
||||||
// // 4. 删除已处理的磁盘记录
|
for (Map.Entry<Object, Object> entry : diskCountMap.entrySet()) {
|
||||||
// if (!disksToRemove.isEmpty()) {
|
String diskName = (String) entry.getKey();
|
||||||
// redisTemplate.opsForHash().delete(diskCountKey, disksToRemove.toArray());
|
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. 数据入库
|
// 5. 数据入库
|
||||||
initialDiskInfoService.batchInsertInitialDiskInfo(disks, createTime);
|
initialDiskInfoService.batchInsertInitialDiskInfo(disks, createTime);
|
||||||
@@ -1961,7 +1976,7 @@ public class MessageHandler {
|
|||||||
* 查询IP地址归属地信息,返回运营商和省份
|
* 查询IP地址归属地信息,返回运营商和省份
|
||||||
*/
|
*/
|
||||||
private Map<String, String> queryIpLocation(String 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();
|
CloseableHttpClient httpClient = HttpClients.createDefault();
|
||||||
HttpGet httpGet = new HttpGet(apiUrl);
|
HttpGet httpGet = new HttpGet(apiUrl);
|
||||||
|
|
||||||
|
|||||||
+1
@@ -71,6 +71,7 @@ public interface InitialBandwidthTrafficMapper
|
|||||||
* @param data 流量数据实体类
|
* @param data 流量数据实体类
|
||||||
*/
|
*/
|
||||||
int batchInsert(InitialBandwidthTraffic data);
|
int batchInsert(InitialBandwidthTraffic data);
|
||||||
|
int batchInsertRecoverTraffic(InitialBandwidthTraffic data);
|
||||||
/**
|
/**
|
||||||
* 网络接口基础信息
|
* 网络接口基础信息
|
||||||
* @param initialBandwidthTraffic
|
* @param initialBandwidthTraffic
|
||||||
|
|||||||
+1
@@ -71,6 +71,7 @@ public interface IInitialBandwidthTrafficService
|
|||||||
* @param data 流量数据
|
* @param data 流量数据
|
||||||
*/
|
*/
|
||||||
void batchInsert(InitialBandwidthTraffic data);
|
void batchInsert(InitialBandwidthTraffic data);
|
||||||
|
void batchInsertRecoverTraffic(InitialBandwidthTraffic data);
|
||||||
/**
|
/**
|
||||||
* 网络接口基础信息
|
* 网络接口基础信息
|
||||||
* @param initialBandwidthTraffic
|
* @param initialBandwidthTraffic
|
||||||
|
|||||||
+50
@@ -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
|
* @param initialBandwidthTraffic
|
||||||
|
|||||||
+28
-1
@@ -143,7 +143,33 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
)
|
)
|
||||||
</foreach>
|
</foreach>
|
||||||
</insert>
|
</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="getNetInterfaceDetailsMsg" parameterType="InitialBandwidthTraffic" resultType="InitialBandwidthTraffic">
|
||||||
select
|
select
|
||||||
id,
|
id,
|
||||||
@@ -229,6 +255,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<where>
|
<where>
|
||||||
<if test="clientId != null and clientId != ''"> and client_id = #{clientId}</if>
|
<if test="clientId != null and clientId != ''"> and client_id = #{clientId}</if>
|
||||||
<if test="startTime != null"> and create_time = #{startTime}</if>
|
<if test="startTime != null"> and create_time = #{startTime}</if>
|
||||||
|
and in_speed is not null
|
||||||
</where>
|
</where>
|
||||||
</select>
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
Reference in New Issue
Block a user