初始化v1.2

This commit is contained in:
gaoyutao
2025-11-24 16:19:09 +08:00
parent c0f51ef007
commit de49404116
918 changed files with 4236 additions and 4239 deletions
@@ -0,0 +1,25 @@
package com.tongran.mtragent;
import com.tongran.common.security.annotation.EnableCustomConfig;
import com.tongran.common.security.annotation.EnableRyFeignClients;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
/**
* 平台管理模块
*
* @author tongran
*/
@EnableCustomConfig
@EnableRyFeignClients
@SpringBootApplication
@EnableAsync
public class TongRanMtragentApplication
{
public static void main(String[] args)
{
SpringApplication.run(TongRanMtragentApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ RuoYiMtragent模块启动成功 ლ(´ڡ`ლ)゙");
}
}
@@ -0,0 +1,77 @@
package com.tongran.mtragent.config;
import com.tongran.mtragent.consumer.RocketMsgListener;
import com.tongran.mtragent.enums.MessageTopic;
import com.tongran.mtragent.model.ConsumerMode;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
/**
* 消费者配置
*/
@RefreshScope
@Configuration
@Slf4j
public class ConsumerConfig {
@Autowired
private ConsumerMode consumerMode;
@Autowired
private RocketMsgListener rocketMsgListener;
@Bean
public DefaultMQPushConsumer getRocketMQConsumer() {
//构建客户端连接
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(consumerMode.getAgentGroup());
//
consumer.setNamesrvAddr(consumerMode.getNamesrvAddr());
consumer.setConsumeThreadMin(consumerMode.getConsumeThreadMin());
consumer.setConsumeThreadMax(consumerMode.getConsumeThreadMax());
consumer.registerMessageListener(rocketMsgListener);
/**
* 1. CONSUME_FROM_LAST_OFFSET:第一次启动从队列最后位置消费,后续再启动接着上次消费的进度开始消费
* 2. CONSUME_FROM_FIRST_OFFSET:第一次启动从队列初始位置消费,后续再启动接着上次消费的进度开始消费
* 3. CONSUME_FROM_TIMESTAMP:第一次启动从指定时间点位置消费,后续再启动接着上次消费的进度开始消费
* 以上所说的第一次启动是指从来没有消费过的消费者,如果该消费者消费过,那么会在broker端记录该消费者的消费位置,如果该消费者挂了再启动,那么自动从上次消费的进度开始
*/
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
/**
* CLUSTERING (集群模式) :默认模式,同一个ConsumerGroup(groupName相同)每个consumer只消费所订阅消息的一部分内容,同一个ConsumerGroup里所有的Consumer消息加起来才是所
* 订阅topic整体,从而达到负载均衡的目的
* BROADCASTING (广播模式) :同一个ConsumerGroup每个consumer都消费到所订阅topic所有消息,也就是一个消费会被多次分发,被多个consumer消费。
* 需要注意的是,在广播模式下,每个Consumer都会独立地处理相同的消息副本。这可能会导致一些潜在的问题,例如消息重复处理或者资源浪费。因此,在使用广播模式时,请确保消息的处理逻辑是幂等的,并仔细考虑系统资源的消耗。
*/
// consumer.setMessageModel(MessageModel.BROADCASTING);
consumer.setVipChannelEnabled(false);
consumer.setConsumeMessageBatchMaxSize(consumerMode.getConsumeMessageBatchMaxSize());
try {
/**
* 订阅topic,可以对指定消息进行过滤,例如:"TopicTest","tagl||tag2||tag3",*或null表示topic所有消息
* 由于官方并没有给直接订阅全部消息示例 所以使用list列表循环订阅所有topic
*/
// 获取所有topic列表
MessageTopic messageTopic = new MessageTopic();
List<String> allTopics = messageTopic.RocketMQTopicList();
//订阅所有topic
for (String topic : allTopics) {
consumer.subscribe(topic,"*");
}
consumer.start();
log.info("消费者初始化成功:{}", consumer);
} catch (MQClientException e) {
e.printStackTrace();
log.error("消费者初始化失败:{}",e.getMessage());
}
return consumer;
}
}
@@ -0,0 +1,56 @@
package com.tongran.mtragent.config;
import com.tongran.mtragent.model.ProducerMode;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* mq搭建地址连接
* 生产者初者连接信息 具体看nacos配置
*/
@Configuration
@Slf4j
public class ProducerConfig {
/**
* 远程调用连接信息
*/
public static DefaultMQProducer producer;
/**
* 连接客户端信息配置 具体看nacos配置
*/
@Autowired
private ProducerMode producerMode;
@Bean
public DefaultMQProducer getRocketMQProducer() {
producer = new DefaultMQProducer(producerMode.getAgentGroup());
producer.setNamesrvAddr(producerMode.getNamesrvAddr());
//如果需要同一个jvm中不同的producer往不同的mq集群发送消息,需要设置不同的instanceName
if(producerMode.getMaxMessageSize()!=null){
producer.setMaxMessageSize(producerMode.getMaxMessageSize());
}
if(producerMode.getSendMsgTimeout()!=null){
producer.setSendMsgTimeout(producerMode.getSendMsgTimeout());
}
//如果发送消息失败,设置重试次数,默认为2次
if(producerMode.getRetryTimesWhenSendFailed()!=null){
producer.setRetryTimesWhenSendFailed(producerMode.getRetryTimesWhenSendFailed());
}
producer.setVipChannelEnabled(false);
try {
producer.start();
log.info("生产者初始化成功:{}",producer.toString());
} catch (MQClientException e) {
log.error("生产者初始化失败:{}",e.getMessage());
}
return producer;
}
}
@@ -0,0 +1,94 @@
package com.tongran.mtragent.consumer;
import com.alibaba.fastjson.JSON;
import com.tongran.mtragent.domain.DeviceMessage;
import com.tongran.mtragent.enums.MessageCodeEnum;
import com.tongran.mtragent.handler.MessageHandler;
import com.tongran.mtragent.producer.ConsumeException;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.io.UnsupportedEncodingException;
import java.util.List;
/**
* 消息监听
*/
@Slf4j
@Component
public class RocketMsgListener implements MessageListenerConcurrently {
@Autowired
private MessageHandler messageHandler;
/**
* 消费消息
* @param list msgs.size() >= 1
* DefaultMQPushConsumer.consumeMessageBatchMaxSize=1you can modify here
* 这里只设置为1,当设置为多个时,list中只要有一条消息消费失败,就会整体重试
* @param consumeConcurrentlyContext 上下文信息
* @return 消费状态 成功(CONSUME_SUCCESS)或者 重试 (RECONSUME_LATER)
*/
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
try{
//消息不等于空情况
if (!CollectionUtils.isEmpty(list)) {
//获取topic
for (MessageExt messageExt : list) {
// 解析消息内容
String body = new String(messageExt.getBody());
log.info("接受到的消息为:{}", body);
String tags = messageExt.getTags();
String topic = messageExt.getTopic();
String msgId = messageExt.getMsgId();
String keys = messageExt.getKeys();
int reConsume = messageExt.getReconsumeTimes();
// 消息已经重试了3次,如果不需要再次消费,则返回成功
if (reConsume == 3) {
// TODO 补偿信息
log.error("消息消费三次失败,消息内容:{}", body);
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;//根据业务返回是否正常
}
if(MessageCodeEnum.TR_MTRAGENT_UP.getCode().equals(topic)){
// 拿到信息
DeviceMessage message = JSON.parseObject(body, DeviceMessage.class);
// 处理消息
messageHandler.handleMessage(message);
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;//业务处理成功
}
// 根据不同的topic处理不同的业务 这里以订单消息为例子
}
}
// 消息消费失败
//broker会根据设置的messageDelayLevel发起重试,默认16次
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
} catch (Exception e) {
// 调用 handleException 方法处理异常并返回处理结果
return handleException(e);
}
}
/**
* 异常处理
*
* @param e 捕获的异常
* @return 消息消费结果
*/
private static ConsumeConcurrentlyStatus handleException(final Exception e) {
Class exceptionClass = e.getClass();
if (exceptionClass.equals(UnsupportedEncodingException.class)) {
log.error(e.getMessage());
} else if (exceptionClass.equals(ConsumeException.class)) {
log.error(e.getMessage());
} else{
log.error(e.getMessage());
}
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
}
@@ -0,0 +1,30 @@
package com.tongran.mtragent.consumer;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.TransactionListener;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageExt;
/**
* 事物消息监听
*/
public class RocketMsgTransactionListenerImpl implements TransactionListener {
@Override
public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
// 在这里执行本地事务,比如数据库操作等
// 如果本地事务执行成功,返回 COMMIT_MESSAGE
// 如果本地事务执行失败,返回 ROLLBACK_MESSAGE
// 如果本地事务执行中,可以返回 UNKNOW,RocketMQ 将会检查事务状态,并根据状态处理消息
return LocalTransactionState.COMMIT_MESSAGE; // 根据实际情况返回对应的状态
}
@Override
public LocalTransactionState checkLocalTransaction(MessageExt msg) {
// 检查本地事务状态,如果本地事务执行成功,返回 COMMIT_MESSAGE
// 如果本地事务执行失败,返回 ROLLBACK_MESSAGE
// 如果本地事务仍在执行中,返回 UNKNOW,RocketMQ 将会继续检查事务状态
return LocalTransactionState.COMMIT_MESSAGE; // 根据实际情况返回对应的状态
}
}
@@ -0,0 +1,105 @@
package com.tongran.mtragent.controller;
import java.util.List;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.tongran.common.log.annotation.Log;
import com.tongran.common.log.enums.BusinessType;
import com.tongran.common.security.annotation.RequiresPermissions;
import com.tongran.mtragent.domain.AllMtrClient;
import com.tongran.mtragent.service.IAllMtrClientService;
import com.tongran.common.core.web.controller.BaseController;
import com.tongran.common.core.web.domain.AjaxResult;
import com.tongran.common.core.utils.poi.ExcelUtil;
import com.tongran.common.core.web.page.TableDataInfo;
/**
* mtr探测丢包clinetId记录Controller
*
* @author gyt
* @date 2025-11-24
*/
@RestController
@RequestMapping("/allMtrClient")
public class AllMtrClientController extends BaseController
{
@Autowired
private IAllMtrClientService allMtrClientService;
/**
* 查询mtr探测丢包clinetId记录列表
*/
@RequiresPermissions("mtragent:allMtrClient:list")
@GetMapping("/list")
public TableDataInfo list(AllMtrClient allMtrClient)
{
startPage();
List<AllMtrClient> list = allMtrClientService.selectAllMtrClientList(allMtrClient);
return getDataTable(list);
}
/**
* 导出mtr探测丢包clinetId记录列表
*/
@RequiresPermissions("mtragent:allMtrClient:export")
@Log(title = "mtr探测丢包clinetId记录", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, AllMtrClient allMtrClient)
{
List<AllMtrClient> list = allMtrClientService.selectAllMtrClientList(allMtrClient);
ExcelUtil<AllMtrClient> util = new ExcelUtil<AllMtrClient>(AllMtrClient.class);
util.exportExcel(response, list, "mtr探测丢包clinetId记录数据");
}
/**
* 获取mtr探测丢包clinetId记录详细信息
*/
@RequiresPermissions("mtragent:allMtrClient:query")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(allMtrClientService.selectAllMtrClientById(id));
}
/**
* 新增mtr探测丢包clinetId记录
*/
@RequiresPermissions("mtragent:allMtrClient:add")
@Log(title = "mtr探测丢包clinetId记录", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody AllMtrClient allMtrClient)
{
return toAjax(allMtrClientService.insertAllMtrClient(allMtrClient));
}
/**
* 修改mtr探测丢包clinetId记录
*/
@RequiresPermissions("mtragent:allMtrClient:edit")
@Log(title = "mtr探测丢包clinetId记录", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody AllMtrClient allMtrClient)
{
return toAjax(allMtrClientService.updateAllMtrClient(allMtrClient));
}
/**
* 删除mtr探测丢包clinetId记录
*/
@RequiresPermissions("mtragent:allMtrClient:remove")
@Log(title = "mtr探测丢包clinetId记录", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(allMtrClientService.deleteAllMtrClientByIds(ids));
}
}
@@ -0,0 +1,138 @@
package com.tongran.mtragent.controller;
import com.tongran.common.core.utils.poi.ExcelUtil;
import com.tongran.common.core.web.controller.BaseController;
import com.tongran.common.core.web.domain.AjaxResult;
import com.tongran.common.core.web.page.PageDomain;
import com.tongran.common.core.web.page.TableDataInfo;
import com.tongran.common.log.annotation.Log;
import com.tongran.common.log.enums.BusinessType;
import com.tongran.common.security.annotation.RequiresPermissions;
import com.tongran.mtragent.domain.AllMtrClient;
import com.tongran.mtragent.domain.RmMtrClientRegistration;
import com.tongran.mtragent.service.IRmMtrClientRegistrationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* MTR客户端注册Controller
*
* @author gyt
* @date 2025-11-18
*/
@RestController
@RequestMapping("/mtrClientRegistration")
public class RmMtrClientRegistrationController extends BaseController
{
@Autowired
private IRmMtrClientRegistrationService rmMtrClientRegistrationService;
/**
* 查询MTR客户端注册列表
*/
@RequiresPermissions("mtragent:mtrClientRegistration:list")
@PostMapping("/list")
public TableDataInfo list(@RequestBody RmMtrClientRegistration rmMtrClientRegistration)
{
PageDomain pageDomain = new PageDomain();
pageDomain.setPageNum(rmMtrClientRegistration.getPageNum());
pageDomain.setPageSize(rmMtrClientRegistration.getPageSize());
startPage(pageDomain);
List<RmMtrClientRegistration> list = rmMtrClientRegistrationService.selectRmMtrClientRegistrationList(rmMtrClientRegistration);
return getDataTable(list);
}
/**
* 导出MTR客户端注册列表
*/
@RequiresPermissions("mtragent:mtrClientRegistration:export")
@Log(title = "MTR客户端注册", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, @RequestBody RmMtrClientRegistration rmMtrClientRegistration)
{
List<RmMtrClientRegistration> list = rmMtrClientRegistrationService.selectRmMtrClientRegistrationList(rmMtrClientRegistration);
ExcelUtil<RmMtrClientRegistration> util = new ExcelUtil<RmMtrClientRegistration>(RmMtrClientRegistration.class);
util.showColumn(rmMtrClientRegistration.getProperties());
util.exportExcel(response, list, "MTR客户端注册数据");
}
/**
* 获取MTR客户端注册详细信息
*/
@RequiresPermissions("mtragent:mtrClientRegistration:query")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(rmMtrClientRegistrationService.selectRmMtrClientRegistrationById(id));
}
/**
* 新增MTR客户端注册
*/
@RequiresPermissions("mtragent:mtrClientRegistration:add")
@Log(title = "MTR客户端注册", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody RmMtrClientRegistration rmMtrClientRegistration)
{
return toAjax(rmMtrClientRegistrationService.insertRmMtrClientRegistration(rmMtrClientRegistration));
}
/**
* 修改MTR客户端注册
*/
@RequiresPermissions("mtragent:mtrClientRegistration:edit")
@Log(title = "MTR客户端注册", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody RmMtrClientRegistration rmMtrClientRegistration)
{
return toAjax(rmMtrClientRegistrationService.updateRmMtrClientRegistration(rmMtrClientRegistration));
}
/**
* 配置更新策略
* @param rmMtrClientRegistration
* @return
*/
@RequiresPermissions("mtragent:mtrClientRegistration:add")
@PostMapping("/addAgentUpdatePolicy")
public AjaxResult addAgentUpdatePolicy(@RequestBody RmMtrClientRegistration rmMtrClientRegistration){
int rows = rmMtrClientRegistrationService.addAgentUpdatePolicy(rmMtrClientRegistration);
return toAjax(rows);
}
/**
* 查询所有MTR客户端注册
*/
@RequiresPermissions("mtragent:mtrClientRegistration:list")
@PostMapping("/getAllMtrMsg")
public AjaxResult getAllMtrMsg(@RequestBody RmMtrClientRegistration rmMtrClientRegistration)
{
List<RmMtrClientRegistration> list = rmMtrClientRegistrationService.selectRmMtrClientRegistrationList(rmMtrClientRegistration);
return success(list);
}
/**
* 查询MTR客户端注册列表
*/
@RequiresPermissions("mtragent:mtrClientRegistration:list")
@PostMapping("/getAllLogicalNode")
public AjaxResult getAllLogicalNode(@RequestBody RmMtrClientRegistration rmMtrClientRegistration)
{
List<RmMtrClientRegistration> list = rmMtrClientRegistrationService.getAllLogicalNode(rmMtrClientRegistration);
return success(list);
}
/**
* 根据mtrClientId查询包含的clientId
* @param rmMtrClientRegistration
* @return
*/
@RequiresPermissions("mtragent:mtrClientRegistration:list")
@PostMapping("/getClientIdByMtrClientId")
public AjaxResult getClientIdByMtrClientId(@RequestBody RmMtrClientRegistration rmMtrClientRegistration)
{
List<AllMtrClient> list = rmMtrClientRegistrationService.getClientIdByMtrClientId(rmMtrClientRegistration);
return success(list);
}
}
@@ -0,0 +1,103 @@
package com.tongran.mtragent.controller;
import com.tongran.common.core.utils.poi.ExcelUtil;
import com.tongran.common.core.web.controller.BaseController;
import com.tongran.common.core.web.domain.AjaxResult;
import com.tongran.common.core.web.page.PageDomain;
import com.tongran.common.core.web.page.TableDataInfo;
import com.tongran.common.log.annotation.Log;
import com.tongran.common.log.enums.BusinessType;
import com.tongran.common.security.annotation.RequiresPermissions;
import com.tongran.mtragent.domain.RmMtrPolicyConfig;
import com.tongran.mtragent.service.IRmMtrPolicyConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* mtr探测策略配置Controller
*
* @author gyt
* @date 2025-11-18
*/
@RestController
@RequestMapping("/mtrPolicyConfig")
public class RmMtrPolicyConfigController extends BaseController
{
@Autowired
private IRmMtrPolicyConfigService rmMtrPolicyConfigService;
/**
* 查询mtr探测策略配置列表
*/
@RequiresPermissions("mtragent:mtrPolicyConfig:list")
@PostMapping("/list")
public TableDataInfo list(@RequestBody RmMtrPolicyConfig rmMtrPolicyConfig)
{
PageDomain pageDomain = new PageDomain();
pageDomain.setPageNum(rmMtrPolicyConfig.getPageNum());
pageDomain.setPageSize(rmMtrPolicyConfig.getPageSize());
startPage(pageDomain);
List<RmMtrPolicyConfig> list = rmMtrPolicyConfigService.selectRmMtrPolicyConfigList(rmMtrPolicyConfig);
return getDataTable(list);
}
/**
* 导出mtr探测策略配置列表
*/
@RequiresPermissions("mtragent:mtrPolicyConfig:export")
@Log(title = "mtr探测策略配置", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, RmMtrPolicyConfig rmMtrPolicyConfig)
{
List<RmMtrPolicyConfig> list = rmMtrPolicyConfigService.selectRmMtrPolicyConfigList(rmMtrPolicyConfig);
ExcelUtil<RmMtrPolicyConfig> util = new ExcelUtil<RmMtrPolicyConfig>(RmMtrPolicyConfig.class);
util.showColumn(rmMtrPolicyConfig.getProperties());
util.exportExcel(response, list, "mtr探测策略配置数据");
}
/**
* 获取mtr探测策略配置详细信息
*/
@RequiresPermissions("mtragent:mtrPolicyConfig:query")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(rmMtrPolicyConfigService.selectRmMtrPolicyConfigById(id));
}
/**
* 新增mtr探测策略配置
*/
@RequiresPermissions("mtragent:mtrPolicyConfig:add")
@Log(title = "mtr探测策略配置", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody RmMtrPolicyConfig rmMtrPolicyConfig)
{
return toAjax(rmMtrPolicyConfigService.insertRmMtrPolicyConfig(rmMtrPolicyConfig));
}
/**
* 修改mtr探测策略配置
*/
@RequiresPermissions("mtragent:mtrPolicyConfig:edit")
@Log(title = "mtr探测策略配置", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody RmMtrPolicyConfig rmMtrPolicyConfig)
{
return toAjax(rmMtrPolicyConfigService.updateRmMtrPolicyConfig(rmMtrPolicyConfig));
}
/**
* 删除mtr探测策略配置
*/
@RequiresPermissions("mtragent:mtrPolicyConfig:remove")
@Log(title = "mtr探测策略配置", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(rmMtrPolicyConfigService.deleteRmMtrPolicyConfigByIds(ids));
}
}
@@ -0,0 +1,110 @@
package com.tongran.mtragent.controller;
import com.tongran.common.core.utils.poi.ExcelUtil;
import com.tongran.common.core.web.controller.BaseController;
import com.tongran.common.core.web.domain.AjaxResult;
import com.tongran.common.core.web.page.TableDataInfo;
import com.tongran.common.log.annotation.Log;
import com.tongran.common.log.enums.BusinessType;
import com.tongran.common.security.annotation.RequiresPermissions;
import com.tongran.mtragent.domain.RmMtrProbeResult;
import com.tongran.mtragent.service.IRmMtrProbeResultService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
/**
* 网络mtr探测结果Controller
*
* @author gyt
* @date 2025-11-20
*/
@RestController
@RequestMapping("/mtrProbeResult")
public class RmMtrProbeResultController extends BaseController
{
@Autowired
private IRmMtrProbeResultService rmMtrProbeResultService;
/**
* 查询网络mtr探测结果列表
*/
@RequiresPermissions("mtragent:mtrProbeResult:list")
@GetMapping("/list")
public TableDataInfo list(RmMtrProbeResult rmMtrProbeResult)
{
startPage();
List<RmMtrProbeResult> list = rmMtrProbeResultService.selectRmMtrProbeResultList(rmMtrProbeResult);
return getDataTable(list);
}
/**
* 导出网络mtr探测结果列表
*/
@RequiresPermissions("mtragent:mtrProbeResult:export")
@Log(title = "网络mtr探测结果", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, RmMtrProbeResult rmMtrProbeResult)
{
List<RmMtrProbeResult> list = rmMtrProbeResultService.selectRmMtrProbeResultList(rmMtrProbeResult);
ExcelUtil<RmMtrProbeResult> util = new ExcelUtil<RmMtrProbeResult>(RmMtrProbeResult.class);
util.exportExcel(response, list, "网络mtr探测结果数据");
}
/**
* 获取网络mtr探测结果详细信息
*/
@RequiresPermissions("mtragent:mtrProbeResult:query")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(rmMtrProbeResultService.selectRmMtrProbeResultById(id));
}
/**
* 新增网络mtr探测结果
*/
@RequiresPermissions("mtragent:mtrProbeResult:add")
@Log(title = "网络mtr探测结果", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody RmMtrProbeResult rmMtrProbeResult)
{
return toAjax(rmMtrProbeResultService.insertRmMtrProbeResult(rmMtrProbeResult));
}
/**
* 修改网络mtr探测结果
*/
@RequiresPermissions("mtragent:mtrProbeResult:edit")
@Log(title = "网络mtr探测结果", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody RmMtrProbeResult rmMtrProbeResult)
{
return toAjax(rmMtrProbeResultService.updateRmMtrProbeResult(rmMtrProbeResult));
}
/**
* 删除网络mtr探测结果
*/
@RequiresPermissions("mtragent:mtrProbeResult:remove")
@Log(title = "网络mtr探测结果", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(rmMtrProbeResultService.deleteRmMtrProbeResultByIds(ids));
}
/**
* 查看丢包率趋势
*/
@RequiresPermissions("mtragent:mtrProbeResult:list")
@PostMapping("/getLossRateByMtrClientId")
public AjaxResult getLossRateByMtrClientId(@RequestBody RmMtrProbeResult rmMtrProbeResult)
{
Map<String, Object> list = rmMtrProbeResultService.getLossRateByMtrClientId(rmMtrProbeResult);
return success(list);
}
}
@@ -0,0 +1,139 @@
package com.tongran.mtragent.controller;
import com.tongran.common.security.annotation.InnerAuth;
import com.tongran.mtragent.producer.MessageProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 消息测试类Controller
*/
@RestController
@RequestMapping("/api/rocketMessage")
public class RocketMqController {
/**
* 发送同步消息
*/
@PostMapping("/sendSynchronizeMessage")
private Map sendSynchronizeMessage(){
MessageProducer messageProducer = new MessageProducer();
//调用MessageProducer配置好的消息方法
SendResult sendResult = messageProducer.sendSynchronizeMessage("order-message","order_message_tag","title","content");
Map<String,Object> result = new HashMap<>();
result.put("data",sendResult);
return result;
}
/**
* 发送单向消息
*/
@PostMapping("/sendOnewayMessage")
private Map sendOnewayMessage(@RequestParam("topic") String topic,@RequestParam("tag") String tag,@RequestParam("key") String key,@RequestParam("value") String value){
MessageProducer messageProducer = new MessageProducer();
//调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的
messageProducer.sendOnewayMessage("order-message","order_timeout_tag","title","content");
Map<String,Object> result = new HashMap<>();
result.put("msg","发送成功");
result.put("code",200);
return result;
}
/**
* 批量发送消息
*/
@PostMapping("/sendBatchMessage")
private Map sendBatchMessage(){
// 根据实际需求创建消息列表并返回
List<Message> messages = new ArrayList<>();
// 添加消息到列表
messages.add(new Message("order-message", "order_timeout_tag", "Message 1".getBytes()));
messages.add(new Message("order-message", "order_timeout_tag", "Message 2".getBytes()));
messages.add(new Message("order-message", "order_timeout_tag", "Message 3".getBytes()));
MessageProducer messageProducer = new MessageProducer();
//调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的
SendResult sendResult = messageProducer.sendBatchMessage(messages);
Map<String,Object> result = new HashMap<>();
result.put("data",sendResult);
return result;
}
/**
* 发送事物消息
*/
@PostMapping("/sendThingMessage")
private Map sendThingMessage(@RequestParam("topic") String topic,@RequestParam("tag") String tag,@RequestParam("key") String key,@RequestParam("value") String value){
MessageProducer messageProducer = new MessageProducer();
//调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的
SendResult sendResult = messageProducer.sendThingMessage("order-message","order_timeout_tag","title","content");
Map<String,Object> result = new HashMap<>();
result.put("data",sendResult);
return result;
}
/**
* 发送有序的消息
*/
@PostMapping("/sendOrderlyMessage")
private Map sendOrderlyMessage(){
// 根据实际需求创建消息列表并返回
List<Message> messages = new ArrayList<>();
// 添加消息到列表
messages.add(new Message("order-message", "order_timeout_tag", "Message 1".getBytes()));
messages.add(new Message("order-message", "order_timeout_tag", "Message 2".getBytes()));
messages.add(new Message("order-message", "order_timeout_tag", "Message 3".getBytes()));
Integer messageQueueNumber = 3;
MessageProducer messageProducer = new MessageProducer();
//调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的
SendResult sendResult = messageProducer.sendOrderlyMessage(messages,messageQueueNumber);
Map<String,Object> result = new HashMap<>();
result.put("data",sendResult);
return result;
}
/**
* 发送延迟消息
*/
@PostMapping("/sendDelayMessage")
private Map sendDelayMessage(@RequestParam("topic") String topic,@RequestParam("tag") String tag,@RequestParam("key") String key,@RequestParam("value") String value){
MessageProducer messageProducer = new MessageProducer();
//调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的
SendResult sendResult = messageProducer.sendDelayMessage("order-message","order_timeout_tag","title","content",4);
Map<String,Object> result = new HashMap<>();
result.put("data",sendResult);
return result;
}
/**
* 发送异步的消息
*/
@InnerAuth
@PostMapping("/sendAsyncProducerMessage")
private Map sendAsyncProducerMessage(@RequestParam("topic") String topic,@RequestParam("tag") String tag,@RequestParam("key") String key,@RequestParam("value") String value){
MessageProducer messageProducer = new MessageProducer();
//调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的
SendResult sendResult = messageProducer.sendAsyncProducerMessage(topic,tag,key,value);
Map<String,Object> result = new HashMap<>();
result.put("data",sendResult);
return result;
}
}
@@ -0,0 +1,86 @@
package com.tongran.mtragent.domain;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.tongran.common.core.annotation.Excel;
import com.tongran.common.core.web.domain.BaseEntity;
/**
* mtr探测丢包clinetId记录对象 all_mtr_client
*
* @author gyt
* @date 2025-11-24
*/
public class AllMtrClient extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** MTR客户端ID */
@Excel(name = "MTR客户端ID")
private String mtrClientId;
/** 客户端ID */
@Excel(name = "客户端ID")
private String clientId;
/** 公网IP地址 */
@Excel(name = "公网IP地址")
private String publicIp;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setMtrClientId(String mtrClientId)
{
this.mtrClientId = mtrClientId;
}
public String getMtrClientId()
{
return mtrClientId;
}
public void setClientId(String clientId)
{
this.clientId = clientId;
}
public String getClientId()
{
return clientId;
}
public void setPublicIp(String publicIp)
{
this.publicIp = publicIp;
}
public String getPublicIp()
{
return publicIp;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("mtrClientId", getMtrClientId())
.append("clientId", getClientId())
.append("publicIp", getPublicIp())
.append("createTime", getCreateTime())
.append("updateTime", getUpdateTime())
.append("createBy", getCreateBy())
.append("updateBy", getUpdateBy())
.toString();
}
}
@@ -0,0 +1,10 @@
package com.tongran.mtragent.domain;
import lombok.Data;
@Data
public class DeviceMessage {
private String clientId;
private String dataType;
private String data;
}
@@ -0,0 +1,37 @@
package com.tongran.mtragent.domain;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.tongran.common.core.annotation.Excel;
import com.tongran.common.core.web.domain.BaseEntity;
import lombok.Data;
/**
* 心跳信息对象 initial_heartbeat_listen
*
* @author gyt
* @date 2025-09-08
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class InitialHeartbeatListen extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 客户端ID */
private String clientId;
/** 节点 */
private String logicalNode;
/** sn */
private String sn;
/** 强度值 */
@Excel(name = "强度值")
private Long strength;
/** 服务名称 */
private String name;
/** 版本 */
private String version;
/** 服务启动时间 */
private Long startupTime;
}
@@ -0,0 +1,25 @@
package com.tongran.mtragent.domain;
import com.tongran.common.core.annotation.Excel;
import com.tongran.common.core.web.domain.BaseEntity;
import lombok.Data;
/**
* 心跳信息日志对象 initial_heartbeat_listen_log
*
* @author gyt
* @date 2025-09-08
*/
@Data
public class InitialHeartbeatListenLog extends BaseEntity
{
private static final long serialVersionUID = 1L;
private Long id;
/** 客户端ID */
private String clientId;
/** 状态0-正常 1-恢复 2-两次丢失 3-三次丢失 */
@Excel(name = "状态0-正常 1-恢复 2-两次丢失 3-三次丢失")
private String status;
}
@@ -0,0 +1,34 @@
package com.tongran.mtragent.domain;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tongran.system.api.domain.NetworkInfo;
import java.io.IOException;
import java.util.List;
public class NetworkInfoDeserializer extends JsonDeserializer<List<NetworkInfo>> {
// 添加无参构造函数(Jackson 需要)
public NetworkInfoDeserializer() {
}
@Override
public List<NetworkInfo> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
ObjectMapper mapper = (ObjectMapper) p.getCodec();
JsonNode node = mapper.readTree(p);
// 如果 networkInfo 是字符串(如日志中的情况),先解析字符串
if (node.isTextual()) {
String jsonStr = node.textValue();
return mapper.readValue(jsonStr, new TypeReference<List<NetworkInfo>>() {});
}
// 如果 networkInfo 是数组,直接解析
else if (node.isArray()) {
return mapper.readValue(node.traverse(), new TypeReference<List<NetworkInfo>>() {});
}
throw new IOException("Invalid networkInfo format");
}
}
@@ -0,0 +1,86 @@
package com.tongran.mtragent.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.tongran.common.core.annotation.Excel;
import com.tongran.common.core.web.domain.BaseEntity;
import lombok.Data;
import java.util.Date;
/**
* Agent管理对象 rm_agent_management
*
* @author gyt
* @date 2025-09-15
*/
@Data
public class RmAgentManagement extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 硬件SN码 */
@Excel(name = "硬件SN码")
private String hardwareSn;
/** 资源名称 */
@Excel(name = "资源名称")
private String resourceName;
/** 内网IP地址 */
@Excel(name = "内网IP地址")
private String internalIp;
/** Agent状态:0-离线,1-在线,2-异常 */
@Excel(name = "Agent状态:0-离线,1-在线,2-异常")
private String status;
/** Agent版本号 */
@Excel(name = "Agent版本号")
private String agentVersion;
/** 执行方式 */
@Excel(name = "执行方式")
private Integer method;
/** 定时更新时间(cron表达式) */
@Excel(name = "定时更新时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date scheduledUpdateTime;
/** 文件地址格式 */
@Excel(name = "文件地址格式")
private Long fileUrlType;
/** 文件地址 */
@Excel(name = "文件地址")
private String fileUrl;
/** 文件目录 */
@Excel(name = "文件目录")
private String fileDirectory;
/** 最后一次更新结果(success/failure */
@Excel(name = "最后一次更新结果", readConverterExp = "s=uccess/failure")
private String lastUpdateResult;
/** 最后一次更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "最后一次更新时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date lastUpdateTime;
/** 生效服务器id */
private String includeIds;
/** 生效服务器名称 */
private String includeNames;
/** 查询条件名称 */
private String queryName;
/** 文件MD5 */
private String fileMd5;
/** 客户端id */
private String clientId;
/** 部署设备 */
private String deployDevice;
/** 管理网公网Ip */
private String managePublicIp;
}
@@ -0,0 +1,44 @@
package com.tongran.mtragent.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.tongran.common.core.annotation.Excel;
import com.tongran.common.core.web.domain.BaseEntity;
import lombok.Data;
import java.util.Date;
/**
* 客户端告警信息对象 rm_alarm_log
*
* @author gyt
* @date 2025-11-10
*/
@Data
public class RmAlarmLog extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 客户端ID */
@Excel(name = "客户端ID")
private String clientId;
/** 告警时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "告警时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date alarmTime;
/** 管理网-公网IP */
@Excel(name = "管理网-公网IP")
private String mgmPublicIp;
/** 告警类型 */
@Excel(name = "告警类型")
private String alarmType;
/** 告警内容 */
@Excel(name = "告警内容")
private String alarmContent;
}
@@ -0,0 +1,44 @@
package com.tongran.mtragent.domain;
import com.tongran.common.core.annotation.Excel;
import com.tongran.common.core.web.domain.BaseEntity;
import lombok.Data;
/**
* 告警推送配置对象 rm_alarm_push_config
*
* @author gyt
* @date 2025-11-11
*/
@Data
public class RmAlarmPushConfig extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 配置名称 */
@Excel(name = "配置名称")
private String configName;
/** 推送方式 */
@Excel(name = "推送方式")
private String pushMethod;
/** 推送地址 */
@Excel(name = "推送地址")
private String pushAddress;
/** 推送告警类型 */
@Excel(name = "推送告警类型")
private String pushAlarmTypes;
/** 消息内容 */
@Excel(name = "消息内容")
private String messageContent;
/** 消息提示人手机号 */
@Excel(name = "消息提示人手机号")
private String contactPhones;
}
@@ -0,0 +1,92 @@
package com.tongran.mtragent.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.tongran.common.core.annotation.Excel;
import com.tongran.common.core.web.domain.BaseEntity;
import lombok.Data;
import java.util.Date;
/**
* MTR客户端注册对象 rm_mtr_client_registration
*
* @author gyt
* @date 2025-11-18
*/
@Data
public class RmMtrClientRegistration extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** MTR客户端ID */
@Excel(name = "MTR客户端ID")
private String mtrClientId;
/** 描述 */
@Excel(name = "描述")
private String description;
/** 版本 */
@Excel(name = "版本")
private String version;
/** 标识 */
@Excel(name = "标识")
private String logicalNode;
/** 注册时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "注册时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date registerTime;
/** 注册状态(0-未注册,1-已注册) */
@Excel(name = "注册状态(0-未注册,1-已注册)")
private String registerStatus;
/** 在线状态(0-离线,1-在线) */
@Excel(name = "在线状态(0-离线,1-在线)")
private String onlineStatus;
/** 心跳时间间隔(秒) */
@Excel(name = "心跳时间间隔(秒)")
private Integer heartbeatInterval;
/** 心跳次数 */
@Excel(name = "心跳次数")
private Integer heartbeatCount;
/** 更新方式 */
@Excel(name = "更新方式")
private String method;
/** 定时更新时间 */
@Excel(name = "定时更新时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date scheduledUpdateTime;
/** 文件地址 */
@Excel(name = "文件地址")
private String filePath;
/** 文件MD5值 */
@Excel(name = "文件MD5值")
private String fileMd5;
/** 最后一次更新结果 */
@Excel(name = "最后一次更新结果")
private String lastUpdateResult;
/** 最后一次更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "最后一次更新时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date lastUpdateTime;
/** 网卡信息(JSON格式) */
@Excel(name = "网卡信息(JSON格式)")
private String networkInfo;
/** 部署设备 */
private String mtrClientIds;
}
@@ -0,0 +1,63 @@
package com.tongran.mtragent.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.tongran.common.core.annotation.Excel;
import com.tongran.common.core.web.domain.BaseEntity;
import lombok.Data;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* mtr探测策略配置对象 rm_mtr_policy_config
*
* @author gyt
* @date 2025-11-18
*/
@Data
public class RmMtrPolicyConfig extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 策略名称 */
@Excel(name = "策略名称")
private String policyName;
/** 优先级 */
@Excel(name = "优先级")
private Long priority;
/** MTR客户端ID */
@Excel(name = "MTR客户端ID")
private String mtrClientId;
/** 服务器集合(换行符分割) */
@Excel(name = "服务器集合(换行符分割)")
private String serverGroup;
/** 探测目标ip集合 */
private String serveripGroup;
/** 是否探测(0-否,1-是) */
@Excel(name = "是否探测(0-否,1-是)")
private Long probeFlag;
/** 开始时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
/** 结束时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "结束时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
/** 探测频率(秒) */
@Excel(name = "探测频率(秒)")
private Long probeFrequency;
/** clientId和ip对应集合 */
private Map<String, List<String>> clientIdToIpsMap;
}
@@ -0,0 +1,50 @@
package com.tongran.mtragent.domain;
import com.tongran.common.core.annotation.Excel;
import com.tongran.common.core.web.domain.BaseEntity;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
* 网络mtr探测结果对象 rm_mtr_probe_result
*
* @author gyt
* @date 2025-11-20
*/
@Data
public class RmMtrProbeResult extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** MTR客户端ID */
@Excel(name = "MTR客户端ID")
private String mtrClientId;
/** 客户端ID */
@Excel(name = "客户端ID")
private String clientId;
/** 公网IP地址 */
@Excel(name = "公网IP地址")
private String publicIp;
/** 丢包率(%) */
@Excel(name = "丢包率(%)")
private BigDecimal packetLossRate;
/** 表名 */
private String tableName;
/** 批量新增集合 */
private List<RmMtrProbeResult> list;
/** 开始时间 */
private String startTime;
/** 结束时间 */
private String endTime;
}
@@ -0,0 +1,65 @@
package com.tongran.mtragent.domain;
import com.tongran.common.core.annotation.Excel;
import com.tongran.common.core.web.domain.BaseEntity;
import lombok.Data;
/**
* 客户端网络接口信息对象 rm_network_interface
*
* @author gyt
* @date 2025-10-14
*/
@Data
public class RmNetworkInterface extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 客户端ID */
@Excel(name = "客户端ID")
private String clientId;
/** 运营商 */
@Excel(name = "运营商")
private String isp;
/** 省 */
@Excel(name = "")
private String province;
/** 市 */
@Excel(name = "")
private String city;
/** 公网IP */
@Excel(name = "公网IP")
private String publicIp;
/** 接口名称 */
@Excel(name = "接口名称")
private String interfaceName;
/** MAC地址 */
@Excel(name = "MAC地址")
private String macAddress;
/** 接口类型 */
@Excel(name = "接口类型")
private String interfaceType;
/** IPv4地址 */
@Excel(name = "IPv4地址")
private String ipv4Address;
/** 网关 */
@Excel(name = "网关")
private String gateway;
/** 绑定ip 1业务IP2管理ip */
private String bindIp;
/** 是否为新信息 */
private Integer newFlag;
}
@@ -0,0 +1,15 @@
package com.tongran.mtragent.domain.vo;
import lombok.Data;
@Data
public class AgentUpdateMsgVo {
/**文件地址,外网HTTP(S)地址 */
private String fileUrl;
/** 文件MD5 */
private String fileMd5;
/** 执行方式:0、立即执行;1、定时执行; */
private Integer method;
/** 定时时间,执行方式为1、定时执行时该字段必传 */
private long policyTime;
}
@@ -0,0 +1,13 @@
package com.tongran.mtragent.domain.vo;
import lombok.Data;
@Data
public class MessageVo {
private String clientId;
private String dataType;
private String data;
}
@@ -0,0 +1,16 @@
package com.tongran.mtragent.domain.vo;
import lombok.Data;
@Data
public class MtrResultVo {
private String targetIp; // 目标IP
private String clientId; // 目标IP
private Long policyId; // 策略ID
private double firstLossPercent; // 第一次探测丢包率
private double finalLossPercent; // 最终丢包率
private long timestamp; // 探测时间戳
private boolean hasRetry; // 是否重试
private String errorMsg; // 错误信息
}
@@ -0,0 +1,22 @@
package com.tongran.mtragent.domain.vo;
import lombok.Data;
import java.time.Instant;
@Data
public class PolicyTypeVo {
/** 服务器监控策略信息 */
private String monitors;
/** 服务器脚本策略信息 */
private String scripts;
/** agent更新信息 */
private String versions;
/** 路由信息 */
private String routes;
/** mtr策略 */
private String mtrPolicys;
/** 时间戳 */
private Long timestamp = Instant.now().getEpochSecond();
}
@@ -0,0 +1,14 @@
package com.tongran.mtragent.domain.vo;
import lombok.Data;
import java.time.Instant;
import java.util.List;
@Data
public class PolicyVo<T> {
/** 更新时间戳 */
private Long upTime = Instant.now().getEpochSecond();
/** 更新内容 */
private List<T> contents;
}
@@ -0,0 +1,26 @@
package com.tongran.mtragent.domain.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.tongran.mtragent.domain.NetworkInfoDeserializer;
import com.tongran.system.api.domain.NetworkInfo;
import lombok.Data;
import java.util.List;
@Data
public class RegisterMsgVo {
@JsonProperty("clientId")
private String clientId;
@JsonProperty("sn")
private String sn;
@JsonProperty("networkInfo")
@JsonDeserialize(using = NetworkInfoDeserializer.class)
private List<NetworkInfo> networkInfo;
@JsonProperty("timestamp")
private long timestamp;
}
@@ -0,0 +1,29 @@
package com.tongran.mtragent.domain.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.time.Instant;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class RspVo {
/**
* 状态码,0、失败;1、成功
*/
private Integer resCode;
/**
* 描述
*/
private String resMag;
/**
* 描述
*/
private String resMsg;
private String result;
/**
* 时间戳
*/
private Long timestamp = Instant.now().getEpochSecond();
}
@@ -0,0 +1,16 @@
package com.tongran.mtragent.enums;
import lombok.Getter;
@Getter
public enum AlarmTypeEnum {
服务器下线("1", "服务器下线"),
交换机下线("2", "交换机下线"),
mtrAgent下线("3", "mtrAgent下线");
private final String code;
private final String msg;
AlarmTypeEnum(String code, String msg){
this.code = code;
this.msg = msg;
}
}
@@ -0,0 +1,67 @@
package com.tongran.mtragent.enums;
import lombok.Getter;
/**
* 用于传递topic和 tag
* 也用于接收消息后判断不同的消息处理不同的业务
*/
@Getter
public enum MessageCodeEnum {
/**
* agent数据采集的信息
*/
AGENT_MESSAGE_TOPIC("agent_up","agent数据采集的信息topic"),
TONGRAN_AGENT_UP("tongran_agent_up","agent数据采集的信息topic"),
TR_AGENT_UP("tr_agent_up","agent数据采集的信息topic v1.1"),
TR_MTRAGENT_UP("tr_mtragent_up","mtragent监测丢包率的信息topic"),
/**
* 系统消息
*/
NOTE_MESSAGE_TOPIC("system-message","系统消息服务模块topic名称"),
/**
* 用户消息
*/
USER_MESSAGE_TOPIC("user-message","用户消息服务模块topic名称"),
/**
* 订单消息
*/
ORDER_MESSAGE_TOPIC("order-message","订单消息服务模块topic名称"),
/**
* 用户消息tag
*/
USER_MESSAGE_TAG("user_message_tag","用户消息推送"),
/**
* 系统消息tag
*/
NOTE_MESSAGE_TAG("system_message_tag","系统消息推送"),
/**
* 订单消息
*/
ORDER_MESSAGE_TAG("order_message_tag","订单消息推送"),
/**
* 订单处理编号
*/
ORDER_TIMEOUT_TAG("order_timeout_tag","订单超时处理");
private final String code;
private final String msg;
MessageCodeEnum(String code, String msg){
this.code = code;
this.msg = msg;
}
}
@@ -0,0 +1,21 @@
package com.tongran.mtragent.enums;
import java.util.ArrayList;
import java.util.List;
/**
* 定义topic列表
*/
public class MessageTopic {
//在这里添加topic 用于批量订阅
public List<String> RocketMQTopicList(){
List<String> getTopicLists=new ArrayList<>();
// agent采集消息
// getTopicLists.add("agent_up");
getTopicLists.add("tr_mtragent_up");
return getTopicLists;
}
}
@@ -0,0 +1,14 @@
package com.tongran.mtragent.enums;
import lombok.Getter;
@Getter
public enum PushMethodEnum {
企业微信("1", "企业微信");
private final String code;
private final String msg;
PushMethodEnum(String code, String msg){
this.code = code;
this.msg = msg;
}
}
@@ -0,0 +1,21 @@
package com.tongran.mtragent.enums;
import lombok.Getter;
@Getter
public enum ServerLogoEnum {
交换卷文件的可用空间("systemSwapSizeFreeCollect", "交换卷/文件的可用空间(字节)"),
内存利用率("memoryUtilizationCollect", "内存利用率"),
可用交换空间百分比("systemSwapSizePercentCollect", "可用交换空间百分比"),
可用内存("memorySizeAvailableCollect", "可用内存"),
可用内存百分比("memorySizePercentCollect", "可用内存百分比"),
正在运行的进程数("procNumRunCollect", "正在运行的进程数"),
登录用户数("systemUsersNumCollect", "登录用户数"),
进程数("procNumCollect", "进程数");
private final String code;
private final String msg;
ServerLogoEnum(String code, String msg){
this.code = code;
this.msg = msg;
}
}
@@ -0,0 +1,17 @@
package com.tongran.mtragent.enums;
import lombok.Getter;
@Getter
public enum SwitchLogo {
设备CPU使用率("hwEntityCpuUsage", "设备CPU使用率"),
设备内存使用率("hwEntityMemUsage", "设备内存使用率(%)"),
系统平均功率("hwAveragePower", "系统平均功率(%)"),
系统实时功率("hwCurrentPower", "系统实时功率(%)");
private final String code;
private final String msg;
SwitchLogo(String code, String msg){
this.code = code;
this.msg = msg;
}
}
@@ -0,0 +1,588 @@
package com.tongran.mtragent.handler;
import com.alibaba.fastjson.JSONObject;
import com.tongran.common.core.enums.MsgEnum;
import com.tongran.common.core.utils.DateUtils;
import com.tongran.common.core.utils.StringUtils;
import com.tongran.mtragent.domain.*;
import com.tongran.mtragent.domain.vo.*;
import com.tongran.mtragent.enums.AlarmTypeEnum;
import com.tongran.mtragent.enums.PushMethodEnum;
import com.tongran.mtragent.model.ProducerMode;
import com.tongran.mtragent.producer.MessageProducer;
import com.tongran.mtragent.service.*;
import com.tongran.mtragent.utils.JsonDataParser;
import com.tongran.mtragent.utils.WeChatWorkBot;
import com.tongran.system.api.domain.NetworkInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Consumer;
/**
* 设备消息处理器
*/
@Slf4j
@Component
@EnableScheduling
public class MessageHandler {
private final Map<String, Consumer<DeviceMessage>> messageHandlers = new HashMap<>();
// 心跳状态
private static final String HEARTBEAT_STATUS_PREFIX = "mtr:heartbeat:status:";
// 心跳时间
private static final String HEARTBEAT_TIME_PREFIX = "mtr:heartbeat:time:";
// 心跳告警
private static final String HEARTBEAT_ALERT_PREFIX = "mtr:heartbeat:alert:";
String HEARTBEAT_RECOVERY_COUNT_PREFIX = "mtr:heartbeat:recovery:count:";
String HEARTBEAT_COUNT_PREFIX = "mtr:heartbeat:count:";
private static final long HEARTBEAT_TIMEOUT = 30000; // 3分钟超时
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private IRmAlarmPushConfigService rmAlarmPushConfigService;
@Autowired
private IRmAlarmLogService rmAlarmLogService;
@Autowired
private IInitialHeartbeatListenLogService initialHeartbeatListenLogService;
@Autowired
private IRmMtrClientRegistrationService rmMtrClientRegistrationService;
@Autowired
private IRmMtrPolicyConfigService rmMtrPolicyConfigService;
@Autowired
private ProducerMode producerMode;
@Autowired
private IRmMtrProbeResultService rmMtrProbeResultService;
@Autowired
private IAllMtrClientService allMtrClientService;
/**
* 初始化处理器映射
*/
@PostConstruct
public void init() {
registerHandler(MsgEnum.Agent版本更新应答.getValue(), this::handleAgentUpdateRspMessage);
// 其他类型消息可以单独注册处理器
registerHandler(MsgEnum.注册.getValue(), this::handleRegisterMessage);
registerHandler(MsgEnum.获取最新策略.getValue(), this::handleNewPolicyMessage);
registerHandler(MsgEnum.心跳上报.getValue(), this::handleHeartbeatMessage);
registerHandler(MsgEnum.多公网IP探测.getValue(), this::handleNetWorkDelectMessage);
registerHandler(MsgEnum.MTR探测上报.getValue(), this::handleMtrDelectMessage);
}
private void handleMtrDelectMessage(DeviceMessage message) {
List<MtrResultVo> mtrResultVoList = JsonDataParser.parseJsonData(message.getData(), MtrResultVo.class);
if(mtrResultVoList != null && !mtrResultVoList.isEmpty()){
String mtrClientId = message.getClientId();
List<RmMtrProbeResult> rmMtrProbeResultList = new ArrayList<>();
List<AllMtrClient> allMtrClientList = new ArrayList<>();
for (MtrResultVo mtrResultVo : mtrResultVoList) {
if(mtrResultVo.getFinalLossPercent() != -1.0){
// 时间戳转换
long timestamp = mtrResultVo.getTimestamp();
long millis = timestamp * 1000;
Date createTime = new Date(millis / 1000 * 1000); // 去除毫秒
RmMtrProbeResult rmMtrProbeResult = new RmMtrProbeResult();
rmMtrProbeResult.setCreateTime(createTime);
rmMtrProbeResult.setClientId(mtrResultVo.getClientId());
rmMtrProbeResult.setMtrClientId(mtrClientId);
rmMtrProbeResult.setPublicIp(mtrResultVo.getTargetIp());
rmMtrProbeResult.setPacketLossRate(new BigDecimal(mtrResultVo.getFinalLossPercent()));
rmMtrProbeResultList.add(rmMtrProbeResult);
AllMtrClient allMtrClient = new AllMtrClient();
BeanUtils.copyProperties(rmMtrProbeResult, allMtrClient);
allMtrClientList.add(allMtrClient);
}else{
log.debug("探测失败,失败原因:{}", mtrResultVo.getErrorMsg());
}
}
RmMtrProbeResult insertData = new RmMtrProbeResult();
insertData.setList(rmMtrProbeResultList);
// 结果批量入库
rmMtrProbeResultService.batchInsertRmMtrProbeResult(insertData);
// 记录下发策略的clientId
allMtrClientService.batchInsertAllMtrClient(allMtrClientList);
}
}
private void handleRegisterMessage(DeviceMessage message) {
MessageProducer messageProducer = new MessageProducer();
List<RegisterMsgVo> interfaces = JsonDataParser.parseJsonData(message.getData(), RegisterMsgVo.class);
if(!interfaces.isEmpty()) {
String clientId = message.getClientId();
RegisterMsgVo registerMsg = interfaces.get(0);
// 时间戳转换
long timestamp = registerMsg.getTimestamp();
long millis = timestamp * 1000;
Date createTime = new Date(millis / 1000 * 1000); // 去除毫秒
String timeStr = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", createTime);
List<NetworkInfo> networkInfoList = registerMsg.getNetworkInfo();
if(!networkInfoList.isEmpty()){
RmMtrClientRegistration rmMtrClientRegistrationQuery = new RmMtrClientRegistration();
rmMtrClientRegistrationQuery.setMtrClientId(clientId);
List<RmMtrClientRegistration> mtrClientRegistrationList = rmMtrClientRegistrationService.selectRmMtrClientRegistrationList(rmMtrClientRegistrationQuery);
if(mtrClientRegistrationList == null || mtrClientRegistrationList.isEmpty()){
// 构建mtrClient信息
RmMtrClientRegistration insertData = new RmMtrClientRegistration();
try {
insertData.setMtrClientId(registerMsg.getClientId());
insertData.setRegisterStatus("1");
insertData.setHeartbeatCount(3);
insertData.setHeartbeatInterval(30);
insertData.setCreateTime(createTime);
insertData.setRegisterTime(createTime);
insertData.setNetworkInfo(JSONObject.toJSONString(networkInfoList));
rmMtrClientRegistrationService.insertRmMtrClientRegistration(insertData);
// 构建注册应答信息
MessageVo messageVo = new MessageVo();
messageVo.setClientId(registerMsg.getClientId());
messageVo.setDataType(MsgEnum.注册应答.getValue());
RspVo rspVo = new RspVo();
rspVo.setResCode(1);
rspVo.setResMag("注册成功");
messageVo.setData(JSONObject.toJSONString(rspVo));
messageProducer.sendAsyncProducerMessage(
"tr_mtragent_down", "", "mtrregist_rsp", JSONObject.toJSONString(messageVo)
);
}catch (Exception e){
log.error("注册服务器失败:{}",e.getMessage());
}
}
}
}
}
/**
* agent更新响应
* @param message
*/
private void handleAgentUpdateRspMessage(DeviceMessage message) {
List<RspVo> rspVoList = JsonDataParser.parseJsonData(message.getData(), RspVo.class);
if (!rspVoList.isEmpty()) {
RspVo rsp = rspVoList.get(0);
if(rsp.getResCode() == 1){
RmMtrClientRegistration rmMtrClientRegistration = new RmMtrClientRegistration();
rmMtrClientRegistration.setMtrClientId(message.getClientId());
rmMtrClientRegistration.setLastUpdateResult("1");
rmMtrClientRegistration.setLastUpdateTime(DateUtils.getNowDate());
rmMtrClientRegistrationService.updateRmMtrClientRegistration(rmMtrClientRegistration);
}else{
RmMtrClientRegistration rmMtrClientRegistration = new RmMtrClientRegistration();
rmMtrClientRegistration.setMtrClientId(message.getClientId());
rmMtrClientRegistration.setDescription(rsp.getResMag());
rmMtrClientRegistration.setLastUpdateResult("0");
rmMtrClientRegistration.setLastUpdateTime(DateUtils.getNowDate());
rmMtrClientRegistrationService.updateRmMtrClientRegistration(rmMtrClientRegistration);
}
}
}
/**
* 注册消息处理器
*/
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);
}
}
// ========== 具体的消息处理方法 ==========
/**
* 获取最新策略
* @param deviceMessage
*/
private void handleNewPolicyMessage(DeviceMessage deviceMessage) {
MessageProducer messageProducer = new MessageProducer();
List<RegisterMsgVo> interfaces = JsonDataParser.parseJsonData(deviceMessage.getData(), RegisterMsgVo.class);
if(!interfaces.isEmpty()) {
RegisterMsgVo registerMsgVo = interfaces.get(0);
String mtrClientId = registerMsgVo.getClientId();
List<RmMtrPolicyConfig> mtrPolicyConfigList = rmMtrPolicyConfigService.getPoliciesForMtrClient(mtrClientId);
if(mtrPolicyConfigList != null && !mtrPolicyConfigList.isEmpty()){
// 构建mtrclient消息
String mtrPolicyListStr = JSONObject.toJSONString(mtrPolicyConfigList);
PolicyTypeVo policyTypeVo = new PolicyTypeVo();
policyTypeVo.setMtrPolicys(mtrPolicyListStr);
String configJson = JSONObject.toJSONString(policyTypeVo);
try {
DeviceMessage message = new DeviceMessage();
message.setClientId(mtrClientId);
message.setData(configJson);
message.setDataType(MsgEnum.获取最新策略应答.getValue());
messageProducer.sendAsyncProducerMessage(
producerMode.getAgentTopic(),
"",
"",
JSONObject.toJSONString(message)
);
} catch (Exception e) {
log.error("发送mtr策略失败,mtrClientId: {}", mtrClientId, e);
}
}
}
}
/**
* 监听心跳
* @param message
*/
private void handleHeartbeatMessage(DeviceMessage message) {
List<InitialHeartbeatListen> heartbeats = JsonDataParser.parseJsonData(message.getData(), InitialHeartbeatListen.class);
if(!heartbeats.isEmpty()){
InitialHeartbeatListen heartbeat = heartbeats.get(0);
String clientId = message.getClientId();
String version = heartbeat.getVersion();
String name = heartbeat.getName();
log.debug("处理心跳消息,客户端ID: {}, 时间: {}", clientId, heartbeat.getTimestamp());
// 使用Redis存储状态
String statusKey = HEARTBEAT_STATUS_PREFIX + clientId;
String timeKey = HEARTBEAT_TIME_PREFIX + clientId;
String recoveryCountKey = HEARTBEAT_RECOVERY_COUNT_PREFIX + clientId;
String heartbeatCountKey = HEARTBEAT_COUNT_PREFIX + clientId;
String alertKey = HEARTBEAT_ALERT_PREFIX + clientId;
try {
// 记录处理前状态(调试用)
String prevStatus = redisTemplate.opsForValue().get(statusKey);
String prevTime = redisTemplate.opsForValue().get(timeKey);
String prevHeartbeatCount = redisTemplate.opsForValue().get(heartbeatCountKey);
Boolean prevAlertStatus = redisTemplate.hasKey(alertKey);
log.debug("客户端ID: {} 处理前状态 - status: {}, time: {}, heartbeatCount: {}, hasAlert: {}",
clientId, prevStatus, prevTime, prevHeartbeatCount, prevAlertStatus);
// 原子递增心跳计数(线程安全)
Long newHeartbeatCount = redisTemplate.opsForValue().increment(heartbeatCountKey);
// 使用事务更新状态和时间
redisTemplate.execute(new SessionCallback<Object>() {
@Override
public Object execute(RedisOperations operations) throws DataAccessException {
operations.multi();
// 重置丢失计数为0,设置最后心跳时间
operations.opsForValue().set(statusKey, "0");
operations.opsForValue().set(timeKey, String.valueOf(System.currentTimeMillis()));
return operations.exec();
}
});
log.debug("客户端ID: {} 心跳处理完成,当前心跳次数: {}", clientId, newHeartbeatCount);
// 检查是否之前有告警状态(心跳恢复检测)
if (Boolean.TRUE.equals(redisTemplate.hasKey(alertKey))) {
log.info("客户端ID: {} 检测到心跳恢复", clientId);
// 原子递增恢复计数
Long recoveryCount = redisTemplate.opsForValue().increment(recoveryCountKey);
log.debug("客户端ID: {} 恢复计数: {}", clientId, recoveryCount);
if (recoveryCount >= 2) {
// 达到2次恢复,清除告警状态
log.warn("客户端ID: {} 心跳恢复达到{}次,清除告警状态", clientId, recoveryCount);
insertHeartbeatLog(clientId, "2", "心跳恢复,设备在线状态改为在线");
// 清理告警相关key
redisTemplate.delete(alertKey);
redisTemplate.delete(recoveryCountKey);
// 修改资源状态为在线
updateResourceStatus(clientId, "1");
log.info("客户端ID: {} 告警状态已清除", clientId);
} else {
// 未达到2次,只记录恢复次数
log.info("客户端ID: {} 心跳恢复第{}次", clientId, recoveryCount);
}
}
// 只有达到3次心跳才执行数据库操作
if (newHeartbeatCount >= 3) {
log.info("客户端ID: {} 达到{}次心跳,开始执行数据库操作", clientId, newHeartbeatCount);
// agent更新结果存储
RmMtrClientRegistration queryMtrClient = new RmMtrClientRegistration();
queryMtrClient.setMtrClientId(clientId);
List<RmMtrClientRegistration> mtrClientRegistrationList = rmMtrClientRegistrationService.selectRmMtrClientRegistrationList(queryMtrClient);
if(mtrClientRegistrationList != null && !mtrClientRegistrationList.isEmpty()){
RmMtrClientRegistration rmMtrClientRegistration = mtrClientRegistrationList.get(0);
boolean needUpdate = false;
RmMtrClientRegistration updateData = new RmMtrClientRegistration();
updateData.setId(rmMtrClientRegistration.getId());
if(rmMtrClientRegistration.getLogicalNode() == null ||
!StringUtils.equals(rmMtrClientRegistration.getLogicalNode(), heartbeat.getLogicalNode())){
updateData.setLogicalNode(heartbeat.getLogicalNode());
needUpdate = true;
}
if("0".equals(rmMtrClientRegistration.getOnlineStatus())){
updateData.setOnlineStatus("1");
needUpdate = true;
}
if(!StringUtils.equals(rmMtrClientRegistration.getVersion(), version)){
updateData.setVersion(version);
updateData.setLastUpdateTime(DateUtils.getNowDate());
updateData.setLastUpdateResult("1");
if(rmMtrClientRegistration.getMethod() == null){
updateData.setMethod("0");
}
needUpdate = true;
}
if(needUpdate){
rmMtrClientRegistrationService.updateRmMtrClientRegistration(updateData);
}
}
} else {
log.debug("客户端ID: {} 当前心跳次数: {},未达到3次,跳过数据库操作", clientId, newHeartbeatCount);
}
// 记录处理后状态(调试用)
String currentStatus = redisTemplate.opsForValue().get(statusKey);
String currentTime = redisTemplate.opsForValue().get(timeKey);
String currentHeartbeatCount = redisTemplate.opsForValue().get(heartbeatCountKey);
Boolean currentAlertStatus = redisTemplate.hasKey(alertKey);
log.debug("客户端ID: {} 处理后状态 - status: {}, time: {}, heartbeatCount: {}, hasAlert: {}",
clientId, currentStatus, currentTime, currentHeartbeatCount, currentAlertStatus);
} catch (Exception e) {
log.error("处理心跳消息异常, clientId: {}", clientId, e);
}
}
}
// 添加一个定时任务方法,定期检查心跳状态
@Scheduled(fixedRate = 60000) // 每60s检查一次
public void checkHeartbeatStatus() {
long currentTime = System.currentTimeMillis();
log.debug("开始心跳状态检查,当前时间: {}", currentTime);
// 获取所有客户端时间键
Set<String> timeKeys = redisTemplate.keys(HEARTBEAT_TIME_PREFIX + "*");
if (timeKeys == null) {
log.debug("未找到任何心跳时间键");
return;
}
log.debug("找到 {} 个客户端需要检查", timeKeys.size());
for (String timeKey : timeKeys) {
String clientId = timeKey.substring(HEARTBEAT_TIME_PREFIX.length());
String statusKey = HEARTBEAT_STATUS_PREFIX + clientId;
String alertKey = HEARTBEAT_ALERT_PREFIX + clientId;
String heartbeatCountKey = HEARTBEAT_COUNT_PREFIX + clientId;
try {
// 检查是否已经存在告警
String existingAlert = redisTemplate.opsForValue().get(alertKey);
if ("1".equals(existingAlert)) {
log.debug("客户端ID: {} 已有告警,跳过检查", clientId);
continue; // 如果已有告警,跳过处理
}
String lastTimeStr = redisTemplate.opsForValue().get(timeKey);
if (lastTimeStr == null) {
log.debug("客户端ID: {} 时间键为空,跳过", clientId);
continue;
}
long lastHeartbeatTime = Long.parseLong(lastTimeStr);
long timeDiff = currentTime - lastHeartbeatTime;
log.debug("客户端ID: {} 最后心跳: {}, 时间差: {}ms, 超时阈值: {}ms",
clientId, lastHeartbeatTime, timeDiff, HEARTBEAT_TIMEOUT);
if (timeDiff > HEARTBEAT_TIMEOUT) {
// 心跳超时处理 - 使用原子操作增加计数
Long lostCount = redisTemplate.opsForValue().increment(statusKey);
if (lostCount == 1) {
// 确保第一次增加时值为1
redisTemplate.opsForValue().set(statusKey, "1");
lostCount = 1L;
}
log.warn("客户端ID: {} 心跳超时,连续次数: {}, 时间差: {}ms",
clientId, lostCount, timeDiff);
if (lostCount >= 3) {
log.warn("客户端ID: {} 连续三次心跳丢失,触发告警", clientId);
insertHeartbeatLog(clientId, "3", "连续三次心跳丢失");
// 告警
insertAlarmRecords(clientId);
redisTemplate.opsForValue().set(HEARTBEAT_ALERT_PREFIX + clientId, "1");
// 设置告警后删除timeKey和statusKey
redisTemplate.delete(timeKey);
redisTemplate.delete(statusKey);
redisTemplate.delete(heartbeatCountKey);
log.info("客户端ID: {} 已设置告警并清理心跳记录", clientId);
// 修改资源状态
updateResourceStatus(clientId, "0");
}
} else {
// 如果心跳正常,重置丢失次数
String currentStatus = redisTemplate.opsForValue().get(statusKey);
if (!"0".equals(currentStatus)) {
redisTemplate.opsForValue().set(statusKey, "0");
log.debug("客户端ID: {} 心跳正常,重置丢失次数从 {} 到 0", clientId, currentStatus);
} else {
log.debug("客户端ID: {} 心跳正常,状态已是0", clientId);
}
}
} catch (Exception e) {
log.error("检查心跳状态异常, clientId: {}", clientId, e);
}
}
log.debug("心跳状态检查完成");
}
// 更新资源状态的公共方法
private void updateResourceStatus(String clientId, String status) {
log.info("开启更新资源状态========");
RmMtrClientRegistration updateData = new RmMtrClientRegistration();
updateData.setMtrClientId(clientId);
updateData.setOnlineStatus(status);
rmMtrClientRegistrationService.updateRmMtrClientRegistration(updateData);
}
// 插入心跳日志到数据库
private void insertHeartbeatLog(String machineId, String status, String remark) {
try {
InitialHeartbeatListenLog listenLog = new InitialHeartbeatListenLog();
listenLog.setClientId(machineId);
listenLog.setStatus(status); // 0-离线 1-在线 2-恢复 3-三次丢失
listenLog.setRemark(remark);
listenLog.setCreateTime(new Date());
// 调用DAO或Service插入日志
initialHeartbeatListenLogService.insertInitialHeartbeatListenLog(listenLog);
log.info("已记录心跳日志,客户端ID: {}, 状态: {}", machineId, status);
} catch (Exception e) {
log.error("插入心跳日志失败", e);
}
}
/**
* 添加告警日志并推送消息到企业微信
* @param clientId
*/
private void insertAlarmRecords(String clientId) {
// 创建告警日志记录
RmAlarmLog rmAlarmLog = createAlarmLog(clientId);
// 插入告警日志
rmAlarmLogService.insertRmAlarmLog(rmAlarmLog);
// 发送告警推送
sendAlarmPush(rmAlarmLog);
}
/**
* 创建告警日志记录
*/
private RmAlarmLog createAlarmLog(String clientId) {
RmAlarmLog rmAlarmLog = new RmAlarmLog();
String alarmContent = clientId + "下线";
rmAlarmLog.setClientId(clientId);
rmAlarmLog.setAlarmType("3");
rmAlarmLog.setAlarmContent(alarmContent);
rmAlarmLog.setAlarmTime(DateUtils.getNowDate());
return rmAlarmLog;
}
/**
* 发送告警推送
*/
private void sendAlarmPush(RmAlarmLog rmAlarmLog) {
String alarmTypeCode = AlarmTypeEnum.mtrAgent下线.getCode();
String alarmTypeMsg = AlarmTypeEnum.mtrAgent下线.getMsg();
RmAlarmPushConfig rmAlarmPushConfig = new RmAlarmPushConfig();
rmAlarmPushConfig.setPushMethod(PushMethodEnum.企业微信.getCode());
rmAlarmPushConfig.setPushAlarmTypes(alarmTypeCode);
List<RmAlarmPushConfig> alarmConfigList = rmAlarmPushConfigService.selectRmAlarmPushConfigList(rmAlarmPushConfig);
if (alarmConfigList != null && !alarmConfigList.isEmpty()) {
for (RmAlarmPushConfig alarmPushConfig : alarmConfigList) {
String contentTemplate = alarmPushConfig.getMessageContent();
String webhookUrl = alarmPushConfig.getPushAddress();
Map<String, Object> alarmMap = new HashMap<>();
alarmMap.put("告警时间", rmAlarmLog.getAlarmTime());
alarmMap.put("管理网-公网IP", rmAlarmLog.getMgmPublicIp());
alarmMap.put("告警类型", alarmTypeMsg);
alarmMap.put("告警设备", rmAlarmLog.getClientId());
alarmMap.put("告警内容", rmAlarmLog.getAlarmContent());
if (alarmPushConfig.getContactPhones() != null) {
String[] phones = alarmPushConfig.getContactPhones().split(",");
WeChatWorkBot.sendTemplateMessage(webhookUrl, contentTemplate, alarmMap, rmAlarmLog.getAlarmContent(), phones, false);
} else {
WeChatWorkBot.sendTemplateMessage(webhookUrl, contentTemplate, alarmMap);
}
}
}
}
/**
* 保存网卡信息
* @param message
*/
private void handleNetWorkDelectMessage(DeviceMessage message) {
List<RegisterMsgVo> interfaces = JsonDataParser.parseJsonData(message.getData(), RegisterMsgVo.class);
if(!interfaces.isEmpty()) {
String mtrClientId = message.getClientId();
RegisterMsgVo registerMsg = interfaces.get(0);
// 时间戳转换
long timestamp = registerMsg.getTimestamp();
long millis = timestamp * 1000;
Date createTime = new Date(millis / 1000 * 1000); // 去除毫秒
List<NetworkInfo> networkInfoList = registerMsg.getNetworkInfo();
if(!networkInfoList.isEmpty()){
String networkInfo = JSONObject.toJSONString(networkInfoList);
// 查询mtrClient信息
RmMtrClientRegistration rmMtrClientRegistration = new RmMtrClientRegistration();
rmMtrClientRegistration.setMtrClientId(mtrClientId);
List<RmMtrClientRegistration> mtrClientRegistrationList = rmMtrClientRegistrationService.selectRmMtrClientRegistrationList(rmMtrClientRegistration);
if(mtrClientRegistrationList != null && !mtrClientRegistrationList.isEmpty()){
RmMtrClientRegistration mtrClientRegistration = mtrClientRegistrationList.get(0);
// 如果网卡信息有变动,更新网卡信息
if(!networkInfo.equals(mtrClientRegistration.getNetworkInfo())){
RmMtrClientRegistration updateData = new RmMtrClientRegistration();
updateData.setId(mtrClientRegistration.getId());
updateData.setNetworkInfo(networkInfo);
rmMtrClientRegistrationService.updateRmMtrClientRegistration(updateData);
}
}
}
}
}
}
@@ -0,0 +1,69 @@
package com.tongran.mtragent.mapper;
import com.tongran.mtragent.domain.AllMtrClient;
import java.util.List;
/**
* mtr探测丢包clinetId记录Mapper接口
*
* @author gyt
* @date 2025-11-24
*/
public interface AllMtrClientMapper
{
/**
* 查询mtr探测丢包clinetId记录
*
* @param id mtr探测丢包clinetId记录主键
* @return mtr探测丢包clinetId记录
*/
public AllMtrClient selectAllMtrClientById(Long id);
/**
* 查询mtr探测丢包clinetId记录列表
*
* @param allMtrClient mtr探测丢包clinetId记录
* @return mtr探测丢包clinetId记录集合
*/
public List<AllMtrClient> selectAllMtrClientList(AllMtrClient allMtrClient);
/**
* 新增mtr探测丢包clinetId记录
*
* @param allMtrClient mtr探测丢包clinetId记录
* @return 结果
*/
public int insertAllMtrClient(AllMtrClient allMtrClient);
/**
* 修改mtr探测丢包clinetId记录
*
* @param allMtrClient mtr探测丢包clinetId记录
* @return 结果
*/
public int updateAllMtrClient(AllMtrClient allMtrClient);
/**
* 删除mtr探测丢包clinetId记录
*
* @param id mtr探测丢包clinetId记录主键
* @return 结果
*/
public int deleteAllMtrClientById(Long id);
/**
* 批量删除mtr探测丢包clinetId记录
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteAllMtrClientByIds(Long[] ids);
/**
* 批量新增
* @param allMtrClientList
* @return
*/
int batchInsertAllMtrClient(List<AllMtrClient> allMtrClientList);
}
@@ -0,0 +1,63 @@
package com.tongran.mtragent.mapper;
import com.tongran.mtragent.domain.InitialHeartbeatListenLog;
import java.util.List;
/**
* 心跳信息日志Mapper接口
*
* @author gyt
* @date 2025-09-08
*/
public interface InitialHeartbeatListenLogMapper
{
/**
* 查询心跳信息日志
*
* @param clientId 心跳信息日志主键
* @return 心跳信息日志
*/
public InitialHeartbeatListenLog selectInitialHeartbeatListenLogByClientId(String clientId);
/**
* 查询心跳信息日志列表
*
* @param initialHeartbeatListenLog 心跳信息日志
* @return 心跳信息日志集合
*/
public List<InitialHeartbeatListenLog> selectInitialHeartbeatListenLogList(InitialHeartbeatListenLog initialHeartbeatListenLog);
/**
* 新增心跳信息日志
*
* @param initialHeartbeatListenLog 心跳信息日志
* @return 结果
*/
public int insertInitialHeartbeatListenLog(InitialHeartbeatListenLog initialHeartbeatListenLog);
/**
* 修改心跳信息日志
*
* @param initialHeartbeatListenLog 心跳信息日志
* @return 结果
*/
public int updateInitialHeartbeatListenLog(InitialHeartbeatListenLog initialHeartbeatListenLog);
/**
* 删除心跳信息日志
*
* @param clientId 心跳信息日志主键
* @return 结果
*/
public int deleteInitialHeartbeatListenLogByClientId(String clientId);
/**
* 批量删除心跳信息日志
*
* @param clientIds 需要删除的数据主键集合
* @return 结果
*/
public int deleteInitialHeartbeatListenLogByClientIds(String[] clientIds);
}
@@ -0,0 +1,65 @@
package com.tongran.mtragent.mapper;
import com.tongran.mtragent.domain.RmAgentManagement;
import java.util.List;
/**
* Agent管理Mapper接口
*
* @author gyt
* @date 2025-09-15
*/
public interface RmAgentManagementMapper
{
/**
* 查询Agent管理
*
* @param id Agent管理主键
* @return Agent管理
*/
public RmAgentManagement selectRmAgentManagementById(Long id);
/**
* 查询Agent管理列表
*
* @param rmAgentManagement Agent管理
* @return Agent管理集合
*/
public List<RmAgentManagement> selectRmAgentManagementList(RmAgentManagement rmAgentManagement);
/**
* 新增Agent管理
*
* @param rmAgentManagement Agent管理
* @return 结果
*/
public int insertRmAgentManagement(RmAgentManagement rmAgentManagement);
/**
* 修改Agent管理
*
* @param rmAgentManagement Agent管理
* @return 结果
*/
public int updateRmAgentManagement(RmAgentManagement rmAgentManagement);
/**
* 删除Agent管理
*
* @param id Agent管理主键
* @return 结果
*/
public int deleteRmAgentManagementById(Long id);
/**
* 批量删除Agent管理
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteRmAgentManagementByIds(Long[] ids);
void updateRmAgentManagementBySn(RmAgentManagement rmAgentManagement);
}
@@ -0,0 +1,63 @@
package com.tongran.mtragent.mapper;
import com.tongran.mtragent.domain.RmAlarmLog;
import java.util.List;
/**
* 客户端告警信息Mapper接口
*
* @author gyt
* @date 2025-11-10
*/
public interface RmAlarmLogMapper
{
/**
* 查询客户端告警信息
*
* @param id 客户端告警信息主键
* @return 客户端告警信息
*/
public RmAlarmLog selectRmAlarmLogById(Long id);
/**
* 查询客户端告警信息列表
*
* @param rmAlarmLog 客户端告警信息
* @return 客户端告警信息集合
*/
public List<RmAlarmLog> selectRmAlarmLogList(RmAlarmLog rmAlarmLog);
/**
* 新增客户端告警信息
*
* @param rmAlarmLog 客户端告警信息
* @return 结果
*/
public int insertRmAlarmLog(RmAlarmLog rmAlarmLog);
/**
* 修改客户端告警信息
*
* @param rmAlarmLog 客户端告警信息
* @return 结果
*/
public int updateRmAlarmLog(RmAlarmLog rmAlarmLog);
/**
* 删除客户端告警信息
*
* @param id 客户端告警信息主键
* @return 结果
*/
public int deleteRmAlarmLogById(Long id);
/**
* 批量删除客户端告警信息
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteRmAlarmLogByIds(Long[] ids);
}
@@ -0,0 +1,63 @@
package com.tongran.mtragent.mapper;
import com.tongran.mtragent.domain.RmAlarmPushConfig;
import java.util.List;
/**
* 告警推送配置Mapper接口
*
* @author gyt
* @date 2025-11-11
*/
public interface RmAlarmPushConfigMapper
{
/**
* 查询告警推送配置
*
* @param id 告警推送配置主键
* @return 告警推送配置
*/
public RmAlarmPushConfig selectRmAlarmPushConfigById(Long id);
/**
* 查询告警推送配置列表
*
* @param rmAlarmPushConfig 告警推送配置
* @return 告警推送配置集合
*/
public List<RmAlarmPushConfig> selectRmAlarmPushConfigList(RmAlarmPushConfig rmAlarmPushConfig);
/**
* 新增告警推送配置
*
* @param rmAlarmPushConfig 告警推送配置
* @return 结果
*/
public int insertRmAlarmPushConfig(RmAlarmPushConfig rmAlarmPushConfig);
/**
* 修改告警推送配置
*
* @param rmAlarmPushConfig 告警推送配置
* @return 结果
*/
public int updateRmAlarmPushConfig(RmAlarmPushConfig rmAlarmPushConfig);
/**
* 删除告警推送配置
*
* @param id 告警推送配置主键
* @return 结果
*/
public int deleteRmAlarmPushConfigById(Long id);
/**
* 批量删除告警推送配置
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteRmAlarmPushConfigByIds(Long[] ids);
}
@@ -0,0 +1,76 @@
package com.tongran.mtragent.mapper;
import com.tongran.mtragent.domain.RmMtrClientRegistration;
import java.util.List;
/**
* MTR客户端注册Mapper接口
*
* @author gyt
* @date 2025-11-18
*/
public interface RmMtrClientRegistrationMapper
{
/**
* 查询MTR客户端注册
*
* @param id MTR客户端注册主键
* @return MTR客户端注册
*/
public RmMtrClientRegistration selectRmMtrClientRegistrationById(Long id);
/**
* 查询MTR客户端注册列表
*
* @param rmMtrClientRegistration MTR客户端注册
* @return MTR客户端注册集合
*/
public List<RmMtrClientRegistration> selectRmMtrClientRegistrationList(RmMtrClientRegistration rmMtrClientRegistration);
/**
* 新增MTR客户端注册
*
* @param rmMtrClientRegistration MTR客户端注册
* @return 结果
*/
public int insertRmMtrClientRegistration(RmMtrClientRegistration rmMtrClientRegistration);
/**
* 修改MTR客户端注册
*
* @param rmMtrClientRegistration MTR客户端注册
* @return 结果
*/
public int updateRmMtrClientRegistration(RmMtrClientRegistration rmMtrClientRegistration);
/**
* 删除MTR客户端注册
*
* @param id MTR客户端注册主键
* @return 结果
*/
public int deleteRmMtrClientRegistrationById(Long id);
/**
* 批量删除MTR客户端注册
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteRmMtrClientRegistrationByIds(Long[] ids);
/**
* 获取所有标识
* @param rmMtrClientRegistration
* @return
*/
List<RmMtrClientRegistration> getAllLogicalNode(RmMtrClientRegistration rmMtrClientRegistration);
/**
* 根据mtrClientId查询mtr管理信息
* @param rmMtrClientRegistration
* @return
*/
RmMtrClientRegistration getMsgByMtrClientId(RmMtrClientRegistration rmMtrClientRegistration);
}
@@ -0,0 +1,61 @@
package com.tongran.mtragent.mapper;
import java.util.List;
import com.tongran.mtragent.domain.RmMtrPolicyConfig;
/**
* mtr探测策略配置Mapper接口
*
* @author gyt
* @date 2025-11-18
*/
public interface RmMtrPolicyConfigMapper
{
/**
* 查询mtr探测策略配置
*
* @param id mtr探测策略配置主键
* @return mtr探测策略配置
*/
public RmMtrPolicyConfig selectRmMtrPolicyConfigById(Long id);
/**
* 查询mtr探测策略配置列表
*
* @param rmMtrPolicyConfig mtr探测策略配置
* @return mtr探测策略配置集合
*/
public List<RmMtrPolicyConfig> selectRmMtrPolicyConfigList(RmMtrPolicyConfig rmMtrPolicyConfig);
/**
* 新增mtr探测策略配置
*
* @param rmMtrPolicyConfig mtr探测策略配置
* @return 结果
*/
public int insertRmMtrPolicyConfig(RmMtrPolicyConfig rmMtrPolicyConfig);
/**
* 修改mtr探测策略配置
*
* @param rmMtrPolicyConfig mtr探测策略配置
* @return 结果
*/
public int updateRmMtrPolicyConfig(RmMtrPolicyConfig rmMtrPolicyConfig);
/**
* 删除mtr探测策略配置
*
* @param id mtr探测策略配置主键
* @return 结果
*/
public int deleteRmMtrPolicyConfigById(Long id);
/**
* 批量删除mtr探测策略配置
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteRmMtrPolicyConfigByIds(Long[] ids);
}
@@ -0,0 +1,71 @@
package com.tongran.mtragent.mapper;
import com.tongran.mtragent.domain.RmMtrProbeResult;
import java.util.List;
/**
* 网络mtr探测结果Mapper接口
*
* @author gyt
* @date 2025-11-20
*/
public interface RmMtrProbeResultMapper
{
/**
* 查询网络mtr探测结果
*
* @param id 网络mtr探测结果主键
* @return 网络mtr探测结果
*/
public RmMtrProbeResult selectRmMtrProbeResultById(Long id);
/**
* 查询网络mtr探测结果列表
*
* @param rmMtrProbeResult 网络mtr探测结果
* @return 网络mtr探测结果集合
*/
public List<RmMtrProbeResult> selectRmMtrProbeResultList(RmMtrProbeResult rmMtrProbeResult);
/**
* 新增网络mtr探测结果
*
* @param rmMtrProbeResult 网络mtr探测结果
* @return 结果
*/
public int insertRmMtrProbeResult(RmMtrProbeResult rmMtrProbeResult);
/**
* 修改网络mtr探测结果
*
* @param rmMtrProbeResult 网络mtr探测结果
* @return 结果
*/
public int updateRmMtrProbeResult(RmMtrProbeResult rmMtrProbeResult);
/**
* 删除网络mtr探测结果
*
* @param id 网络mtr探测结果主键
* @return 结果
*/
public int deleteRmMtrProbeResultById(Long id);
/**
* 批量删除网络mtr探测结果
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteRmMtrProbeResultByIds(Long[] ids);
void batchInsertRmMtrProbeResult(RmMtrProbeResult batchData);
/**
* 分表查询
* @param condition
* @return
*/
List<RmMtrProbeResult> selectByCondition(RmMtrProbeResult condition);
}
@@ -0,0 +1,65 @@
package com.tongran.mtragent.mapper;
import com.tongran.mtragent.domain.RmNetworkInterface;
import java.util.List;
/**
* 客户端网络接口信息Mapper接口
*
* @author gyt
* @date 2025-10-14
*/
public interface RmNetworkInterfaceMapper
{
/**
* 查询客户端网络接口信息
*
* @param id 客户端网络接口信息主键
* @return 客户端网络接口信息
*/
public RmNetworkInterface selectRmNetworkInterfaceById(Long id);
/**
* 查询客户端网络接口信息列表
*
* @param rmNetworkInterface 客户端网络接口信息
* @return 客户端网络接口信息集合
*/
public List<RmNetworkInterface> selectRmNetworkInterfaceList(RmNetworkInterface rmNetworkInterface);
/**
* 新增客户端网络接口信息
*
* @param rmNetworkInterface 客户端网络接口信息
* @return 结果
*/
public int insertRmNetworkInterface(RmNetworkInterface rmNetworkInterface);
/**
* 修改客户端网络接口信息
*
* @param rmNetworkInterface 客户端网络接口信息
* @return 结果
*/
public int updateRmNetworkInterface(RmNetworkInterface rmNetworkInterface);
/**
* 删除客户端网络接口信息
*
* @param id 客户端网络接口信息主键
* @return 结果
*/
public int deleteRmNetworkInterfaceById(Long id);
/**
* 批量删除客户端网络接口信息
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteRmNetworkInterfaceByIds(Long[] ids);
int updateRmNetworkInterfaceByMac(RmNetworkInterface rmNetworkInterface);
}
@@ -0,0 +1,30 @@
package com.tongran.mtragent.model;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
/**
* 消费者初始化
* 消费者连接信息 具体看nacos配置
*/
@Data
@Configuration
@Component
public class ConsumerMode {
@Value("${suning.rocketmq.namesrvAddr}")
private String namesrvAddr;
@Value("${suning.rocketmq.conumer.groupName}")
private String groupName ;
@Value("${suning.rocketmq.conumer.consumeThreadMin}")
private int consumeThreadMin;
@Value("${suning.rocketmq.conumer.consumeThreadMax}")
private int consumeThreadMax;
@Value("${suning.rocketmq.conumer.consumeMessageBatchMaxSize}")
private int consumeMessageBatchMaxSize;
@Value("${suning.rocketmq.conumer.agentTopic}")
private String agentTopic;
@Value("${suning.rocketmq.conumer.agentGroup}")
private String agentGroup;
}
@@ -0,0 +1,29 @@
package com.tongran.mtragent.model;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;
/**
* 生产者初始化
*/
@RefreshScope
@Data
@Configuration
public class ProducerMode {
@Value("${suning.rocketmq.producer.groupName}")
private String groupName;
@Value("${suning.rocketmq.producer.agentTopic}")
private String agentTopic;
@Value("${suning.rocketmq.producer.agentGroup}")
private String agentGroup;
@Value("${suning.rocketmq.namesrvAddr}")
private String namesrvAddr;
@Value("${suning.rocketmq.producer.maxMessageSize}")
private Integer maxMessageSize;
@Value("${suning.rocketmq.producer.sendMsgTimeout}")
private Integer sendMsgTimeout;
@Value("${suning.rocketmq.producer.retryTimesWhenSendFailed}")
private Integer retryTimesWhenSendFailed;
}
@@ -0,0 +1,23 @@
package com.tongran.mtragent.producer;
/**
* @author 影子
* 用于捕捉异常非受检异常(unchecked exception
* RuntimeException 和其子类的异常在编译时不需要进行强制性的异常处理,可以选择在运行时进行捕获和处理
* 可选择使用
*/
public class ConsumeException extends RuntimeException{
private static final long serialVersionUID = 4093867789628938836L;
public ConsumeException(String message) {
super(message);
}
public ConsumeException(Throwable cause) {
super(cause);
}
public ConsumeException(String message, Throwable cause) {
super(message, cause);
}
}
@@ -0,0 +1,225 @@
package com.tongran.mtragent.producer;
import com.alibaba.fastjson.JSON;
import com.tongran.mtragent.consumer.RocketMsgTransactionListenerImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.TransactionMQProducer;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.exception.RemotingException;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import static com.tongran.mtragent.config.ProducerConfig.producer;
/**
* 消息发送
*/
@Slf4j
public class MessageProducer {
/**
* 同步发送消息
* @param topic 主题
* @param tag 标签
* @param key 自定义的key,根据业务来定
* @param value 消息的内容
* 通过调用 send() 方法发送消息,阻塞等待服务器响应。
*/
public SendResult sendSynchronizeMessage(String topic, String tag, String key, String value){
String body = "topic:【"+topic+"】, tag:【"+tag+"】, key:【"+key+"】, value:【"+value+"";
try {
Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET));
System.out.println("生产者发送消息:"+ JSON.toJSONString(value));
SendResult result = producer.send(msg);
return result;
} catch (UnsupportedEncodingException e) {
log.error("消息初始化失败!body{}",body);
} catch (MQClientException | InterruptedException | RemotingException | MQBrokerException e) {
log.error("消息发送失败! body{}",body);
}
return null;
}
/**
* 单向发送消息
* @param topic 主题
* @param tag 标签
* @param key 自定义的key,根据业务来定
* @param value 消息的内容
* 单向发送:通过调用 sendOneway() 方法发送消息,不关心发送结果,适用于对可靠性要求不高的场景。
*/
public void sendOnewayMessage(String topic, String tag, String key, String value){
String body = "topic:【"+topic+"】, tag:【"+tag+"】, key:【"+key+"】, value:【"+value+"";
try {
Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET));
System.out.println("生产者发送消息:"+ JSON.toJSONString(value));
producer.sendOneway(msg);
} catch (UnsupportedEncodingException e) {
log.error("消息初始化失败!body{}",body);
} catch (MQClientException | InterruptedException | RemotingException e) {
log.error("消息发送失败! body{}",body);
}
}
/**
* 批量发送消息
* @param messages 消息列表
* 批量发送:通过调用 send() 方法并传入多条消息,实现批量发送消息。
*/
public SendResult sendBatchMessage(List<Message> messages){
String body = messages.toString();
try {
System.out.println("生产者发送消息:"+ messages);
// 发送批量消息
SendResult sendResult = producer.send(messages);
return sendResult;
} catch (MQClientException | InterruptedException | RemotingException e) {
log.error("消息发送失败! body{}",body);
} catch (MQBrokerException e) {
throw new RuntimeException(e);
}
return null;
}
/**
* 事务消息发送
* @param topic 主题
* @param tag 标签
* @param key 自定义的key,根据业务来定
* @param value 消息的内容
* 事务消息发送:通过使用事务监听器实现本地事务执行和消息发送的一致性。
*/
public SendResult sendThingMessage(String topic, String tag, String key, String value){
String body = "topic:【"+topic+"】, tag:【"+tag+"】, key:【"+key+"】, value:【"+value+"";
try {
// 实例化事务生产者
TransactionMQProducer transactionMQProducer = new TransactionMQProducer(producer.getProducerGroup());
transactionMQProducer.setNamesrvAddr(producer.getNamesrvAddr());
// 设置事务监听器
transactionMQProducer.setTransactionListener(new RocketMsgTransactionListenerImpl());
Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET));
System.out.println("生产者发送消息:"+ JSON.toJSONString(value));
// 发送事务消息
TransactionSendResult sendResult = transactionMQProducer.sendMessageInTransaction(msg, null);
return sendResult;
} catch (UnsupportedEncodingException e) {
log.error("消息初始化失败!body{}",body);
} catch (MQClientException e) {
log.error("消息发送失败! body{}",body);
}
return null;
}
/**
* 发送有序的消息
* @param messagesList Message集合
* @param messageQueueNumber 消息队列数量,根据实际情况设定
* 顺序发送: messageQueueNumber 表示消息的业务标识,可以根据具体需求进行设置来保证消息按顺序发送。
*/
public SendResult sendOrderlyMessage(List<Message> messagesList, Integer messageQueueNumber) {
SendResult result = null;
for (Message message : messagesList) {
try {
result = producer.send(message, (list, msg, arg) -> {
Integer queueNumber = (Integer) arg;
//int queueIndex = queueNumber % list.size();
return list.get(queueNumber);
}, messageQueueNumber);//根据编号取模,选择消息队列
} catch (MQClientException | RemotingException | MQBrokerException | InterruptedException e) {
log.error("发送有序消息失败");
return result;
}
}
return result;
}
/**
* 发送延迟消息
* @param topic 主题
* @param tag 标签
* @param key 自定义的key,根据业务来定
* @param value 消息的内容
* 延迟发送:通过设置延迟级别来实现延迟发送消息。
*/
public SendResult sendDelayMessage(String topic, String tag, String key, String value, Integer level)
{
SendResult result = null;
try
{
Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET));
System.out.println("生产者发送消息:"+ JSON.toJSONString(value));
//设置消息延迟级别,我这里设置5,对应就是延时一分钟
// "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h"
msg.setDelayTimeLevel(level);
// 发送消息到一个Broker
result = producer.send(msg);
// 通过sendResult返回消息是否成功送达
log.info("发送延迟消息结果:======sendResult{}", result);
DateFormat format =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
log.info("发送时间:{}", format.format(new Date()));
return result;
}
catch (Exception e)
{
e.printStackTrace();
log.error("延迟消息队列推送消息异常:{},推送内容:{}", e.getMessage(), result);
}
return result;
}
/**
* 发送异步的消息
* @param topic 主题
* @param tag 标签
* @param key 自定义的key,根据业务来定
* @param value 消息的内容
* 通过调用 send() 方法,并传入一个 SendCallback 对象,在发送消息的同时可以继续处理其他逻辑,消息发送结果通过回调函数通知。
*/
public SendResult sendAsyncProducerMessage(String topic, String tag, String key, String value){
try {
//创建一个消息实例,指定主题、标签和消息体。
Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET));
System.out.println("生产者发送消息:"+ JSON.toJSONString(value));
producer.send(msg,new SendCallback() {
// 异步回调的处理
@Override
public void onSuccess(SendResult sendResult) {
System.out.printf("%-10d 异步发送消息成功 %s %n", msg, sendResult.getMsgId());
}
@Override
public void onException(Throwable e) {
System.out.printf("%-10d 异步发送消息失败 %s %n", msg, e);
e.printStackTrace();
}
});
} catch (MQClientException e) {
e.printStackTrace();
} catch (RemotingException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return null;
}
}
@@ -0,0 +1,69 @@
package com.tongran.mtragent.service;
import com.tongran.mtragent.domain.AllMtrClient;
import java.util.List;
/**
* mtr探测丢包clinetId记录Service接口
*
* @author gyt
* @date 2025-11-24
*/
public interface IAllMtrClientService
{
/**
* 查询mtr探测丢包clinetId记录
*
* @param id mtr探测丢包clinetId记录主键
* @return mtr探测丢包clinetId记录
*/
public AllMtrClient selectAllMtrClientById(Long id);
/**
* 查询mtr探测丢包clinetId记录列表
*
* @param allMtrClient mtr探测丢包clinetId记录
* @return mtr探测丢包clinetId记录集合
*/
public List<AllMtrClient> selectAllMtrClientList(AllMtrClient allMtrClient);
/**
* 新增mtr探测丢包clinetId记录
*
* @param allMtrClient mtr探测丢包clinetId记录
* @return 结果
*/
public int insertAllMtrClient(AllMtrClient allMtrClient);
/**
* 修改mtr探测丢包clinetId记录
*
* @param allMtrClient mtr探测丢包clinetId记录
* @return 结果
*/
public int updateAllMtrClient(AllMtrClient allMtrClient);
/**
* 批量删除mtr探测丢包clinetId记录
*
* @param ids 需要删除的mtr探测丢包clinetId记录主键集合
* @return 结果
*/
public int deleteAllMtrClientByIds(Long[] ids);
/**
* 删除mtr探测丢包clinetId记录信息
*
* @param id mtr探测丢包clinetId记录主键
* @return 结果
*/
public int deleteAllMtrClientById(Long id);
/**
* 批量插入client记录
* @param allMtrClientList
* @return
*/
int batchInsertAllMtrClient(List<AllMtrClient> allMtrClientList);
}
@@ -0,0 +1,63 @@
package com.tongran.mtragent.service;
import com.tongran.mtragent.domain.InitialHeartbeatListenLog;
import java.util.List;
/**
* 心跳信息日志Service接口
*
* @author gyt
* @date 2025-09-08
*/
public interface IInitialHeartbeatListenLogService
{
/**
* 查询心跳信息日志
*
* @param clientId 心跳信息日志主键
* @return 心跳信息日志
*/
public InitialHeartbeatListenLog selectInitialHeartbeatListenLogByClientId(String clientId);
/**
* 查询心跳信息日志列表
*
* @param initialHeartbeatListenLog 心跳信息日志
* @return 心跳信息日志集合
*/
public List<InitialHeartbeatListenLog> selectInitialHeartbeatListenLogList(InitialHeartbeatListenLog initialHeartbeatListenLog);
/**
* 新增心跳信息日志
*
* @param initialHeartbeatListenLog 心跳信息日志
* @return 结果
*/
public int insertInitialHeartbeatListenLog(InitialHeartbeatListenLog initialHeartbeatListenLog);
/**
* 修改心跳信息日志
*
* @param initialHeartbeatListenLog 心跳信息日志
* @return 结果
*/
public int updateInitialHeartbeatListenLog(InitialHeartbeatListenLog initialHeartbeatListenLog);
/**
* 批量删除心跳信息日志
*
* @param clientIds 需要删除的心跳信息日志主键集合
* @return 结果
*/
public int deleteInitialHeartbeatListenLogByClientIds(String[] clientIds);
/**
* 删除心跳信息日志信息
*
* @param clientId 心跳信息日志主键
* @return 结果
*/
public int deleteInitialHeartbeatListenLogByClientId(String clientId);
}
@@ -0,0 +1,56 @@
package com.tongran.mtragent.service;
import com.tongran.mtragent.domain.RmAgentManagement;
import java.util.List;
/**
* Agent管理Service接口
*
* @author gyt
* @date 2025-09-15
*/
public interface IRmAgentManagementService
{
/**
* 查询Agent管理
*
* @param id Agent管理主键
* @return Agent管理
*/
public RmAgentManagement selectRmAgentManagementById(Long id);
/**
* 查询Agent管理列表
*
* @param rmAgentManagement Agent管理
* @return Agent管理集合
*/
public List<RmAgentManagement> selectRmAgentManagementList(RmAgentManagement rmAgentManagement);
/**
* 保存最后更新结果
*
* @param rmAgentManagement Agent管理
* @return 结果
*/
public void updateRmAgentManagementByHardwareSn(RmAgentManagement rmAgentManagement);
/**
* 手动立即更新agent
* @param rmAgentManagement
* @return
*/
int updateAgentNow(RmAgentManagement rmAgentManagement);
/**
* 配置更新策略
* @param rmAgentManagement
* @return
*/
int addUpdatePolicy(RmAgentManagement rmAgentManagement);
}
@@ -0,0 +1,63 @@
package com.tongran.mtragent.service;
import com.tongran.mtragent.domain.RmAlarmLog;
import java.util.List;
/**
* 客户端告警信息Service接口
*
* @author gyt
* @date 2025-11-10
*/
public interface IRmAlarmLogService
{
/**
* 查询客户端告警信息
*
* @param id 客户端告警信息主键
* @return 客户端告警信息
*/
public RmAlarmLog selectRmAlarmLogById(Long id);
/**
* 查询客户端告警信息列表
*
* @param rmAlarmLog 客户端告警信息
* @return 客户端告警信息集合
*/
public List<RmAlarmLog> selectRmAlarmLogList(RmAlarmLog rmAlarmLog);
/**
* 新增客户端告警信息
*
* @param rmAlarmLog 客户端告警信息
* @return 结果
*/
public int insertRmAlarmLog(RmAlarmLog rmAlarmLog);
/**
* 修改客户端告警信息
*
* @param rmAlarmLog 客户端告警信息
* @return 结果
*/
public int updateRmAlarmLog(RmAlarmLog rmAlarmLog);
/**
* 批量删除客户端告警信息
*
* @param ids 需要删除的客户端告警信息主键集合
* @return 结果
*/
public int deleteRmAlarmLogByIds(Long[] ids);
/**
* 删除客户端告警信息信息
*
* @param id 客户端告警信息主键
* @return 结果
*/
public int deleteRmAlarmLogById(Long id);
}
@@ -0,0 +1,63 @@
package com.tongran.mtragent.service;
import com.tongran.mtragent.domain.RmAlarmPushConfig;
import java.util.List;
/**
* 告警推送配置Service接口
*
* @author gyt
* @date 2025-11-11
*/
public interface IRmAlarmPushConfigService
{
/**
* 查询告警推送配置
*
* @param id 告警推送配置主键
* @return 告警推送配置
*/
public RmAlarmPushConfig selectRmAlarmPushConfigById(Long id);
/**
* 查询告警推送配置列表
*
* @param rmAlarmPushConfig 告警推送配置
* @return 告警推送配置集合
*/
public List<RmAlarmPushConfig> selectRmAlarmPushConfigList(RmAlarmPushConfig rmAlarmPushConfig);
/**
* 新增告警推送配置
*
* @param rmAlarmPushConfig 告警推送配置
* @return 结果
*/
public int insertRmAlarmPushConfig(RmAlarmPushConfig rmAlarmPushConfig);
/**
* 修改告警推送配置
*
* @param rmAlarmPushConfig 告警推送配置
* @return 结果
*/
public int updateRmAlarmPushConfig(RmAlarmPushConfig rmAlarmPushConfig);
/**
* 批量删除告警推送配置
*
* @param ids 需要删除的告警推送配置主键集合
* @return 结果
*/
public int deleteRmAlarmPushConfigByIds(Long[] ids);
/**
* 删除告警推送配置信息
*
* @param id 告警推送配置主键
* @return 结果
*/
public int deleteRmAlarmPushConfigById(Long id);
}
@@ -0,0 +1,83 @@
package com.tongran.mtragent.service;
import com.tongran.mtragent.domain.AllMtrClient;
import com.tongran.mtragent.domain.RmMtrClientRegistration;
import java.util.List;
/**
* MTR客户端注册Service接口
*
* @author gyt
* @date 2025-11-18
*/
public interface IRmMtrClientRegistrationService
{
/**
* 查询MTR客户端注册
*
* @param id MTR客户端注册主键
* @return MTR客户端注册
*/
public RmMtrClientRegistration selectRmMtrClientRegistrationById(Long id);
/**
* 查询MTR客户端注册列表
*
* @param rmMtrClientRegistration MTR客户端注册
* @return MTR客户端注册集合
*/
public List<RmMtrClientRegistration> selectRmMtrClientRegistrationList(RmMtrClientRegistration rmMtrClientRegistration);
/**
* 新增MTR客户端注册
*
* @param rmMtrClientRegistration MTR客户端注册
* @return 结果
*/
public int insertRmMtrClientRegistration(RmMtrClientRegistration rmMtrClientRegistration);
/**
* 修改MTR客户端注册
*
* @param rmMtrClientRegistration MTR客户端注册
* @return 结果
*/
public int updateRmMtrClientRegistration(RmMtrClientRegistration rmMtrClientRegistration);
/**
* 批量删除MTR客户端注册
*
* @param ids 需要删除的MTR客户端注册主键集合
* @return 结果
*/
public int deleteRmMtrClientRegistrationByIds(Long[] ids);
/**
* 删除MTR客户端注册信息
*
* @param id MTR客户端注册主键
* @return 结果
*/
public int deleteRmMtrClientRegistrationById(Long id);
/**
* 配置更新策略
* @param rmMtrClientRegistration
* @return
*/
int addAgentUpdatePolicy(RmMtrClientRegistration rmMtrClientRegistration);
/**
* 获取所有标识
* @param rmMtrClientRegistration
* @return
*/
List<RmMtrClientRegistration> getAllLogicalNode(RmMtrClientRegistration rmMtrClientRegistration);
/**
* 根据mtrClientId查询包含的clientId
* @param rmMtrClientRegistration
* @return clientId列表
*/
List<AllMtrClient> getClientIdByMtrClientId(RmMtrClientRegistration rmMtrClientRegistration);
}
@@ -0,0 +1,70 @@
package com.tongran.mtragent.service;
import com.tongran.mtragent.domain.RmMtrPolicyConfig;
import java.util.List;
/**
* mtr探测策略配置Service接口
*
* @author gyt
* @date 2025-11-18
*/
public interface IRmMtrPolicyConfigService
{
/**
* 查询mtr探测策略配置
*
* @param id mtr探测策略配置主键
* @return mtr探测策略配置
*/
public RmMtrPolicyConfig selectRmMtrPolicyConfigById(Long id);
/**
* 查询mtr探测策略配置列表
*
* @param rmMtrPolicyConfig mtr探测策略配置
* @return mtr探测策略配置集合
*/
public List<RmMtrPolicyConfig> selectRmMtrPolicyConfigList(RmMtrPolicyConfig rmMtrPolicyConfig);
/**
* 新增mtr探测策略配置
*
* @param rmMtrPolicyConfig mtr探测策略配置
* @return 结果
*/
public int insertRmMtrPolicyConfig(RmMtrPolicyConfig rmMtrPolicyConfig);
/**
* 修改mtr探测策略配置
*
* @param rmMtrPolicyConfig mtr探测策略配置
* @return 结果
*/
public int updateRmMtrPolicyConfig(RmMtrPolicyConfig rmMtrPolicyConfig);
/**
* 批量删除mtr探测策略配置
*
* @param ids 需要删除的mtr探测策略配置主键集合
* @return 结果
*/
public int deleteRmMtrPolicyConfigByIds(Long[] ids);
/**
* 删除mtr探测策略配置信息
*
* @param id mtr探测策略配置主键
* @return 结果
*/
public int deleteRmMtrPolicyConfigById(Long id);
/**
* 根据MTR客户端ID获取应该下发的策略列表
*
* @param mtrClientId MTR客户端ID
* @return 策略列表
*/
List<RmMtrPolicyConfig> getPoliciesForMtrClient(String mtrClientId);
}
@@ -0,0 +1,72 @@
package com.tongran.mtragent.service;
import com.tongran.mtragent.domain.RmMtrProbeResult;
import java.util.List;
import java.util.Map;
/**
* 网络mtr探测结果Service接口
*
* @author gyt
* @date 2025-11-20
*/
public interface IRmMtrProbeResultService
{
/**
* 查询网络mtr探测结果
*
* @param id 网络mtr探测结果主键
* @return 网络mtr探测结果
*/
public RmMtrProbeResult selectRmMtrProbeResultById(Long id);
/**
* 查询网络mtr探测结果列表
*
* @param rmMtrProbeResult 网络mtr探测结果
* @return 网络mtr探测结果集合
*/
public List<RmMtrProbeResult> selectRmMtrProbeResultList(RmMtrProbeResult rmMtrProbeResult);
/**
* 新增网络mtr探测结果
*
* @param rmMtrProbeResult 网络mtr探测结果
* @return 结果
*/
public int insertRmMtrProbeResult(RmMtrProbeResult rmMtrProbeResult);
/**
* 修改网络mtr探测结果
*
* @param rmMtrProbeResult 网络mtr探测结果
* @return 结果
*/
public int updateRmMtrProbeResult(RmMtrProbeResult rmMtrProbeResult);
/**
* 批量删除网络mtr探测结果
*
* @param ids 需要删除的网络mtr探测结果主键集合
* @return 结果
*/
public int deleteRmMtrProbeResultByIds(Long[] ids);
/**
* 删除网络mtr探测结果信息
*
* @param id 网络mtr探测结果主键
* @return 结果
*/
public int deleteRmMtrProbeResultById(Long id);
public void batchInsertRmMtrProbeResult(RmMtrProbeResult result);
/**
* 查看丢包率趋势
* @param rmMtrProbeResult
* @return
*/
Map<String, Object> getLossRateByMtrClientId(RmMtrProbeResult rmMtrProbeResult);
}
@@ -0,0 +1,83 @@
package com.tongran.mtragent.service;
import com.tongran.mtragent.domain.RmNetworkInterface;
import java.util.List;
/**
* 客户端网络接口信息Service接口
*
* @author gyt
* @date 2025-10-14
*/
public interface IRmNetworkInterfaceService
{
/**
* 查询客户端网络接口信息
*
* @param id 客户端网络接口信息主键
* @return 客户端网络接口信息
*/
public RmNetworkInterface selectRmNetworkInterfaceById(Long id);
/**
* 查询客户端网络接口信息列表
*
* @param rmNetworkInterface 客户端网络接口信息
* @return 客户端网络接口信息集合
*/
public List<RmNetworkInterface> selectRmNetworkInterfaceList(RmNetworkInterface rmNetworkInterface);
/**
* 新增客户端网络接口信息
*
* @param rmNetworkInterface 客户端网络接口信息
* @return 结果
*/
public int insertRmNetworkInterface(RmNetworkInterface rmNetworkInterface);
/**
* 修改客户端网络接口信息
*
* @param rmNetworkInterface 客户端网络接口信息
* @return 结果
*/
public int updateRmNetworkInterface(RmNetworkInterface rmNetworkInterface);
/**
* 修改客户端网络接口信息
*
* @param rmNetworkInterface 客户端网络接口信息
* @return 结果
*/
public int updateRmNetworkInterfaceByMac(RmNetworkInterface rmNetworkInterface);
/**
* 批量删除客户端网络接口信息
*
* @param ids 需要删除的客户端网络接口信息主键集合
* @return 结果
*/
public int deleteRmNetworkInterfaceByIds(Long[] ids);
/**
* 删除客户端网络接口信息信息
*
* @param id 客户端网络接口信息主键
* @return 结果
*/
public int deleteRmNetworkInterfaceById(Long id);
/**
* 绑定公网ip
* @param rmNetworkInterface
* @return
*/
int bindPublicIp(RmNetworkInterface rmNetworkInterface);
/**
* 更新路由信息
* @param clientId
*/
void updateRouteMsg(String clientId);
}
@@ -0,0 +1,103 @@
package com.tongran.mtragent.service.impl;
import com.tongran.common.core.utils.DateUtils;
import com.tongran.mtragent.domain.AllMtrClient;
import com.tongran.mtragent.mapper.AllMtrClientMapper;
import com.tongran.mtragent.service.IAllMtrClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* mtr探测丢包clinetId记录Service业务层处理
*
* @author gyt
* @date 2025-11-24
*/
@Service
public class AllMtrClientServiceImpl implements IAllMtrClientService
{
@Autowired
private AllMtrClientMapper allMtrClientMapper;
/**
* 查询mtr探测丢包clinetId记录
*
* @param id mtr探测丢包clinetId记录主键
* @return mtr探测丢包clinetId记录
*/
@Override
public AllMtrClient selectAllMtrClientById(Long id)
{
return allMtrClientMapper.selectAllMtrClientById(id);
}
/**
* 查询mtr探测丢包clinetId记录列表
*
* @param allMtrClient mtr探测丢包clinetId记录
* @return mtr探测丢包clinetId记录
*/
@Override
public List<AllMtrClient> selectAllMtrClientList(AllMtrClient allMtrClient)
{
return allMtrClientMapper.selectAllMtrClientList(allMtrClient);
}
/**
* 新增mtr探测丢包clinetId记录
*
* @param allMtrClient mtr探测丢包clinetId记录
* @return 结果
*/
@Override
public int insertAllMtrClient(AllMtrClient allMtrClient)
{
allMtrClient.setCreateTime(DateUtils.getNowDate());
return allMtrClientMapper.insertAllMtrClient(allMtrClient);
}
/**
* 修改mtr探测丢包clinetId记录
*
* @param allMtrClient mtr探测丢包clinetId记录
* @return 结果
*/
@Override
public int updateAllMtrClient(AllMtrClient allMtrClient)
{
allMtrClient.setUpdateTime(DateUtils.getNowDate());
return allMtrClientMapper.updateAllMtrClient(allMtrClient);
}
/**
* 批量删除mtr探测丢包clinetId记录
*
* @param ids 需要删除的mtr探测丢包clinetId记录主键
* @return 结果
*/
@Override
public int deleteAllMtrClientByIds(Long[] ids)
{
return allMtrClientMapper.deleteAllMtrClientByIds(ids);
}
/**
* 删除mtr探测丢包clinetId记录信息
*
* @param id mtr探测丢包clinetId记录主键
* @return 结果
*/
@Override
public int deleteAllMtrClientById(Long id)
{
return allMtrClientMapper.deleteAllMtrClientById(id);
}
@Override
public int batchInsertAllMtrClient(List<AllMtrClient> allMtrClientList) {
int rows = allMtrClientMapper.batchInsertAllMtrClient(allMtrClientList);
return rows;
}
}
@@ -0,0 +1,97 @@
package com.tongran.mtragent.service.impl;
import com.tongran.common.core.utils.DateUtils;
import com.tongran.mtragent.domain.InitialHeartbeatListenLog;
import com.tongran.mtragent.mapper.InitialHeartbeatListenLogMapper;
import com.tongran.mtragent.service.IInitialHeartbeatListenLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 心跳信息日志Service业务层处理
*
* @author gyt
* @date 2025-09-08
*/
@Service
public class InitialHeartbeatListenLogServiceImpl implements IInitialHeartbeatListenLogService
{
@Autowired
private InitialHeartbeatListenLogMapper initialHeartbeatListenLogMapper;
/**
* 查询心跳信息日志
*
* @param clientId 心跳信息日志主键
* @return 心跳信息日志
*/
@Override
public InitialHeartbeatListenLog selectInitialHeartbeatListenLogByClientId(String clientId)
{
return initialHeartbeatListenLogMapper.selectInitialHeartbeatListenLogByClientId(clientId);
}
/**
* 查询心跳信息日志列表
*
* @param initialHeartbeatListenLog 心跳信息日志
* @return 心跳信息日志
*/
@Override
public List<InitialHeartbeatListenLog> selectInitialHeartbeatListenLogList(InitialHeartbeatListenLog initialHeartbeatListenLog)
{
return initialHeartbeatListenLogMapper.selectInitialHeartbeatListenLogList(initialHeartbeatListenLog);
}
/**
* 新增心跳信息日志
*
* @param initialHeartbeatListenLog 心跳信息日志
* @return 结果
*/
@Override
public int insertInitialHeartbeatListenLog(InitialHeartbeatListenLog initialHeartbeatListenLog)
{
initialHeartbeatListenLog.setCreateTime(DateUtils.getNowDate());
return initialHeartbeatListenLogMapper.insertInitialHeartbeatListenLog(initialHeartbeatListenLog);
}
/**
* 修改心跳信息日志
*
* @param initialHeartbeatListenLog 心跳信息日志
* @return 结果
*/
@Override
public int updateInitialHeartbeatListenLog(InitialHeartbeatListenLog initialHeartbeatListenLog)
{
initialHeartbeatListenLog.setUpdateTime(DateUtils.getNowDate());
return initialHeartbeatListenLogMapper.updateInitialHeartbeatListenLog(initialHeartbeatListenLog);
}
/**
* 批量删除心跳信息日志
*
* @param clientIds 需要删除的心跳信息日志主键
* @return 结果
*/
@Override
public int deleteInitialHeartbeatListenLogByClientIds(String[] clientIds)
{
return initialHeartbeatListenLogMapper.deleteInitialHeartbeatListenLogByClientIds(clientIds);
}
/**
* 删除心跳信息日志信息
*
* @param clientId 心跳信息日志主键
* @return 结果
*/
@Override
public int deleteInitialHeartbeatListenLogByClientId(String clientId)
{
return initialHeartbeatListenLogMapper.deleteInitialHeartbeatListenLogByClientId(clientId);
}
}
@@ -0,0 +1,202 @@
package com.tongran.mtragent.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.tongran.common.core.constant.SecurityConstants;
import com.tongran.common.core.domain.R;
import com.tongran.common.core.enums.MsgEnum;
import com.tongran.common.core.utils.DateUtils;
import com.tongran.mtragent.domain.DeviceMessage;
import com.tongran.mtragent.domain.RmAgentManagement;
import com.tongran.mtragent.domain.vo.AgentUpdateMsgVo;
import com.tongran.mtragent.domain.vo.PolicyTypeVo;
import com.tongran.mtragent.domain.vo.PolicyVo;
import com.tongran.mtragent.mapper.RmAgentManagementMapper;
import com.tongran.mtragent.model.ProducerMode;
import com.tongran.mtragent.producer.MessageProducer;
import com.tongran.mtragent.service.IRmAgentManagementService;
import com.tongran.system.api.RemoteRevenueConfigService;
import com.tongran.system.api.domain.RmResourceRegistrationRemote;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* Agent管理Service业务层处理
*
* @author gyt
* @date 2025-09-15
*/
@Service
@Slf4j
public class RmAgentManagementServiceImpl implements IRmAgentManagementService
{
@Autowired
private RmAgentManagementMapper rmAgentManagementMapper;
@Autowired
private RemoteRevenueConfigService remoteRevenueConfigService;
@Autowired
private ProducerMode producerMode;
/**
* 查询Agent管理
*
* @param id Agent管理主键
* @return Agent管理
*/
@Override
public RmAgentManagement selectRmAgentManagementById(Long id)
{
RmAgentManagement agentManagement = rmAgentManagementMapper.selectRmAgentManagementById(id);
if(agentManagement != null){
if(agentManagement.getClientId() != null){
// 赋其他值
setPropties(agentManagement);
}
}
return agentManagement;
}
/**
* 查询Agent管理列表
*
* @param rmAgentManagement Agent管理
* @return Agent管理
*/
@Override
public List<RmAgentManagement> selectRmAgentManagementList(RmAgentManagement rmAgentManagement)
{
List<RmAgentManagement> managementList = rmAgentManagementMapper.selectRmAgentManagementList(rmAgentManagement);
for (RmAgentManagement agentManagement : managementList) {
if(agentManagement.getClientId()!=null){
// 查询注册表信息赋值
setPropties(agentManagement);
}
}
return managementList;
}
/**
* 根据注册表赋值
* @param agentManagement
*/
public void setPropties(RmAgentManagement agentManagement){
String clientId = agentManagement.getClientId();
// 设置其他信息
RmResourceRegistrationRemote queryRegist = new RmResourceRegistrationRemote();
queryRegist.setClientId(clientId);
R<RmResourceRegistrationRemote> registMsgR = remoteRevenueConfigService.getListByHardwareSn(queryRegist, SecurityConstants.INNER);
if(registMsgR != null && registMsgR.getData() != null){
RmResourceRegistrationRemote registMsg = registMsgR.getData();
agentManagement.setStatus(registMsg.getOnlineStatus());
agentManagement.setHardwareSn(registMsg.getHardwareSn());
}
}
/**
* 保存最后更新结果
*
* @param rmAgentManagement Agent管理
* @return 结果
*/
public void updateRmAgentManagementByHardwareSn(RmAgentManagement rmAgentManagement){
rmAgentManagementMapper.updateRmAgentManagementBySn(rmAgentManagement);
}
/**
* 配置更新策略v1.1
* @param rmAgentManagement
* @return
*/
@Override
public int addUpdatePolicy(RmAgentManagement rmAgentManagement) {
processAgentData(rmAgentManagement);
return 1;
}
/**
* 手动立即更新
* @param rmAgentManagement 更新信息
* @return
*/
@Override
public int updateAgentNow(RmAgentManagement rmAgentManagement) {
processAgentData(rmAgentManagement);
return 1;
}
/**
* 处理agen更新数据
* @param rmAgentManagement
*/
public void processAgentData(RmAgentManagement rmAgentManagement){
String clientIds = rmAgentManagement.getDeployDevice();
String[] clientIdArr = clientIds.split("\n");
for (String clientId : clientIdArr) {
// 创建新的对象,避免污染原始数据
RmAgentManagement currentAgent = new RmAgentManagement();
// 复制原始对象的属性
BeanUtils.copyProperties(rmAgentManagement, currentAgent);
// 设置当前循环的 clientId
currentAgent.setClientId(clientId);
currentAgent.setDeployDevice(clientId);
// 查询该资源是否已经配置
RmAgentManagement agentQueryParam = new RmAgentManagement();
agentQueryParam.setClientId(clientId);
List<RmAgentManagement> agentManagements = rmAgentManagementMapper.selectRmAgentManagementList(agentQueryParam);
if(!agentManagements.isEmpty()){
// 如果存在,修改
currentAgent.setLastUpdateTime(DateUtils.getNowDate());
if("0".equals(rmAgentManagement.getMethod())){
currentAgent.setScheduledUpdateTime(null);
}
rmAgentManagementMapper.updateRmAgentManagement(currentAgent);
}else{
// 如果不存在,添加
currentAgent.setLastUpdateTime(DateUtils.getNowDate());
if("0".equals(rmAgentManagement.getMethod())){
currentAgent.setScheduledUpdateTime(null);
}
rmAgentManagementMapper.insertRmAgentManagement(currentAgent);
}
// 构建更新策略
AgentUpdateMsgVo agentUpdateMsgVo = new AgentUpdateMsgVo();
agentUpdateMsgVo.setFileUrl(rmAgentManagement.getFileUrl());
agentUpdateMsgVo.setFileMd5(rmAgentManagement.getFileMd5());
agentUpdateMsgVo.setMethod(rmAgentManagement.getMethod());
if(rmAgentManagement.getMethod() == 1){
Date scheduledUpdateTime = rmAgentManagement.getScheduledUpdateTime();
long scheduledTime = scheduledUpdateTime.toInstant().getEpochSecond();
agentUpdateMsgVo.setPolicyTime(scheduledTime);
}
try {
PolicyVo<AgentUpdateMsgVo> policyVo = new PolicyVo();
List<AgentUpdateMsgVo> list = new ArrayList<>();
list.add(agentUpdateMsgVo);
policyVo.setContents(list);
String policyVoStr = JSONObject.toJSONString(policyVo);
PolicyTypeVo policyTypeVo = new PolicyTypeVo();
policyTypeVo.setVersions(policyVoStr);
String configJson = JSONObject.toJSONString(policyTypeVo);
DeviceMessage deviceMessage = new DeviceMessage();
deviceMessage.setClientId(clientId);
deviceMessage.setDataType(MsgEnum.获取最新策略应答.getValue());
deviceMessage.setData(configJson);
MessageProducer messageProducer = new MessageProducer();
messageProducer.sendAsyncProducerMessage(
producerMode.getAgentTopic(),
"",
"",
JSONObject.toJSONString(deviceMessage)
);
} catch (Exception e) {
log.error("发送设备配置失败,deviceId: {}", rmAgentManagement.getHardwareSn(), e);
}
}
}
}
@@ -0,0 +1,97 @@
package com.tongran.mtragent.service.impl;
import com.tongran.common.core.utils.DateUtils;
import com.tongran.mtragent.domain.RmAlarmLog;
import com.tongran.mtragent.mapper.RmAlarmLogMapper;
import com.tongran.mtragent.service.IRmAlarmLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 客户端告警信息Service业务层处理
*
* @author gyt
* @date 2025-11-10
*/
@Service
public class RmAlarmLogServiceImpl implements IRmAlarmLogService
{
@Autowired
private RmAlarmLogMapper rmAlarmLogMapper;
/**
* 查询客户端告警信息
*
* @param id 客户端告警信息主键
* @return 客户端告警信息
*/
@Override
public RmAlarmLog selectRmAlarmLogById(Long id)
{
return rmAlarmLogMapper.selectRmAlarmLogById(id);
}
/**
* 查询客户端告警信息列表
*
* @param rmAlarmLog 客户端告警信息
* @return 客户端告警信息
*/
@Override
public List<RmAlarmLog> selectRmAlarmLogList(RmAlarmLog rmAlarmLog)
{
return rmAlarmLogMapper.selectRmAlarmLogList(rmAlarmLog);
}
/**
* 新增客户端告警信息
*
* @param rmAlarmLog 客户端告警信息
* @return 结果
*/
@Override
public int insertRmAlarmLog(RmAlarmLog rmAlarmLog)
{
rmAlarmLog.setCreateTime(DateUtils.getNowDate());
return rmAlarmLogMapper.insertRmAlarmLog(rmAlarmLog);
}
/**
* 修改客户端告警信息
*
* @param rmAlarmLog 客户端告警信息
* @return 结果
*/
@Override
public int updateRmAlarmLog(RmAlarmLog rmAlarmLog)
{
rmAlarmLog.setUpdateTime(DateUtils.getNowDate());
return rmAlarmLogMapper.updateRmAlarmLog(rmAlarmLog);
}
/**
* 批量删除客户端告警信息
*
* @param ids 需要删除的客户端告警信息主键
* @return 结果
*/
@Override
public int deleteRmAlarmLogByIds(Long[] ids)
{
return rmAlarmLogMapper.deleteRmAlarmLogByIds(ids);
}
/**
* 删除客户端告警信息信息
*
* @param id 客户端告警信息主键
* @return 结果
*/
@Override
public int deleteRmAlarmLogById(Long id)
{
return rmAlarmLogMapper.deleteRmAlarmLogById(id);
}
}
@@ -0,0 +1,97 @@
package com.tongran.mtragent.service.impl;
import com.tongran.common.core.utils.DateUtils;
import com.tongran.mtragent.domain.RmAlarmPushConfig;
import com.tongran.mtragent.mapper.RmAlarmPushConfigMapper;
import com.tongran.mtragent.service.IRmAlarmPushConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 告警推送配置Service业务层处理
*
* @author gyt
* @date 2025-11-11
*/
@Service
public class RmAlarmPushConfigServiceImpl implements IRmAlarmPushConfigService
{
@Autowired
private RmAlarmPushConfigMapper rmAlarmPushConfigMapper;
/**
* 查询告警推送配置
*
* @param id 告警推送配置主键
* @return 告警推送配置
*/
@Override
public RmAlarmPushConfig selectRmAlarmPushConfigById(Long id)
{
return rmAlarmPushConfigMapper.selectRmAlarmPushConfigById(id);
}
/**
* 查询告警推送配置列表
*
* @param rmAlarmPushConfig 告警推送配置
* @return 告警推送配置
*/
@Override
public List<RmAlarmPushConfig> selectRmAlarmPushConfigList(RmAlarmPushConfig rmAlarmPushConfig)
{
return rmAlarmPushConfigMapper.selectRmAlarmPushConfigList(rmAlarmPushConfig);
}
/**
* 新增告警推送配置
*
* @param rmAlarmPushConfig 告警推送配置
* @return 结果
*/
@Override
public int insertRmAlarmPushConfig(RmAlarmPushConfig rmAlarmPushConfig)
{
rmAlarmPushConfig.setCreateTime(DateUtils.getNowDate());
return rmAlarmPushConfigMapper.insertRmAlarmPushConfig(rmAlarmPushConfig);
}
/**
* 修改告警推送配置
*
* @param rmAlarmPushConfig 告警推送配置
* @return 结果
*/
@Override
public int updateRmAlarmPushConfig(RmAlarmPushConfig rmAlarmPushConfig)
{
rmAlarmPushConfig.setUpdateTime(DateUtils.getNowDate());
return rmAlarmPushConfigMapper.updateRmAlarmPushConfig(rmAlarmPushConfig);
}
/**
* 批量删除告警推送配置
*
* @param ids 需要删除的告警推送配置主键
* @return 结果
*/
@Override
public int deleteRmAlarmPushConfigByIds(Long[] ids)
{
return rmAlarmPushConfigMapper.deleteRmAlarmPushConfigByIds(ids);
}
/**
* 删除告警推送配置信息
*
* @param id 告警推送配置主键
* @return 结果
*/
@Override
public int deleteRmAlarmPushConfigById(Long id)
{
return rmAlarmPushConfigMapper.deleteRmAlarmPushConfigById(id);
}
}
@@ -0,0 +1,231 @@
package com.tongran.mtragent.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.tongran.common.core.enums.MsgEnum;
import com.tongran.common.core.utils.DateUtils;
import com.tongran.mtragent.domain.AllMtrClient;
import com.tongran.mtragent.domain.DeviceMessage;
import com.tongran.mtragent.domain.RmMtrClientRegistration;
import com.tongran.mtragent.domain.vo.AgentUpdateMsgVo;
import com.tongran.mtragent.domain.vo.PolicyTypeVo;
import com.tongran.mtragent.domain.vo.PolicyVo;
import com.tongran.mtragent.mapper.AllMtrClientMapper;
import com.tongran.mtragent.mapper.RmMtrClientRegistrationMapper;
import com.tongran.mtragent.model.ProducerMode;
import com.tongran.mtragent.producer.MessageProducer;
import com.tongran.mtragent.service.IRmMtrClientRegistrationService;
import com.tongran.system.api.domain.NetworkInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.StringJoiner;
/**
* MTR客户端注册Service业务层处理
*
* @author gyt
* @date 2025-11-18
*/
@Service
@Slf4j
public class RmMtrClientRegistrationServiceImpl implements IRmMtrClientRegistrationService
{
@Autowired
private RmMtrClientRegistrationMapper rmMtrClientRegistrationMapper;
@Autowired
private AllMtrClientMapper allMtrClientMapper;
@Autowired
private ProducerMode producerMode;
/**
* 查询MTR客户端注册
*
* @param id MTR客户端注册主键
* @return MTR客户端注册
*/
@Override
public RmMtrClientRegistration selectRmMtrClientRegistrationById(Long id)
{
RmMtrClientRegistration rmMtrClientRegistration = rmMtrClientRegistrationMapper.selectRmMtrClientRegistrationById(id);
// 处理网卡信息
setNetworkMsg(rmMtrClientRegistration);
return rmMtrClientRegistration;
}
/**
* 查询MTR客户端注册列表
*
* @param rmMtrClientRegistration MTR客户端注册
* @return MTR客户端注册
*/
@Override
public List<RmMtrClientRegistration> selectRmMtrClientRegistrationList(RmMtrClientRegistration rmMtrClientRegistration)
{
List<RmMtrClientRegistration> list = rmMtrClientRegistrationMapper.selectRmMtrClientRegistrationList(rmMtrClientRegistration);
for (RmMtrClientRegistration mtrClientRegistration : list) {
// 处理网卡信息
setNetworkMsg(rmMtrClientRegistration);
}
return list;
}
/**
* 网卡信息处理
* @param rmMtrClientRegistration
*/
public void setNetworkMsg(RmMtrClientRegistration rmMtrClientRegistration){
String networkMsg = rmMtrClientRegistration.getNetworkInfo();
StringJoiner resultJoiner = new StringJoiner(";");
if(networkMsg != null){
List<NetworkInfo> networkInfoList = JSONObject.parseArray(networkMsg, NetworkInfo.class);
for (NetworkInfo networkInfo : networkInfoList) {
String name = networkInfo.getName() != null ? networkInfo.getName() : "";
String mac = networkInfo.getMac() != null ? networkInfo.getMac() : "";
String type = networkInfo.getType() != null ? networkInfo.getType() : "";
String ipv4 = networkInfo.getIpv4() != null ? networkInfo.getIpv4() : "";
// 单个对象的字段用逗号隔开
StringJoiner objectJoiner = new StringJoiner(",");
objectJoiner.add("接口名称:" + name)
.add("MAC地址:" + mac)
.add("接口类型:" + type)
.add("IPv4地址:" + ipv4);
resultJoiner.add(objectJoiner.toString());
}
rmMtrClientRegistration.setNetworkInfo(resultJoiner.toString());
}
}
/**
* 新增MTR客户端注册
*
* @param rmMtrClientRegistration MTR客户端注册
* @return 结果
*/
@Override
public int insertRmMtrClientRegistration(RmMtrClientRegistration rmMtrClientRegistration)
{
rmMtrClientRegistration.setCreateTime(DateUtils.getNowDate());
return rmMtrClientRegistrationMapper.insertRmMtrClientRegistration(rmMtrClientRegistration);
}
/**
* 修改MTR客户端注册
*
* @param rmMtrClientRegistration MTR客户端注册
* @return 结果
*/
@Override
public int updateRmMtrClientRegistration(RmMtrClientRegistration rmMtrClientRegistration)
{
rmMtrClientRegistration.setUpdateTime(DateUtils.getNowDate());
return rmMtrClientRegistrationMapper.updateRmMtrClientRegistration(rmMtrClientRegistration);
}
/**
* 批量删除MTR客户端注册
*
* @param ids 需要删除的MTR客户端注册主键
* @return 结果
*/
@Override
public int deleteRmMtrClientRegistrationByIds(Long[] ids)
{
return rmMtrClientRegistrationMapper.deleteRmMtrClientRegistrationByIds(ids);
}
/**
* 删除MTR客户端注册信息
*
* @param id MTR客户端注册主键
* @return 结果
*/
@Override
public int deleteRmMtrClientRegistrationById(Long id)
{
return rmMtrClientRegistrationMapper.deleteRmMtrClientRegistrationById(id);
}
/**
* 配置更新策略
* @param rmMtrClientRegistration
* @return
*/
@Override
public int addAgentUpdatePolicy(RmMtrClientRegistration rmMtrClientRegistration) {
String mtrClientIdStr = rmMtrClientRegistration.getMtrClientIds();
String[] mtrClientIdArr = mtrClientIdStr.split("\n");
// 只提取公共变量
String method = rmMtrClientRegistration.getMethod();
String fileMd5 = rmMtrClientRegistration.getFileMd5();
String filePath = rmMtrClientRegistration.getFilePath();
Date scheduledUpdateTime = rmMtrClientRegistration.getScheduledUpdateTime();
for (String mtrClientId : mtrClientIdArr) {
// 配置更新参数
RmMtrClientRegistration updateData = new RmMtrClientRegistration();
updateData.setMtrClientId(mtrClientId);
updateData.setMethod(method);
updateData.setFileMd5(fileMd5);
updateData.setFilePath(filePath);
updateData.setScheduledUpdateTime(scheduledUpdateTime);
if("0".equals(method)){
updateData.setScheduledUpdateTime(null);
}
rmMtrClientRegistrationMapper.updateRmMtrClientRegistration(updateData);
// 构建更新策略
AgentUpdateMsgVo agentUpdateMsgVo = new AgentUpdateMsgVo();
agentUpdateMsgVo.setFileUrl(filePath);
agentUpdateMsgVo.setFileMd5(fileMd5);
agentUpdateMsgVo.setMethod(Integer.valueOf(method));
if("1".equals(method)){
Date scheduledUpdateTimeInner = scheduledUpdateTime;
long scheduledTime = scheduledUpdateTimeInner.toInstant().getEpochSecond();
agentUpdateMsgVo.setPolicyTime(scheduledTime);
}
try {
PolicyVo<AgentUpdateMsgVo> policyVo = new PolicyVo();
List<AgentUpdateMsgVo> list = new ArrayList<>();
list.add(agentUpdateMsgVo);
policyVo.setContents(list);
String policyVoStr = JSONObject.toJSONString(policyVo);
PolicyTypeVo policyTypeVo = new PolicyTypeVo();
policyTypeVo.setVersions(policyVoStr);
String configJson = JSONObject.toJSONString(policyTypeVo);
DeviceMessage deviceMessage = new DeviceMessage();
deviceMessage.setClientId(mtrClientId);
deviceMessage.setDataType(MsgEnum.获取最新策略应答.getValue());
deviceMessage.setData(configJson);
MessageProducer messageProducer = new MessageProducer();
messageProducer.sendAsyncProducerMessage(
producerMode.getAgentTopic(),
"",
"",
JSONObject.toJSONString(deviceMessage)
);
} catch (Exception e) {
log.error("发送设备配置失败,deviceId: {}", mtrClientId, e);
}
}
return 1;
}
@Override
public List<RmMtrClientRegistration> getAllLogicalNode(RmMtrClientRegistration rmMtrClientRegistration) {
List<RmMtrClientRegistration> list = rmMtrClientRegistrationMapper.getAllLogicalNode(rmMtrClientRegistration);
return list;
}
@Override
public List<AllMtrClient> getClientIdByMtrClientId(RmMtrClientRegistration rmMtrClientRegistration) {
AllMtrClient allMtrClient = new AllMtrClient();
allMtrClient.setMtrClientId(rmMtrClientRegistration.getMtrClientId());
List<AllMtrClient> allMtrClientList = allMtrClientMapper.selectAllMtrClientList(allMtrClient);
return allMtrClientList;
}
}
@@ -0,0 +1,329 @@
package com.tongran.mtragent.service.impl;
import com.tongran.common.core.constant.SecurityConstants;
import com.tongran.common.core.domain.R;
import com.tongran.common.core.utils.DateUtils;
import com.tongran.common.core.utils.StringUtils;
import com.tongran.common.security.utils.SecurityUtils;
import com.tongran.mtragent.domain.RmMtrPolicyConfig;
import com.tongran.mtragent.mapper.RmMtrPolicyConfigMapper;
import com.tongran.mtragent.service.IRmMtrPolicyConfigService;
import com.tongran.system.api.RemoteRocketMqService;
import com.tongran.system.api.domain.RmNetworkInterfaceRemote;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
/**
* mtr探测策略配置Service业务层处理
*
* @author gyt
* @date 2025-11-18
*/
@Service
public class RmMtrPolicyConfigServiceImpl implements IRmMtrPolicyConfigService
{
@Autowired
private RmMtrPolicyConfigMapper rmMtrPolicyConfigMapper;
@Autowired
private RemoteRocketMqService remoteRocketMqService;
/**
* 查询mtr探测策略配置
*
* @param id mtr探测策略配置主键
* @return mtr探测策略配置
*/
@Override
public RmMtrPolicyConfig selectRmMtrPolicyConfigById(Long id)
{
RmMtrPolicyConfig mtrPolicyConfig = rmMtrPolicyConfigMapper.selectRmMtrPolicyConfigById(id);
mtrPolicyConfig.setServerGroup(mtrPolicyConfig.getServerGroup().replace("\n", ";"));
return mtrPolicyConfig;
}
/**
* 查询mtr探测策略配置列表
*
* @param rmMtrPolicyConfig mtr探测策略配置
* @return mtr探测策略配置
*/
@Override
public List<RmMtrPolicyConfig> selectRmMtrPolicyConfigList(RmMtrPolicyConfig rmMtrPolicyConfig)
{
List<RmMtrPolicyConfig> list = rmMtrPolicyConfigMapper.selectRmMtrPolicyConfigList(rmMtrPolicyConfig);
for (RmMtrPolicyConfig mtrPolicyConfig : list) {
mtrPolicyConfig.setServerGroup(mtrPolicyConfig.getServerGroup().replace("\n", ";"));
}
return list;
}
/**
* 辅助方法,给ip集合赋值
* @param mtrPolicyConfig
*/
public void setServerip(RmMtrPolicyConfig mtrPolicyConfig){
StringJoiner resultJoiner = new StringJoiner(";");
String serverGroupStr = mtrPolicyConfig.getServerGroup().replace("\n",",");
RmNetworkInterfaceRemote query = new RmNetworkInterfaceRemote();
query.setClientIds(serverGroupStr);
R<List<RmNetworkInterfaceRemote>> networkList = remoteRocketMqService.getNetworkInterfaceList(query, SecurityConstants.INNER);
if(networkList != null && networkList.getData() != null){
List<RmNetworkInterfaceRemote> rmNetworkInterfaceRemoteList = networkList.getData();
if(!rmNetworkInterfaceRemoteList.isEmpty()){
for (RmNetworkInterfaceRemote rmNetworkInterfaceRemote : rmNetworkInterfaceRemoteList) {
String publicIp = rmNetworkInterfaceRemote.getPublicIp();
resultJoiner.add(publicIp);
}
mtrPolicyConfig.setServeripGroup(resultJoiner.toString());
}
}
}
/**
* 辅助方法,给ip集合一一对应赋值
* @param mtrPolicyConfig
*/
public void setServeripToClientId(RmMtrPolicyConfig mtrPolicyConfig){
String serverGroupStr = mtrPolicyConfig.getServerGroup();
if(serverGroupStr == null){
return;
}
// 使用Set自动去重
Set<String> allIpsSet = new HashSet<>();
String[] clientIds = serverGroupStr.split("\n");
Map<String, List<String>> clientIdToIpsMap = new HashMap<>();
for (String clientId : clientIds) {
RmNetworkInterfaceRemote query = new RmNetworkInterfaceRemote();
query.setClientIds(clientId);
R<List<RmNetworkInterfaceRemote>> networkList = remoteRocketMqService.getNetworkInterfaceList(query, SecurityConstants.INNER);
if(networkList != null && networkList.getData() != null){
List<RmNetworkInterfaceRemote> rmNetworkInterfaceRemoteList = networkList.getData();
if(!rmNetworkInterfaceRemoteList.isEmpty()){
for (RmNetworkInterfaceRemote rmNetworkInterfaceRemote : rmNetworkInterfaceRemoteList) {
List<String> ips = networkList.getData().stream()
.map(RmNetworkInterfaceRemote::getPublicIp)
.filter(StringUtils::isNotBlank)
.collect(Collectors.toList());
if (!ips.isEmpty()) {
clientIdToIpsMap.put(clientId, ips);
allIpsSet.addAll(ips); // 自动去重
}
clientIdToIpsMap.put(clientId, ips);
}
// 将Set转换为分号分隔的字符串
String allIps = String.join(";", allIpsSet);
mtrPolicyConfig.setServeripGroup(allIps);
mtrPolicyConfig.setClientIdToIpsMap(clientIdToIpsMap);
}
}
}
}
/**
* 新增mtr探测策略配置
*
* @param rmMtrPolicyConfig mtr探测策略配置
* @return 结果
*/
@Override
public int insertRmMtrPolicyConfig(RmMtrPolicyConfig rmMtrPolicyConfig)
{
rmMtrPolicyConfig.setCreateTime(DateUtils.getNowDate());
rmMtrPolicyConfig.setUpdateTime(DateUtils.getNowDate());
rmMtrPolicyConfig.setCreateBy(SecurityUtils.getUsername());
// 数据表触发器,优先级自增
rmMtrPolicyConfig.setPriority(null);
// 给ip赋值
setServerip(rmMtrPolicyConfig);
int rows = rmMtrPolicyConfigMapper.insertRmMtrPolicyConfig(rmMtrPolicyConfig);
return rows;
}
/**
* 修改mtr探测策略配置
*
* @param rmMtrPolicyConfig mtr探测策略配置
* @return 结果
*/
@Override
public int updateRmMtrPolicyConfig(RmMtrPolicyConfig rmMtrPolicyConfig)
{
rmMtrPolicyConfig.setUpdateTime(DateUtils.getNowDate());
return rmMtrPolicyConfigMapper.updateRmMtrPolicyConfig(rmMtrPolicyConfig);
}
/**
* 批量删除mtr探测策略配置
*
* @param ids 需要删除的mtr探测策略配置主键
* @return 结果
*/
@Override
public int deleteRmMtrPolicyConfigByIds(Long[] ids)
{
return rmMtrPolicyConfigMapper.deleteRmMtrPolicyConfigByIds(ids);
}
/**
* 删除mtr探测策略配置信息
*
* @param id mtr探测策略配置主键
* @return 结果
*/
@Override
public int deleteRmMtrPolicyConfigById(Long id)
{
return rmMtrPolicyConfigMapper.deleteRmMtrPolicyConfigById(id);
}
/**
* 根据MTR客户端ID获取应该下发的策略列表
*
* @param mtrClientId MTR客户端ID
* @return 策略列表
*/
@Override
public List<RmMtrPolicyConfig> getPoliciesForMtrClient(String mtrClientId) {
List<RmMtrPolicyConfig> result = new ArrayList<>();
if (mtrClientId == null || mtrClientId.trim().isEmpty()) {
return result;
}
// 查询所有有效的策略(探测标志为1)
RmMtrPolicyConfig query = new RmMtrPolicyConfig();
query.setProbeFlag(1L); // 只查询启用探测的策略
List<RmMtrPolicyConfig> allPolicies = rmMtrPolicyConfigMapper.selectRmMtrPolicyConfigList(query);
if (allPolicies == null || allPolicies.isEmpty()) {
return result;
}
// 按优先级降序排序(优先级高的在前面)
List<RmMtrPolicyConfig> sortedPolicies = allPolicies.stream()
.filter(p -> p.getPriority() != null && p.getProbeFlag() != null)
.sorted((p1, p2) -> Long.compare(p2.getPriority(), p1.getPriority()))
.collect(Collectors.toList());
// 构建最终的服务器分配映射
Map<String, String> serverAssignment = new HashMap<>();
// 从高优先级到低优先级处理策略
for (RmMtrPolicyConfig policy : sortedPolicies) {
List<String> serverIds = getServerIdsFromPolicy(policy);
if (serverIds.isEmpty()) {
continue;
}
// 处理每个服务器:只有这个服务器还没有被处理过时,才处理当前策略
for (String serverId : serverIds) {
if (!serverAssignment.containsKey(serverId)) {
if (policy.getProbeFlag() == 1) {
// 探测:记录分配给哪个MTR客户端
serverAssignment.put(serverId, policy.getMtrClientId());
} else {
// 不探测:记录为null
serverAssignment.put(serverId, null);
}
}
}
}
// 找出应该由当前请求客户端执行的服务器
List<String> assignedServers = new ArrayList<>();
for (Map.Entry<String, String> entry : serverAssignment.entrySet()) {
String serverId = entry.getKey();
String assignedClientId = entry.getValue();
// 只有当分配给的客户端是当前请求客户端,且不是null(即需要探测)时
if (mtrClientId.equals(assignedClientId)) {
assignedServers.add(serverId);
}
}
// 如果没有服务器分配给当前客户端,返回空列表
if (assignedServers.isEmpty()) {
return result;
}
// 找出每个服务器最终生效的策略(最高优先级的那个)
Map<RmMtrPolicyConfig, List<String>> policyServersMap = new HashMap<>();
for (String serverId : assignedServers) {
RmMtrPolicyConfig finalPolicy = findFinalPolicyForServer(serverId, sortedPolicies);
if (finalPolicy != null) {
policyServersMap.computeIfAbsent(finalPolicy, k -> new ArrayList<>()).add(serverId);
}
}
// 创建策略副本返回
for (Map.Entry<RmMtrPolicyConfig, List<String>> entry : policyServersMap.entrySet()) {
RmMtrPolicyConfig newPolicy = createPolicyCopy(entry.getKey(), entry.getValue());
setServeripToClientId(newPolicy);
result.add(newPolicy);
}
return result;
}
/**
* 找出服务器最终生效的策略(最高优先级的那个)
*/
private RmMtrPolicyConfig findFinalPolicyForServer(String serverId, List<RmMtrPolicyConfig> sortedPolicies) {
for (RmMtrPolicyConfig policy : sortedPolicies) {
if (containsServer(policy, serverId)) {
return policy;
}
}
return null;
}
/**
* 从策略中提取服务器ID列表
*/
private List<String> getServerIdsFromPolicy(RmMtrPolicyConfig policy) {
List<String> serverIds = new ArrayList<>();
if (policy.getServerGroup() != null) {
String serverGroup = policy.getServerGroup();
String[] ids = serverGroup.split("\n");
for (String id : ids) {
if (id != null && !id.trim().isEmpty()) {
serverIds.add(id.trim());
}
}
}
return serverIds;
}
/**
* 检查策略是否包含指定服务器
*/
private boolean containsServer(RmMtrPolicyConfig policy, String serverId) {
List<String> serverIds = getServerIdsFromPolicy(policy);
return serverIds.contains(serverId);
}
/**
* 创建策略副本
*/
private RmMtrPolicyConfig createPolicyCopy(RmMtrPolicyConfig original, List<String> serverIds) {
RmMtrPolicyConfig copy = new RmMtrPolicyConfig();
copy.setId(original.getId());
copy.setPolicyName(original.getPolicyName());
copy.setPriority(original.getPriority());
copy.setMtrClientId(original.getMtrClientId());
copy.setProbeFlag(original.getProbeFlag());
copy.setStartTime(original.getStartTime());
copy.setEndTime(original.getEndTime());
copy.setProbeFrequency(original.getProbeFrequency());
// 服务器组用换行符连接
copy.setServerGroup(String.join("\n", serverIds));
copy.setServeripGroup(original.getServeripGroup());
copy.setCreateTime(original.getCreateTime());
copy.setUpdateTime(original.getUpdateTime());
copy.setCreateBy(original.getCreateBy());
copy.setUpdateBy(original.getUpdateBy());
return copy;
}
}
@@ -0,0 +1,219 @@
package com.tongran.mtragent.service.impl;
import com.tongran.common.core.utils.DateUtils;
import com.tongran.common.core.utils.EchartsDataUtils;
import com.tongran.common.core.utils.TableSubUtil;
import com.tongran.mtragent.domain.RmMtrProbeResult;
import com.tongran.mtragent.mapper.RmMtrProbeResultMapper;
import com.tongran.mtragent.service.IRmMtrProbeResultService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 网络mtr探测结果Service业务层处理
*
* @author gyt
* @date 2025-11-20
*/
@Service
@Slf4j
public class RmMtrProbeResultServiceImpl implements IRmMtrProbeResultService
{
@Autowired
private RmMtrProbeResultMapper rmMtrProbeResultMapper;
private final static String TABLE_PREFIX = "rm_mtr_probe_result";
/**
* 查询网络mtr探测结果
*
* @param id 网络mtr探测结果主键
* @return 网络mtr探测结果
*/
@Override
public RmMtrProbeResult selectRmMtrProbeResultById(Long id)
{
return rmMtrProbeResultMapper.selectRmMtrProbeResultById(id);
}
/**
* 查询网络mtr探测结果列表
*
* @param rmMtrProbeResult 网络mtr探测结果
* @return 网络mtr探测结果
*/
@Override
public List<RmMtrProbeResult> selectRmMtrProbeResultList(RmMtrProbeResult rmMtrProbeResult)
{
return rmMtrProbeResultMapper.selectRmMtrProbeResultList(rmMtrProbeResult);
}
/**
* 新增网络mtr探测结果
*
* @param rmMtrProbeResult 网络mtr探测结果
* @return 结果
*/
@Override
public int insertRmMtrProbeResult(RmMtrProbeResult rmMtrProbeResult)
{
Date createTime = rmMtrProbeResult.getCreateTime();
String tableName = TableSubUtil.getTableName(createTime, TABLE_PREFIX);
return rmMtrProbeResultMapper.insertRmMtrProbeResult(rmMtrProbeResult);
}
/**
* 修改网络mtr探测结果
*
* @param rmMtrProbeResult 网络mtr探测结果
* @return 结果
*/
@Override
public int updateRmMtrProbeResult(RmMtrProbeResult rmMtrProbeResult)
{
rmMtrProbeResult.setUpdateTime(DateUtils.getNowDate());
return rmMtrProbeResultMapper.updateRmMtrProbeResult(rmMtrProbeResult);
}
/**
* 批量删除网络mtr探测结果
*
* @param ids 需要删除的网络mtr探测结果主键
* @return 结果
*/
@Override
public int deleteRmMtrProbeResultByIds(Long[] ids)
{
return rmMtrProbeResultMapper.deleteRmMtrProbeResultByIds(ids);
}
/**
* 删除网络mtr探测结果信息
*
* @param id 网络mtr探测结果主键
* @return 结果
*/
@Override
public int deleteRmMtrProbeResultById(Long id)
{
return rmMtrProbeResultMapper.deleteRmMtrProbeResultById(id);
}
@Override
@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
public void batchInsertRmMtrProbeResult(RmMtrProbeResult rmMtrProbeResult) {
if (rmMtrProbeResult == null) {
return;
}
List<RmMtrProbeResult> dataList = rmMtrProbeResult.getList();
if (dataList == null || dataList.isEmpty()) {
return;
}
// 按表名分组批量插入
Map<String, List<RmMtrProbeResult>> groupedData = dataList.stream()
.map(data -> {
try {
RmMtrProbeResult processed = new RmMtrProbeResult();
BeanUtils.copyProperties(data, processed);
if (data.getCreateTime() == null) {
processed.setCreateTime(new Date());
}
if(data.getUpdateTime() == null){
processed.setUpdateTime(new Date());
}
processed.setTableName(TableSubUtil.getTableName(data.getCreateTime(), TABLE_PREFIX));
return processed;
} catch (Exception e) {
log.error("RmMtrProbeResult数据处理失败", e);
return null;
}
})
.filter(Objects::nonNull) // 过滤掉处理失败的数据
.collect(Collectors.groupingBy(
RmMtrProbeResult::getTableName,
LinkedHashMap::new, // 保持插入顺序
Collectors.toList()));
groupedData.forEach((tableName, list) -> {
try {
RmMtrProbeResult batchData = new RmMtrProbeResult();
BeanUtils.copyProperties(rmMtrProbeResult, batchData);
batchData.setTableName(tableName);
batchData.setList(list);
rmMtrProbeResultMapper.batchInsertRmMtrProbeResult(batchData);
} catch (Exception e) {
log.error("表{}插入失败", tableName, e);
throw new RuntimeException("批量插入失败", e);
}
});
}
/**
* 分表查询探测结果
* @param queryParam
* @return
*/
public List<RmMtrProbeResult> getListByTime(RmMtrProbeResult queryParam){
// 获取涉及的表名
Set<String> tableNames = TableSubUtil.getExistingTableNamesBetween(
queryParam.getStartTime(),
queryParam.getEndTime(),
TABLE_PREFIX
);
// 并行查询各表
return tableNames.parallelStream()
.flatMap(tableName -> {
RmMtrProbeResult condition = new RmMtrProbeResult();
condition.setTableName(tableName);
condition.setMtrClientId(queryParam.getMtrClientId());
condition.setClientId(queryParam.getClientId());
condition.setStartTime(queryParam.getStartTime());
condition.setEndTime(queryParam.getEndTime());
return rmMtrProbeResultMapper.selectByCondition(condition).stream();
})
.collect(Collectors.toList());
}
/**
* 查看丢包率趋势
* @param rmMtrProbeResult
* @return
*/
@Override
public Map<String, Object> getLossRateByMtrClientId(RmMtrProbeResult rmMtrProbeResult) {
if(rmMtrProbeResult.getStartTime() == null && rmMtrProbeResult.getEndTime() == null){
String[] timeRange = DateUtils.getTodayTimeRange();
rmMtrProbeResult.setStartTime(timeRange[0]);
rmMtrProbeResult.setEndTime(timeRange[1]);
}
List<RmMtrProbeResult> list = getListByTime(rmMtrProbeResult);
if(list == null){
list = new ArrayList<>();
}
try {
Map<String, Function<RmMtrProbeResult, ?>> extractors = new LinkedHashMap<>();
extractors.put("packetLossRate", info ->
info != null && info.getPacketLossRate() != null ?
info.getPacketLossRate() :
0);
Map<String, Object> resultMap = EchartsDataUtils.buildEchartsDataAutoPadding(
list, RmMtrProbeResult::getCreateTime, extractors, rmMtrProbeResult.getStartTime(), rmMtrProbeResult.getEndTime()
);
return resultMap;
} catch (Exception e){
e.printStackTrace();
}
return null;
}
}
@@ -0,0 +1,182 @@
package com.tongran.mtragent.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.tongran.common.core.enums.MsgEnum;
import com.tongran.common.core.utils.DateUtils;
import com.tongran.mtragent.domain.DeviceMessage;
import com.tongran.mtragent.domain.RmNetworkInterface;
import com.tongran.mtragent.domain.vo.PolicyTypeVo;
import com.tongran.mtragent.mapper.RmNetworkInterfaceMapper;
import com.tongran.mtragent.model.ProducerMode;
import com.tongran.mtragent.producer.MessageProducer;
import com.tongran.mtragent.service.IRmNetworkInterfaceService;
import com.tongran.system.api.domain.RouteMsg;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 客户端网络接口信息Service业务层处理
*
* @author gyt
* @date 2025-10-14
*/
@Service
public class RmNetworkInterfaceServiceImpl implements IRmNetworkInterfaceService
{
@Autowired
private RmNetworkInterfaceMapper rmNetworkInterfaceMapper;
@Autowired
private ProducerMode producerMode;
/**
* 查询客户端网络接口信息
*
* @param id 客户端网络接口信息主键
* @return 客户端网络接口信息
*/
@Override
public RmNetworkInterface selectRmNetworkInterfaceById(Long id)
{
return rmNetworkInterfaceMapper.selectRmNetworkInterfaceById(id);
}
/**
* 查询客户端网络接口信息列表
*
* @param rmNetworkInterface 客户端网络接口信息
* @return 客户端网络接口信息
*/
@Override
public List<RmNetworkInterface> selectRmNetworkInterfaceList(RmNetworkInterface rmNetworkInterface)
{
return rmNetworkInterfaceMapper.selectRmNetworkInterfaceList(rmNetworkInterface);
}
/**
* 新增客户端网络接口信息
*
* @param rmNetworkInterface 客户端网络接口信息
* @return 结果
*/
@Override
public int insertRmNetworkInterface(RmNetworkInterface rmNetworkInterface)
{
rmNetworkInterface.setCreateTime(DateUtils.getNowDate());
return rmNetworkInterfaceMapper.insertRmNetworkInterface(rmNetworkInterface);
}
/**
* 修改客户端网络接口信息
*
* @param rmNetworkInterface 客户端网络接口信息
* @return 结果
*/
@Override
public int updateRmNetworkInterface(RmNetworkInterface rmNetworkInterface)
{
rmNetworkInterface.setUpdateTime(DateUtils.getNowDate());
return rmNetworkInterfaceMapper.updateRmNetworkInterface(rmNetworkInterface);
}
@Override
public int updateRmNetworkInterfaceByMac(RmNetworkInterface rmNetworkInterface) {
rmNetworkInterface.setUpdateTime(DateUtils.getNowDate());
return rmNetworkInterfaceMapper.updateRmNetworkInterfaceByMac(rmNetworkInterface);
}
/**
* 批量删除客户端网络接口信息
*
* @param ids 需要删除的客户端网络接口信息主键
* @return 结果
*/
@Override
public int deleteRmNetworkInterfaceByIds(Long[] ids)
{
return rmNetworkInterfaceMapper.deleteRmNetworkInterfaceByIds(ids);
}
/**
* 删除客户端网络接口信息信息
*
* @param id 客户端网络接口信息主键
* @return 结果
*/
@Override
public int deleteRmNetworkInterfaceById(Long id)
{
return rmNetworkInterfaceMapper.deleteRmNetworkInterfaceById(id);
}
/**
* 绑定公网ip
* @param rmNetworkInterface
* @return
*/
@Override
public int bindPublicIp(RmNetworkInterface rmNetworkInterface) {
return rmNetworkInterfaceMapper.updateRmNetworkInterface(rmNetworkInterface);
}
/**
* 更新路由信息
* @param clientId
*/
public void updateRouteMsg(String clientId){
MessageProducer messageProducer = new MessageProducer();
// 查询路由是否有变化
RmNetworkInterface rmNetworkInterface = new RmNetworkInterface();
rmNetworkInterface.setClientId(clientId);
rmNetworkInterface.setBindIp("2");
List<RmNetworkInterface> networkInterfaces = rmNetworkInterfaceMapper.selectRmNetworkInterfaceList(rmNetworkInterface);
if(!networkInterfaces.isEmpty()){
List<RmNetworkInterface> oldList = networkInterfaces.stream()
.filter(networkInterface -> networkInterface.getNewFlag() == 0)
.collect(Collectors.toList());
if(!oldList.isEmpty()){
Map<String, Object> resultMap = new HashMap<>();
// 增加静态路由
RmNetworkInterface oldMsg = oldList.get(0);
RouteMsg oldRouteMsg = new RouteMsg();
oldRouteMsg.setGateway(oldMsg.getGateway());
oldRouteMsg.setName(oldMsg.getInterfaceName());
resultMap.put("delRoute", oldRouteMsg);
List<RmNetworkInterface> newList = networkInterfaces.stream()
.filter(networkInterface -> networkInterface.getNewFlag() == 1)
.collect(Collectors.toList());
RmNetworkInterface newMsg = newList.get(0);
RouteMsg newRouteMsg = new RouteMsg();
newRouteMsg.setGateway(newMsg.getGateway());
newRouteMsg.setName(newMsg.getInterfaceName());
resultMap.put("addRoute", newRouteMsg);
resultMap.put("upTime", Instant.now().getEpochSecond());
PolicyTypeVo policyTypeVo = new PolicyTypeVo();
policyTypeVo.setRoutes(JSONObject.toJSONString(resultMap));
String configJson = JSONObject.toJSONString(policyTypeVo);
// 构建发送消息
DeviceMessage message = new DeviceMessage();
message.setClientId(clientId);
message.setData(configJson);
message.setDataType(MsgEnum.获取最新策略应答.getValue());
messageProducer.sendAsyncProducerMessage(
producerMode.getAgentTopic(),
"",
"",
JSONObject.toJSONString(message)
);
// 更新网卡信息表
RmNetworkInterface updateQuery = new RmNetworkInterface();
updateQuery.setNewFlag(999);
updateQuery.setMacAddress(networkInterfaces.get(0).getMacAddress());
rmNetworkInterfaceMapper.updateRmNetworkInterfaceByMac(updateQuery);
}
}
}
}
@@ -0,0 +1,41 @@
package com.tongran.mtragent.utils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
public class JsonDataParser {
private static final ObjectMapper objectMapper = new ObjectMapper();
/**
* 通用JSON解析方法(兼容对象和数组)
* @param jsonStr JSON字符串
* @param valueType 目标实体类类型
* @return 实体类List集合
*/
public static <T> List<T> parseJsonData(String jsonStr, Class<T> valueType) {
if (!StringUtils.hasText(jsonStr)) {
return new ArrayList<>();
}
try {
JsonNode rootNode = objectMapper.readTree(jsonStr);
if (rootNode.isArray()) {
// 处理数组格式JSON
return objectMapper.readValue(jsonStr,
objectMapper.getTypeFactory().constructCollectionType(List.class, valueType));
} else {
// 处理单个对象格式JSON
List<T> result = new ArrayList<>(1);
result.add(objectMapper.readValue(jsonStr, valueType));
return result;
}
} catch (Exception e) {
throw new RuntimeException("JSON解析失败: " + e.getMessage(), e);
}
}
}
@@ -0,0 +1,149 @@
package com.tongran.mtragent.utils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
public class SwitchJsonDataParser {
private static final ObjectMapper objectMapper = new ObjectMapper();
/**
* 通用JSON解析方法(兼容对象和数组)
* @param jsonStr JSON字符串
* @param valueType 目标实体类类型
* @return 实体类List集合
*/
public static <T> List<T> parseJsonData(String jsonStr, Class<T> valueType) {
if (!StringUtils.hasText(jsonStr)) {
return new ArrayList<>();
}
try {
JsonNode rootNode = objectMapper.readTree(jsonStr);
if (rootNode.isArray()) {
// 处理数组格式JSON
if (isStringArrayContainingJsonObjects((ArrayNode) rootNode)) {
// 处理包含JSON对象字符串的数组 - 转换为真正的对象数组
ArrayNode processedArray = processStringJsonArrayToObjectArray((ArrayNode) rootNode);
return convertJsonArrayToList(processedArray, valueType);
} else {
// 处理普通JSON数组
processJsonArray((ArrayNode) rootNode);
return convertJsonArrayToList((ArrayNode) rootNode, valueType);
}
} else {
// 处理单个对象格式JSON
if (rootNode.isObject()) {
processJsonObject((ObjectNode) rootNode);
}
List<T> result = new ArrayList<>(1);
result.add(objectMapper.treeToValue(rootNode, valueType));
return result;
}
} catch (Exception e) {
throw new RuntimeException("JSON解析失败: " + e.getMessage(), e);
}
}
/**
* 将JsonArray转换为List<T>
*/
private static <T> List<T> convertJsonArrayToList(ArrayNode arrayNode, Class<T> valueType) throws Exception {
List<T> result = new ArrayList<>();
for (int i = 0; i < arrayNode.size(); i++) {
JsonNode element = arrayNode.get(i);
result.add(objectMapper.treeToValue(element, valueType));
}
return result;
}
/**
* 判断是否是包含JSON对象字符串的字符串数组
*/
private static boolean isStringArrayContainingJsonObjects(ArrayNode arrayNode) {
if (arrayNode.size() == 0) return false;
JsonNode firstElement = arrayNode.get(0);
if (firstElement.isTextual()) {
try {
String strValue = firstElement.textValue();
// 检查是否是JSON对象格式的字符串
if (strValue.startsWith("{") && strValue.endsWith("}")) {
objectMapper.readTree(strValue);
return true;
}
} catch (Exception e) {
return false;
}
}
return false;
}
/**
* 处理包含JSON对象字符串的字符串数组,转换为真正的对象数组
*/
private static ArrayNode processStringJsonArrayToObjectArray(ArrayNode arrayNode) {
ArrayNode resultArray = objectMapper.createArrayNode();
for (int i = 0; i < arrayNode.size(); i++) {
JsonNode element = arrayNode.get(i);
if (element.isTextual()) {
try {
String jsonString = element.textValue();
JsonNode jsonNode = objectMapper.readTree(jsonString);
if (jsonNode.isObject()) {
// 处理JSON对象中的 noSuchInstance
processJsonObject((ObjectNode) jsonNode);
resultArray.add(jsonNode);
} else {
resultArray.add(element);
}
} catch (Exception e) {
// 如果解析失败,保持原样
resultArray.add(element);
}
} else {
resultArray.add(element);
}
}
return resultArray;
}
/**
* 处理JSON数组
*/
private static void processJsonArray(ArrayNode arrayNode) {
for (int i = 0; i < arrayNode.size(); i++) {
JsonNode element = arrayNode.get(i);
if (element.isObject()) {
processJsonObject((ObjectNode) element);
} else if (element.isArray()) {
processJsonArray((ArrayNode) element);
}
}
}
/**
* 处理JSON对象
*/
private static void processJsonObject(ObjectNode objectNode) {
objectNode.fields().forEachRemaining(entry -> {
JsonNode value = entry.getValue();
if (value.isTextual() && "noSuchInstance".equals(value.textValue())) {
objectNode.putNull(entry.getKey());
} else if (value.isObject()) {
processJsonObject((ObjectNode) value);
} else if (value.isArray()) {
processJsonArray((ArrayNode) value);
}
});
}
}
@@ -0,0 +1,99 @@
package com.tongran.mtragent.utils;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedHashSet;
import java.util.Set;
public class TableRouterUtil {
// 日期格式
private static final DateTimeFormatter YEAR_MONTH_FORMAT =
DateTimeFormatter.ofPattern("yyyy_MM");
private static final DateTimeFormatter DATE_TIME_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 表名前缀
private static final String TABLE_PREFIX = "eps_initial_traffic";
// 表名前缀
private static final String TABLE_PREFIX_INITIAL = "initial_bandwidth_traffic";
/**
* 根据创建时间获取表名
* @param createTime 记录创建时间
* @return 对应的分表名称
* @throws IllegalArgumentException 如果createTime为null
*
* 示例:
* 2023-08-05 14:30:00 → eps_initial_traffic_2023_08_1_10
* 2023-08-15 09:15:00 → eps_initial_traffic_2023_08_11_20
* 2023-08-25 18:45:00 → eps_initial_traffic_2023_08_21_31
*/
public static String getTableName(LocalDateTime createTime) {
if (createTime == null) {
throw new IllegalArgumentException("创建时间不能为null");
}
String yearMonth = createTime.format(YEAR_MONTH_FORMAT);
int day = createTime.getDayOfMonth();
return String.format("%s_%s_%s",
TABLE_PREFIX_INITIAL,
yearMonth,
getDayRange(day));
}
/**
* 获取时间范围内涉及的所有表名
* @param startTime 开始时间 (格式: "yyyy-MM-dd HH:mm:ss")
* @param endTime 结束时间 (格式: "yyyy-MM-dd HH:mm:ss")
* @return 按时间顺序排列的表名集合
*/
public static Set<String> getTableNamesBetween(String startTime, String endTime) {
LocalDateTime start = parseDateTime(startTime);
LocalDateTime end = parseDateTime(endTime);
validateTimeRange(start, end);
Set<String> tableNames = new LinkedHashSet<>();
LocalDateTime current = start.withHour(0).withMinute(0).withSecond(0);
while (!current.isAfter(end)) {
tableNames.add(getTableName(current));
current = current.plusDays(1);
}
return tableNames;
}
// 解析字符串为LocalDateTime
private static LocalDateTime parseDateTime(String dateTimeStr) {
if (dateTimeStr == null || dateTimeStr.trim().isEmpty()) {
throw new IllegalArgumentException("时间字符串不能为空");
}
try {
return LocalDateTime.parse(dateTimeStr, DATE_TIME_FORMATTER);
} catch (Exception e) {
throw new IllegalArgumentException("时间格式必须为: yyyy-MM-dd HH:mm:ss", e);
}
}
// 获取日期区间
private static String getDayRange(int day) {
if (day < 1 || day > 31) {
throw new IllegalArgumentException("日期必须在1-31之间");
}
if (day <= 10) return "1_10";
if (day <= 20) return "11_20";
return "21_31";
}
// 验证时间范围
private static void validateTimeRange(LocalDateTime start, LocalDateTime end) {
if (start == null || end == null) {
throw new IllegalArgumentException("时间范围参数不能为null");
}
if (start.isAfter(end)) {
throw new IllegalArgumentException("开始时间不能晚于结束时间");
}
}
}
@@ -0,0 +1,285 @@
package com.tongran.mtragent.utils;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class WeChatWorkBot {
private static final ObjectMapper mapper = new ObjectMapper();
/**
* 发送基于模板的文本消息
* @param webhookUrl webhook地址
* @param template 消息模板,例如:"项目[项目名称]在[时间]发生[事件类型]"
* @param fieldValues 字段值的映射,key为中文字段名,value为实际值(支持String、Number、Boolean等)
* @return 是否发送成功
*/
public static boolean sendTemplateMessage(String webhookUrl, String template,
Map<String, Object> fieldValues) {
return sendTemplateMessage(webhookUrl, template, fieldValues, null, null, false);
}
/**
* 发送基于模板的文本消息(支持@功能)
* @param webhookUrl webhook地址
* @param template 消息模板
* @param fieldValues 字段值的映射
* @param mentionedMobiles 被@的用户列表(手机号)
* @param mentionedAll 是否@所有人
* @return 是否发送成功
*/
public static boolean sendTemplateMessage(String webhookUrl, String template,
Map<String, Object> fieldValues,
String[] mentionedMobiles, boolean mentionedAll) {
return sendTemplateMessage(webhookUrl, template, fieldValues, null, mentionedMobiles, mentionedAll);
}
/**
* 发送基于模板的文本消息(完整参数)
* @param webhookUrl webhook地址
* @param template 消息模板
* @param fieldValues 字段值的映射
* @param defaultValue 未找到字段时的默认值
* @param mentionedMobiles 被@的用户列表(手机号)
* @param mentionedAll 是否@所有人
* @return 是否发送成功
*/
public static boolean sendTemplateMessage(String webhookUrl, String template,
Map<String, Object> fieldValues, Object defaultValue,
String[] mentionedMobiles, boolean mentionedAll) {
try {
String actualContent = processTemplate(template, fieldValues, defaultValue);
return sendTextMessage(webhookUrl, actualContent, mentionedMobiles, mentionedAll);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 处理模板,替换字段占位符
* @param template 消息模板
* @param fieldValues 字段值映射
* @param defaultValue 默认值
* @return 处理后的消息内容
*/
public static String processTemplate(String template, Map<String, Object> fieldValues,
Object defaultValue) {
if (template == null) return "";
if (fieldValues == null || fieldValues.isEmpty()) {
return template;
}
Pattern pattern = Pattern.compile("\\[(.*?)\\]");
Matcher matcher = pattern.matcher(template);
StringBuffer result = new StringBuffer();
while (matcher.find()) {
String fieldName = matcher.group(1);
Object fieldValueObj = fieldValues.get(fieldName);
String fieldValue = convertToString(fieldValueObj);
// 如果字段值为空,使用默认值或保留原占位符
if (fieldValue == null || fieldValue.trim().isEmpty()) {
fieldValue = convertToString(defaultValue);
if (fieldValue == null) {
fieldValue = "[" + fieldName + "]";
}
}
// 对替换值进行转义,防止正则表达式特殊字符问题
matcher.appendReplacement(result, Matcher.quoteReplacement(fieldValue));
}
matcher.appendTail(result);
return result.toString();
}
/**
* 将对象转换为字符串
* @param obj 要转换的对象
* @return 字符串表示
*/
private static String convertToString(Object obj) {
if (obj == null) {
return null;
}
if (obj instanceof String) {
return (String) obj;
} else if (obj instanceof Number || obj instanceof Boolean) {
return String.valueOf(obj);
} else if (obj instanceof java.util.Date) {
return new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((java.util.Date) obj);
} else {
return obj.toString();
}
}
/**
* 验证模板中的字段是否都有对应的值
* @param template 消息模板
* @param fieldValues 字段值映射
* @return 是否所有字段都有值
*/
public static boolean validateTemplate(String template, Map<String, Object> fieldValues) {
if (template == null || fieldValues == null) {
return false;
}
Pattern pattern = Pattern.compile("\\[(.*?)\\]");
Matcher matcher = pattern.matcher(template);
while (matcher.find()) {
String fieldName = matcher.group(1);
Object fieldValue = fieldValues.get(fieldName);
String strValue = convertToString(fieldValue);
if (!fieldValues.containsKey(fieldName) ||
strValue == null ||
strValue.trim().isEmpty()) {
return false;
}
}
return true;
}
/**
* 获取模板中的所有字段名
* @param template 消息模板
* @return 字段名列表
*/
public static java.util.List<String> getTemplateFields(String template) {
java.util.List<String> fields = new java.util.ArrayList<>();
if (template == null) {
return fields;
}
Pattern pattern = Pattern.compile("\\[(.*?)\\]");
Matcher matcher = pattern.matcher(template);
while (matcher.find()) {
fields.add(matcher.group(1));
}
return fields;
}
/**
* 发送Markdown模板消息
* @param webhookUrl webhook地址
* @param template Markdown模板
* @param fieldValues 字段值映射
* @return 是否发送成功
*/
public static boolean sendMarkdownTemplateMessage(String webhookUrl, String template,
Map<String, Object> fieldValues) {
return sendMarkdownTemplateMessage(webhookUrl, template, fieldValues, null);
}
/**
* 发送Markdown模板消息
* @param webhookUrl webhook地址
* @param template Markdown模板
* @param fieldValues 字段值映射
* @param defaultValue 默认值
* @return 是否发送成功
*/
public static boolean sendMarkdownTemplateMessage(String webhookUrl, String template,
Map<String, Object> fieldValues,
Object defaultValue) {
try {
String actualContent = processTemplate(template, fieldValues, defaultValue);
return sendMarkdownMessage(webhookUrl, actualContent);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 发送文本消息
*/
public static boolean sendTextMessage(String webhookUrl, String content) {
return sendTextMessage(webhookUrl, content, null, false);
}
/**
* 发送文本消息(支持@功能)
*/
public static boolean sendTextMessage(String webhookUrl, String content,
String[] mentionedMobiles, boolean mentionedAll) {
try {
Map<String, Object> message = new HashMap<>();
message.put("msgtype", "text");
Map<String, Object> textContent = new HashMap<>();
textContent.put("content", content);
if (mentionedAll) {
textContent.put("mentioned_mobile_list", new String[]{"@all"});
} else if (mentionedMobiles != null && mentionedMobiles.length > 0) {
textContent.put("mentioned_mobile_list", mentionedMobiles);
}
message.put("text", textContent);
return sendMessage(webhookUrl, mapper.writeValueAsString(message));
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 发送Markdown消息
*/
public static boolean sendMarkdownMessage(String webhookUrl, String content) {
try {
Map<String, Object> message = new HashMap<>();
message.put("msgtype", "markdown");
Map<String, Object> markdownContent = new HashMap<>();
markdownContent.put("content", content);
message.put("markdown", markdownContent);
return sendMessage(webhookUrl, mapper.writeValueAsString(message));
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private static boolean sendMessage(String webhookUrl, String jsonBody) {
try {
URL url = new URL(webhookUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setDoOutput(true);
connection.setConnectTimeout(5000);
connection.setReadTimeout(10000);
try (OutputStream os = connection.getOutputStream()) {
byte[] input = jsonBody.getBytes("UTF-8");
os.write(input, 0, input.length);
}
int responseCode = connection.getResponseCode();
return responseCode == 200;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}