增加历史消息消费接口
This commit is contained in:
@@ -115,8 +115,6 @@ public class MessageHandler {
|
||||
@Autowired
|
||||
private IRmAlarmLogService rmAlarmLogService;
|
||||
@Autowired
|
||||
private IRmAlarmPushConfigService rmAlarmPushConfigService;
|
||||
@Autowired
|
||||
private IRmFrpcConfigManageService rmFrpcConfigManageService;
|
||||
@Autowired
|
||||
private IRmPppoeConfigSubService rmPppoeConfigSubService;
|
||||
@@ -740,9 +738,9 @@ public class MessageHandler {
|
||||
// 尝试获取锁
|
||||
locked = lock.tryLock(0, 20, TimeUnit.SECONDS);
|
||||
if (locked) {
|
||||
log.info("设备{}获取锁成功,开始处理消息", clientId);
|
||||
// log.info("设备{}获取锁成功,开始处理消息", clientId);
|
||||
processNetRecoverMessageInternal(message);
|
||||
log.info("设备{}消息处理完成", clientId);
|
||||
// log.info("设备{}消息处理完成", clientId);
|
||||
} else {
|
||||
log.warn("设备{}获取锁失败,消息处理繁忙", clientId);
|
||||
throw new RuntimeException("设备处理繁忙,请重试");
|
||||
@@ -755,7 +753,7 @@ public class MessageHandler {
|
||||
if (locked && lock.isHeldByCurrentThread()) {
|
||||
try {
|
||||
lock.unlock();
|
||||
log.debug("设备{}锁已释放", clientId);
|
||||
// log.debug("设备{}锁已释放", clientId);
|
||||
} catch (IllegalMonitorStateException e) {
|
||||
log.warn("设备{}锁释放异常,可能已自动超时", clientId);
|
||||
}
|
||||
@@ -775,10 +773,6 @@ public class MessageHandler {
|
||||
boolean lasttrafficFlag = interfaces.get(0).isLastTrafficFlag();
|
||||
// 时间戳存储到redis
|
||||
storeTimestampToRedis(clientId, timestamp);
|
||||
if(lasttrafficFlag){
|
||||
// 把redis中存储的时间戳提取出来,删除redis中的时间戳
|
||||
processExitsTraffic(clientId);
|
||||
}
|
||||
long millis = timestamp * 1000;
|
||||
Date createTime = new Date(millis / 1000 * 1000); // 去除毫秒
|
||||
String timeStr = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",createTime);
|
||||
@@ -790,13 +784,6 @@ public class MessageHandler {
|
||||
countQuery.setStartTime(timeStr);
|
||||
int exitsCount = initialBandwidthTrafficService.countByClientIdAndTime(countQuery);
|
||||
|
||||
// 即使数据已存在,也需要处理临时表逻辑,确保后续计算正确
|
||||
if(exitsCount > 0){
|
||||
// 不直接返回,继续执行临时表处理逻辑
|
||||
// 但跳过最终的数据入库操作
|
||||
System.out.println("数据已存在,跳过入库操作,但继续处理临时表逻辑");
|
||||
}
|
||||
|
||||
// 创建比timestamp少5分钟的时间
|
||||
long fiveMinutesEarlier = millis - (5 * 60 * 1000); // 减去5分钟的毫秒数
|
||||
Date fiveMinutesEarlierDate = new Date(fiveMinutesEarlier / 1000 * 1000); // 同样去除毫秒
|
||||
@@ -943,6 +930,10 @@ public class MessageHandler {
|
||||
// 数据已存在时,只更新临时表,确保后续计算正确
|
||||
initialBandwidthTrafficTempService.batchInsertServerRecoverTemp(interfaces);
|
||||
}
|
||||
if(lasttrafficFlag){
|
||||
// 把redis中存储的时间戳提取出来,删除redis中的时间戳
|
||||
processExitsTraffic(clientId);
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("NET流量data数据为空");
|
||||
}
|
||||
|
||||
+291
@@ -0,0 +1,291 @@
|
||||
package com.tongran.rocketmq.handler;
|
||||
|
||||
import com.tongran.common.core.constant.SecurityConstants;
|
||||
import com.tongran.common.core.enums.MsgEnum;
|
||||
import com.tongran.common.core.utils.DateUtils;
|
||||
import com.tongran.rocketmq.domain.DeviceMessage;
|
||||
import com.tongran.rocketmq.domain.InitialBandwidthTraffic;
|
||||
import com.tongran.rocketmq.domain.InitialBandwidthTrafficTemp;
|
||||
import com.tongran.rocketmq.service.IInitialBandwidthTrafficService;
|
||||
import com.tongran.rocketmq.service.IInitialBandwidthTrafficTempService;
|
||||
import com.tongran.rocketmq.utils.DataProcessUtil;
|
||||
import com.tongran.rocketmq.utils.JsonDataParser;
|
||||
import com.tongran.system.api.RemoteRevenueConfigService;
|
||||
import com.tongran.system.api.domain.EpsInitialTrafficDataRemote;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 设备消息处理器
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@EnableScheduling
|
||||
public class MessageHistoryDataHandler {
|
||||
|
||||
private final Map<String, Consumer<DeviceMessage>> messageHandlers = new HashMap<>();
|
||||
@Autowired
|
||||
private IInitialBandwidthTrafficService initialBandwidthTrafficService;
|
||||
@Autowired
|
||||
private RemoteRevenueConfigService remoteRevenueConfigService;
|
||||
@Autowired
|
||||
private DataProcessUtil dataProcessUtil;
|
||||
@Autowired
|
||||
private RedissonClient redissonClient;
|
||||
@Autowired
|
||||
private IInitialBandwidthTrafficTempService initialBandwidthTrafficTempService;
|
||||
/**
|
||||
* 注册消息处理器
|
||||
*/
|
||||
private void registerHandler(String dataType, Consumer<DeviceMessage> handler) {
|
||||
messageHandlers.put(dataType, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理设备消息(对外暴露的主方法)
|
||||
*/
|
||||
public void handleMessage(DeviceMessage message) {
|
||||
String dataType = message.getDataType();
|
||||
Consumer<DeviceMessage> handler = messageHandlers.get(dataType);
|
||||
|
||||
if (handler != null) {
|
||||
handler.accept(message);
|
||||
} else {
|
||||
log.warn("未知数据类型:{}", dataType);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 初始化处理器映射
|
||||
*/
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
registerHandler(MsgEnum.网络上报重试.getValue(), this::handleNetRecoverMessage);
|
||||
}
|
||||
private void handleNetRecoverMessage(DeviceMessage message) {
|
||||
String clientId = message.getClientId();
|
||||
String lockKey = "traffic:recover:" + clientId;
|
||||
RLock lock = redissonClient.getLock(lockKey);
|
||||
boolean locked = false;
|
||||
|
||||
try {
|
||||
// 尝试获取锁
|
||||
locked = lock.tryLock(0, 20, TimeUnit.SECONDS);
|
||||
if (locked) {
|
||||
processNetRecoverMessageInternal(message);
|
||||
} else {
|
||||
log.warn("设备{}获取锁失败,消息处理繁忙", clientId);
|
||||
throw new RuntimeException("设备处理繁忙,请重试");
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
log.error("处理消息时线程被中断", e);
|
||||
} finally {
|
||||
// 只有成功获取锁的线程才需要释放
|
||||
if (locked && lock.isHeldByCurrentThread()) {
|
||||
try {
|
||||
lock.unlock();
|
||||
} catch (IllegalMonitorStateException e) {
|
||||
log.warn("设备{}锁释放异常,可能已自动超时", clientId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 网络重试流量数据入库
|
||||
* @param message
|
||||
*/
|
||||
private void processNetRecoverMessageInternal(DeviceMessage message) {
|
||||
List<InitialBandwidthTraffic> interfaces = JsonDataParser.parseJsonData(message.getData(), InitialBandwidthTraffic.class);
|
||||
if(!interfaces.isEmpty()){
|
||||
String clientId = message.getClientId();
|
||||
// 时间戳转换
|
||||
long timestamp = interfaces.get(0).getTimestamp();
|
||||
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);
|
||||
|
||||
// 创建比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()
|
||||
.collect(Collectors.toMap(
|
||||
tempItem -> generateKey(tempItem.getMac(), tempItem.getName()),
|
||||
Function.identity(),
|
||||
(existing, replacement) -> existing
|
||||
));
|
||||
|
||||
// 2. 预计算除数(避免重复创建对象)
|
||||
BigDecimal divisor = new BigDecimal(300);
|
||||
|
||||
interfaces.forEach(iface -> {
|
||||
iface.setClientId(clientId);
|
||||
iface.setCreateTime(createTime);
|
||||
|
||||
// 设置总流量(转换为比特)
|
||||
iface.setTotalOutSpeed(dataProcessUtil.bytesToBits(iface.getOutSpeed()));
|
||||
iface.setTotalInSpeed(dataProcessUtil.bytesToBits(iface.getInSpeed()));
|
||||
iface.setTotalIpv4OutSpeed(dataProcessUtil.bytesToBits(iface.getIpv4OutSpeed()));
|
||||
iface.setTotalIpv4InSpeed(dataProcessUtil.bytesToBits(iface.getIpv4InSpeed()));
|
||||
iface.setTotalIpv6OutSpeed(dataProcessUtil.bytesToBits(iface.getIpv6OutSpeed()));
|
||||
iface.setTotalIpv6InSpeed(dataProcessUtil.bytesToBits(iface.getIpv6InSpeed()));
|
||||
// 首次采集,速率设为null
|
||||
iface.setInSpeed(null);
|
||||
iface.setOutSpeed(null);
|
||||
iface.setIpv4InSpeed(null);
|
||||
iface.setIpv4OutSpeed(null);
|
||||
iface.setIpv6InSpeed(null);
|
||||
iface.setIpv6OutSpeed(null);
|
||||
|
||||
// 使用MAC地址+网卡名称作为查找键
|
||||
String key = generateKey(iface.getMac(), iface.getName());
|
||||
InitialBandwidthTrafficTemp tempInfo = tempMap.get(key);
|
||||
if (tempInfo != null) {
|
||||
// 计算总流入速率
|
||||
if (iface.getTotalInSpeed() != null && tempInfo.getTotalInSpeed() != null) {
|
||||
BigDecimal nowInSpeed = new BigDecimal(iface.getTotalInSpeed());
|
||||
BigDecimal tempInSpeed = new BigDecimal(tempInfo.getTotalInSpeed());
|
||||
BigDecimal inDiff = nowInSpeed.subtract(tempInSpeed);
|
||||
if (inDiff.compareTo(BigDecimal.ZERO) >= 0) {
|
||||
iface.setInSpeed(inDiff.divide(divisor, 0, RoundingMode.HALF_UP).toString());
|
||||
}
|
||||
}
|
||||
// 计算总流出速率
|
||||
if (iface.getTotalOutSpeed() != null && tempInfo.getTotalOutSpeed() != null) {
|
||||
BigDecimal nowOutSpeed = new BigDecimal(iface.getTotalOutSpeed());
|
||||
BigDecimal tempOutSpeed = new BigDecimal(tempInfo.getTotalOutSpeed());
|
||||
BigDecimal outDiff = nowOutSpeed.subtract(tempOutSpeed);
|
||||
if (outDiff.compareTo(BigDecimal.ZERO) >= 0) {
|
||||
iface.setOutSpeed(outDiff.divide(divisor, 0, RoundingMode.HALF_UP).toString());
|
||||
}
|
||||
}
|
||||
// 计算IPv4流入速率
|
||||
if (iface.getTotalIpv4InSpeed() != null && tempInfo.getTotalIpv4InSpeed() != null) {
|
||||
BigDecimal nowIpv4In = new BigDecimal(iface.getTotalIpv4InSpeed());
|
||||
BigDecimal tempIpv4In = new BigDecimal(tempInfo.getTotalIpv4InSpeed());
|
||||
BigDecimal ipv4InDiff = nowIpv4In.subtract(tempIpv4In);
|
||||
if (ipv4InDiff.compareTo(BigDecimal.ZERO) >= 0) {
|
||||
iface.setIpv4InSpeed(ipv4InDiff.divide(divisor, 0, RoundingMode.HALF_UP).toString());
|
||||
}
|
||||
}
|
||||
// 计算IPv4流出速率
|
||||
if (iface.getTotalIpv4OutSpeed() != null && tempInfo.getTotalIpv4OutSpeed() != null) {
|
||||
BigDecimal nowIpv4Out = new BigDecimal(iface.getTotalIpv4OutSpeed());
|
||||
BigDecimal tempIpv4Out = new BigDecimal(tempInfo.getTotalIpv4OutSpeed());
|
||||
BigDecimal ipv4OutDiff = nowIpv4Out.subtract(tempIpv4Out);
|
||||
if (ipv4OutDiff.compareTo(BigDecimal.ZERO) >= 0) {
|
||||
iface.setIpv4OutSpeed(ipv4OutDiff.divide(divisor, 0, RoundingMode.HALF_UP).toString());
|
||||
}
|
||||
}
|
||||
// 计算IPv6流入速率
|
||||
if (iface.getTotalIpv6InSpeed() != null && tempInfo.getTotalIpv6InSpeed() != null) {
|
||||
BigDecimal nowIpv6In = new BigDecimal(iface.getTotalIpv6InSpeed());
|
||||
BigDecimal tempIpv6In = new BigDecimal(tempInfo.getTotalIpv6InSpeed());
|
||||
BigDecimal ipv6InDiff = nowIpv6In.subtract(tempIpv6In);
|
||||
if (ipv6InDiff.compareTo(BigDecimal.ZERO) >= 0) {
|
||||
iface.setIpv6InSpeed(ipv6InDiff.divide(divisor, 0, RoundingMode.HALF_UP).toString());
|
||||
}
|
||||
}
|
||||
// 计算IPv6流出速率
|
||||
if (iface.getTotalIpv6OutSpeed() != null && tempInfo.getTotalIpv6OutSpeed() != null) {
|
||||
BigDecimal nowIpv6Out = new BigDecimal(iface.getTotalIpv6OutSpeed());
|
||||
BigDecimal tempIpv6Out = new BigDecimal(tempInfo.getTotalIpv6OutSpeed());
|
||||
BigDecimal ipv6OutDiff = nowIpv6Out.subtract(tempIpv6Out);
|
||||
if (ipv6OutDiff.compareTo(BigDecimal.ZERO) >= 0) {
|
||||
iface.setIpv6OutSpeed(ipv6OutDiff.divide(divisor, 0, RoundingMode.HALF_UP).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// 清空临时表对应server信息
|
||||
InitialBandwidthTrafficTemp delQuery = new InitialBandwidthTrafficTemp();
|
||||
delQuery.setClientId(clientId);
|
||||
delQuery.setCreateTime(fiveMinutesEarlierDate);
|
||||
initialBandwidthTrafficTempService.deleteTempMsgByClientIdAndTime(delQuery);
|
||||
} else {
|
||||
interfaces.forEach(iface -> {
|
||||
iface.setClientId(clientId);
|
||||
iface.setCreateTime(createTime);
|
||||
// 设置总流量(转换为比特)
|
||||
iface.setTotalOutSpeed(dataProcessUtil.bytesToBits(iface.getOutSpeed()));
|
||||
iface.setTotalInSpeed(dataProcessUtil.bytesToBits(iface.getInSpeed()));
|
||||
iface.setTotalIpv4OutSpeed(dataProcessUtil.bytesToBits(iface.getIpv4OutSpeed()));
|
||||
iface.setTotalIpv4InSpeed(dataProcessUtil.bytesToBits(iface.getIpv4InSpeed()));
|
||||
iface.setTotalIpv6OutSpeed(dataProcessUtil.bytesToBits(iface.getIpv6OutSpeed()));
|
||||
iface.setTotalIpv6InSpeed(dataProcessUtil.bytesToBits(iface.getIpv6InSpeed()));
|
||||
|
||||
// 首次采集,速率设为null
|
||||
iface.setInSpeed(null);
|
||||
iface.setOutSpeed(null);
|
||||
iface.setIpv4InSpeed(null);
|
||||
iface.setIpv4OutSpeed(null);
|
||||
iface.setIpv6InSpeed(null);
|
||||
iface.setIpv6OutSpeed(null);
|
||||
});
|
||||
}
|
||||
|
||||
// 只有在数据不存在时才执行入库操作
|
||||
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数据为空");
|
||||
}
|
||||
}
|
||||
|
||||
private String generateKey(String mac, String name) {
|
||||
if (mac == null) {
|
||||
mac = "";
|
||||
}
|
||||
if (name == null) {
|
||||
name = "";
|
||||
}
|
||||
return mac + "|" + name;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user