parent
c422565cfe
commit
81b6fa6760
14 changed files with 915 additions and 3 deletions
@ -0,0 +1,62 @@ |
|||||||
|
|
||||||
|
package org.springblade.common.constant; |
||||||
|
|
||||||
|
/** |
||||||
|
* 通用常量 |
||||||
|
* |
||||||
|
* @author Chill |
||||||
|
*/ |
||||||
|
public interface MonitorConstant { |
||||||
|
|
||||||
|
String EQUIP = "equip"; |
||||||
|
|
||||||
|
/** |
||||||
|
* 监控类型-服务 |
||||||
|
*/ |
||||||
|
String SERVICE = "service"; |
||||||
|
|
||||||
|
String RESULT = "result"; |
||||||
|
|
||||||
|
/** |
||||||
|
* 状态0:未运行 |
||||||
|
*/ |
||||||
|
Integer STATUS_0 = 0; |
||||||
|
|
||||||
|
/** |
||||||
|
* 状态1:正常运行 |
||||||
|
*/ |
||||||
|
Integer STATUS_1 = 1; |
||||||
|
|
||||||
|
/** |
||||||
|
* 状态2:状态异常 |
||||||
|
*/ |
||||||
|
Integer STATUS_2 = 2; |
||||||
|
|
||||||
|
/** |
||||||
|
* 状态3:通信异常 |
||||||
|
*/ |
||||||
|
Integer STATUS_3 = 3; |
||||||
|
|
||||||
|
/** |
||||||
|
* 状态4:状态静默 |
||||||
|
*/ |
||||||
|
Integer STATUS_4 = 4; |
||||||
|
|
||||||
|
/** |
||||||
|
* 监控类型-中间件 |
||||||
|
*/ |
||||||
|
String MIDDLEWARE = "middleware"; |
||||||
|
|
||||||
|
/** |
||||||
|
* 网关 |
||||||
|
*/ |
||||||
|
String GATEWAY = "gateway"; |
||||||
|
|
||||||
|
/** |
||||||
|
* mqtt |
||||||
|
*/ |
||||||
|
String MQTT = "mqtt"; |
||||||
|
|
||||||
|
String WEB = "web"; |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,84 @@ |
|||||||
|
package org.springblade.common.utils; |
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject; |
||||||
|
import com.google.common.base.Joiner; |
||||||
|
import lombok.RequiredArgsConstructor; |
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
import org.springframework.web.client.RestTemplate; |
||||||
|
import org.springframework.web.util.UriComponentsBuilder; |
||||||
|
|
||||||
|
import java.net.URI; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
/** |
||||||
|
* 天气相关接口 |
||||||
|
* |
||||||
|
* @Description |
||||||
|
* @Author ytl |
||||||
|
* @Date 2022/11/7 0007 12:03 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Component |
||||||
|
@RequiredArgsConstructor |
||||||
|
public class HttpUtil { |
||||||
|
private final RestTemplate restTemplate; |
||||||
|
|
||||||
|
public String doGet(String url, JSONObject params) { |
||||||
|
URI uri = getUriByUrl(url,params); |
||||||
|
String responseEntity = restTemplate.getForEntity(uri, String.class).getBody(); |
||||||
|
return responseEntity; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 通过URL获取URI |
||||||
|
* |
||||||
|
* @param url url |
||||||
|
* @param params 请求参数 |
||||||
|
* @return {@code URI} |
||||||
|
*/ |
||||||
|
private URI getUriByUrl(String url, JSONObject params) { |
||||||
|
String query = "query"; |
||||||
|
if (!params.isEmpty()) { |
||||||
|
// 针对未处理特殊字符参数进行转义处理
|
||||||
|
if (params.containsKey(query)) { |
||||||
|
String replaceQuery = params.getString(query) |
||||||
|
.replace("=", "%3D").replace(" ", "%20") |
||||||
|
.replace("{", "%7B").replace("}", "%7D") |
||||||
|
.replace("\"", "%22").replace("/", "%2F") |
||||||
|
.replace("|", "%7C").replace("+", "%2B") |
||||||
|
.replace("[", "%5B").replace("]", "%5D") |
||||||
|
.replace("<", "%3C").replace(">", "%3E") |
||||||
|
.replace("\n", "%20"); |
||||||
|
params.put(query, replaceQuery); |
||||||
|
} |
||||||
|
url = expandUrl(url, params); |
||||||
|
} |
||||||
|
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url); |
||||||
|
if (params.containsKey(query)) { |
||||||
|
return builder.build(true).toUri(); |
||||||
|
} else { |
||||||
|
return builder.build().encode().toUri(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* URL拼接 |
||||||
|
* |
||||||
|
* @param url 请求URL |
||||||
|
* @param jsonObject JSON对象 |
||||||
|
* @return 拼接之后的URL |
||||||
|
*/ |
||||||
|
private String expandUrl(String url, JSONObject jsonObject) { |
||||||
|
HashMap<String, Object> paramMap = new HashMap<>(16); |
||||||
|
StringBuilder stringBuilder = new StringBuilder(url); |
||||||
|
stringBuilder.append("?"); |
||||||
|
|
||||||
|
Set<String> keys = jsonObject.keySet(); |
||||||
|
keys.forEach(key -> paramMap.put(key, jsonObject.getString(key))); |
||||||
|
String joinStr = Joiner.on("&").withKeyValueSeparator("=").join(paramMap); |
||||||
|
return stringBuilder.append(joinStr).toString(); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,134 @@ |
|||||||
|
package org.springblade.common.utils; |
||||||
|
|
||||||
|
import javax.management.MBeanServer; |
||||||
|
import javax.management.MalformedObjectNameException; |
||||||
|
import javax.management.ObjectName; |
||||||
|
import javax.management.Query; |
||||||
|
import java.lang.management.ManagementFactory; |
||||||
|
import java.net.*; |
||||||
|
import java.util.Enumeration; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
public class IpUtil { |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取本机IP地址 |
||||||
|
* |
||||||
|
* @return |
||||||
|
* @throws SocketException |
||||||
|
*/ |
||||||
|
public static String getIpAddress() throws SocketException { |
||||||
|
String ipString = null; |
||||||
|
Inet4Address inet4Address = getInet4Address(); |
||||||
|
if (inet4Address != null) { |
||||||
|
ipString = inet4Address.getHostAddress(); |
||||||
|
} |
||||||
|
return ipString; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取tomcat容器的http端口 |
||||||
|
* |
||||||
|
* @return |
||||||
|
* @throws MalformedObjectNameException |
||||||
|
*/ |
||||||
|
public static String getTomcatHttpPort() throws MalformedObjectNameException { |
||||||
|
MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer(); |
||||||
|
Set<ObjectName> objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"), |
||||||
|
Query.match(Query.attr("protocol"), Query.value("HTTP/1.1"))); |
||||||
|
String port = objectNames.iterator().next().getKeyProperty("port"); |
||||||
|
return port; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取网络前缀长度, |
||||||
|
* 如果长度为8,则表示掩码是255.0.0.0, |
||||||
|
* 如果长度为16,则表示掩码是255.255.0.0, |
||||||
|
* 如果长度为24,则表示掩码是255.255.255.0, |
||||||
|
* |
||||||
|
* @return |
||||||
|
* @throws UnknownHostException |
||||||
|
* @throws SocketException |
||||||
|
*/ |
||||||
|
public static int getNetworkPrefixLength() throws UnknownHostException, SocketException { |
||||||
|
|
||||||
|
int networkPrefixLength = 0; |
||||||
|
Inet4Address inet4Address = getInet4Address(); |
||||||
|
if (inet4Address != null) { |
||||||
|
NetworkInterface networkInterface = NetworkInterface.getByInetAddress(inet4Address); |
||||||
|
for (InterfaceAddress address : networkInterface.getInterfaceAddresses()) { |
||||||
|
if (address.getAddress() instanceof Inet4Address) { |
||||||
|
networkPrefixLength = address.getNetworkPrefixLength(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
return networkPrefixLength; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取网络掩码255.0.0.0,255.0.0.0,255.0.0.0, |
||||||
|
* |
||||||
|
* @return |
||||||
|
* @throws UnknownHostException |
||||||
|
* @throws SocketException |
||||||
|
*/ |
||||||
|
public static String getSubnet() throws UnknownHostException, SocketException { |
||||||
|
String subnet = null; |
||||||
|
int prefix = getNetworkPrefixLength(); |
||||||
|
if (prefix > 0) { |
||||||
|
if (prefix == 8) { |
||||||
|
subnet = "255.0.0.0"; |
||||||
|
} else if (prefix == 16) { |
||||||
|
subnet = "255.255.0.0"; |
||||||
|
} else if (prefix == 24) { |
||||||
|
subnet = "255.255.255.0"; |
||||||
|
} else if (prefix == 32) { |
||||||
|
subnet = "255.255.255.255"; |
||||||
|
} |
||||||
|
} |
||||||
|
return subnet; |
||||||
|
} |
||||||
|
|
||||||
|
private static Inet4Address getInet4Address() throws SocketException { |
||||||
|
Inet4Address inet4Address = null; |
||||||
|
Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces(); |
||||||
|
InetAddress ip = null; |
||||||
|
while (allNetInterfaces.hasMoreElements()) { |
||||||
|
NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement(); |
||||||
|
// 用于排除回送接口,非虚拟网卡,未在使用中的网络接口.
|
||||||
|
if (netInterface.isLoopback() || netInterface.isVirtual() || !netInterface.isUp()) { |
||||||
|
continue; |
||||||
|
} else { |
||||||
|
Enumeration<InetAddress> addresses = netInterface.getInetAddresses(); |
||||||
|
while (addresses.hasMoreElements()) { |
||||||
|
ip = addresses.nextElement(); |
||||||
|
if (ip != null && ip instanceof Inet4Address) { |
||||||
|
inet4Address = (Inet4Address) ip; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
if (inet4Address != null) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return inet4Address; |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean isIPReachable(String ip) { |
||||||
|
try { |
||||||
|
return InetAddress.getByName(ip).isReachable(5000); // 超时时间为5秒
|
||||||
|
} catch (Exception e) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void main(String[] args) throws SocketException, UnknownHostException { |
||||||
|
System.out.println(getIpAddress()); |
||||||
|
System.out.println(getNetworkPrefixLength()); |
||||||
|
System.out.println(getSubnet()); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,27 @@ |
|||||||
|
package org.springblade.common.utils; |
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean; |
||||||
|
import org.springframework.context.annotation.Configuration; |
||||||
|
import org.springframework.http.client.SimpleClientHttpRequestFactory; |
||||||
|
import org.springframework.web.client.RestTemplate; |
||||||
|
|
||||||
|
/** |
||||||
|
* spring restTemplate配置类 |
||||||
|
* @Description |
||||||
|
* @Author ytl |
||||||
|
* @Date 2022/11/7 0007 12:18 |
||||||
|
*/ |
||||||
|
@Configuration |
||||||
|
public class SpringRestTemplate { |
||||||
|
@Bean |
||||||
|
public static RestTemplate restTemplate() { |
||||||
|
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); |
||||||
|
requestFactory.setConnectTimeout(5000); |
||||||
|
requestFactory.setReadTimeout(5000); |
||||||
|
requestFactory.setOutputStreaming(false); |
||||||
|
|
||||||
|
RestTemplate restTemplate = new RestTemplate(); |
||||||
|
restTemplate.setRequestFactory(requestFactory); |
||||||
|
return restTemplate; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,44 @@ |
|||||||
|
package org.springblade.modules.monitor.controller; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import org.springblade.core.tool.api.R; |
||||||
|
import org.springblade.modules.monitor.service.IConfigMonitorService; |
||||||
|
import org.springblade.modules.monitor.vo.ConfigMonitorVO; |
||||||
|
import org.springframework.web.bind.annotation.GetMapping; |
||||||
|
import org.springframework.web.bind.annotation.RequestMapping; |
||||||
|
import org.springframework.web.bind.annotation.RestController; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
@RestController |
||||||
|
@AllArgsConstructor |
||||||
|
@RequestMapping("/monitor") |
||||||
|
public class MonitorController { |
||||||
|
private final IConfigMonitorService configMonitorService; |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取所有监控设备 |
||||||
|
*/ |
||||||
|
@GetMapping("/tree") |
||||||
|
public R<List<ConfigMonitorVO>> tree(){ |
||||||
|
List<ConfigMonitorVO> list = configMonitorService.tree(); |
||||||
|
return R.data(list); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 判断设备是否正常 |
||||||
|
*/ |
||||||
|
@GetMapping("/findList") |
||||||
|
public void ifFestival(){ |
||||||
|
configMonitorService.updateMonitorInfo(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 定时排查监控沈北状态 |
||||||
|
*/ |
||||||
|
@GetMapping("/monitoringEquip") |
||||||
|
public void monitoringEquip(){ |
||||||
|
configMonitorService.monitoringEquip(); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,102 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are met: |
||||||
|
* |
||||||
|
* Redistributions of source code must retain the above copyright notice, |
||||||
|
* this list of conditions and the following disclaimer. |
||||||
|
* Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* Neither the name of the dreamlu.net developer nor the names of its |
||||||
|
* contributors may be used to endorse or promote products derived from |
||||||
|
* this software without specific prior written permission. |
||||||
|
* Author: Chill 庄骞 (smallchill@163.com) |
||||||
|
*/ |
||||||
|
package org.springblade.modules.monitor.entity; |
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType; |
||||||
|
import com.baomidou.mybatisplus.annotation.TableId; |
||||||
|
import com.baomidou.mybatisplus.annotation.TableName; |
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize; |
||||||
|
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; |
||||||
|
import io.swagger.annotations.ApiModel; |
||||||
|
import io.swagger.annotations.ApiModelProperty; |
||||||
|
import lombok.Data; |
||||||
|
import org.springblade.core.mp.base.BaseEntity; |
||||||
|
|
||||||
|
/** |
||||||
|
* 服务器监控基础配置表 实体类 |
||||||
|
* |
||||||
|
* @author BladeX |
||||||
|
* @since 2022-02-12 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
@TableName("t_config_monitor") |
||||||
|
@ApiModel(value = "ConfigMonitor对象", description = "服务器监控基础配置表 ") |
||||||
|
public class ConfigMonitor extends BaseEntity { |
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L; |
||||||
|
|
||||||
|
/** |
||||||
|
* 主键 |
||||||
|
*/ |
||||||
|
@ApiModelProperty(value = "主键") |
||||||
|
@TableId(value = "id", type = IdType.AUTO) |
||||||
|
private Long id; |
||||||
|
|
||||||
|
/** |
||||||
|
* 父级id |
||||||
|
*/ |
||||||
|
@ApiModelProperty(value = "父级id") |
||||||
|
private Long parentId; |
||||||
|
|
||||||
|
/** |
||||||
|
* 类型 |
||||||
|
*/ |
||||||
|
@ApiModelProperty(value = "类型") |
||||||
|
private String type; |
||||||
|
/** |
||||||
|
* ip |
||||||
|
*/ |
||||||
|
@ApiModelProperty(value = "ip") |
||||||
|
private String ip; |
||||||
|
|
||||||
|
/** |
||||||
|
* 监控类型 |
||||||
|
*/ |
||||||
|
@ApiModelProperty(value = "监控类型") |
||||||
|
private String monitorType; |
||||||
|
|
||||||
|
/** |
||||||
|
* 计算公式 |
||||||
|
*/ |
||||||
|
@ApiModelProperty(value = "计算公式") |
||||||
|
private String formula; |
||||||
|
|
||||||
|
/** |
||||||
|
* 计算结果 |
||||||
|
*/ |
||||||
|
@ApiModelProperty(value = "计算结果") |
||||||
|
private String result; |
||||||
|
|
||||||
|
/** |
||||||
|
* 设备编码 |
||||||
|
*/ |
||||||
|
@ApiModelProperty(value = "设备编码") |
||||||
|
private String equipCode; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 设备类型 |
||||||
|
*/ |
||||||
|
@ApiModelProperty(value = "设备类型") |
||||||
|
private String classCode; |
||||||
|
|
||||||
|
@JsonSerialize( |
||||||
|
using = ToStringSerializer.class |
||||||
|
) |
||||||
|
@ApiModelProperty("创建部门") |
||||||
|
private Long createDept; |
||||||
|
} |
||||||
@ -0,0 +1,42 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are met: |
||||||
|
* |
||||||
|
* Redistributions of source code must retain the above copyright notice, |
||||||
|
* this list of conditions and the following disclaimer. |
||||||
|
* Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* Neither the name of the dreamlu.net developer nor the names of its |
||||||
|
* contributors may be used to endorse or promote products derived from |
||||||
|
* this software without specific prior written permission. |
||||||
|
* Author: Chill 庄骞 (smallchill@163.com) |
||||||
|
*/ |
||||||
|
package org.springblade.modules.monitor.mapper; |
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||||
|
import org.springblade.modules.monitor.entity.ConfigMonitor; |
||||||
|
import org.springblade.modules.monitor.vo.ConfigMonitorVO; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* 服务器监控基础配置表 Mapper 接口 |
||||||
|
* |
||||||
|
* @author BladeX |
||||||
|
* @since 2022-02-12 |
||||||
|
*/ |
||||||
|
public interface ConfigMonitorMapper extends BaseMapper<ConfigMonitor> { |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取树形节点 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
List<ConfigMonitorVO> tree(); |
||||||
|
|
||||||
|
Integer findMqttEquipCount(String updateTime); |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,65 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||||
|
<mapper namespace="org.springblade.modules.monitor.mapper.ConfigMonitorMapper"> |
||||||
|
|
||||||
|
<!-- 通用查询映射结果 --> |
||||||
|
<resultMap id="commonResultMap" type="org.springblade.modules.monitor.entity.ConfigMonitor"> |
||||||
|
<id column="id" property="id"/> |
||||||
|
<result column="parent_id" property="parentId"/> |
||||||
|
<result column="type" property="type"/> |
||||||
|
<result column="ip" property="ip"/> |
||||||
|
<result column="monitor_type" property="monitorType"/> |
||||||
|
<result column="formula" property="formula"/> |
||||||
|
<result column="result" property="result"/> |
||||||
|
<result column="create_time" property="createTime"/> |
||||||
|
<result column="create_user" property="createUser"/> |
||||||
|
<result column="create_dept" property="createDept"/> |
||||||
|
<result column="update_time" property="updateTime"/> |
||||||
|
<result column="update_user" property="updateUser"/> |
||||||
|
<result column="status" property="status"/> |
||||||
|
<result column="is_deleted" property="isDeleted"/> |
||||||
|
</resultMap> |
||||||
|
|
||||||
|
<resultMap id="treeNodeResultMap" type="org.springblade.core.tool.node.TreeNode"> |
||||||
|
<id column="id" property="id"/> |
||||||
|
<result column="parent_id" property="parentId"/> |
||||||
|
<result column="title" property="title"/> |
||||||
|
<result column="value" property="value"/> |
||||||
|
<result column="key" property="key"/> |
||||||
|
<result column="has_children" property="hasChildren"/> |
||||||
|
</resultMap> |
||||||
|
|
||||||
|
<select id="tree" resultMap="treeNodeResultMap" > |
||||||
|
SELECT |
||||||
|
a.id, |
||||||
|
a.parent_id, |
||||||
|
a.type AS title, |
||||||
|
a.status AS "value", |
||||||
|
a.id AS "key", |
||||||
|
( |
||||||
|
SELECT |
||||||
|
CASE WHEN count(1) > 0 THEN 1 ELSE 0 END |
||||||
|
FROM |
||||||
|
t_config_monitor |
||||||
|
WHERE |
||||||
|
parent_id = a.id and is_deleted = 0 |
||||||
|
) AS "has_children" |
||||||
|
FROM |
||||||
|
t_config_monitor a |
||||||
|
WHERE |
||||||
|
a.is_deleted = 0 |
||||||
|
order by a.status |
||||||
|
</select> |
||||||
|
|
||||||
|
<select id="findMqttEquipCount" resultType="java.lang.Integer" > |
||||||
|
SELECT |
||||||
|
count( 1 ) |
||||||
|
FROM |
||||||
|
`t_config_monitor` |
||||||
|
WHERE |
||||||
|
class_code IN ( '0200', '0300', '0600', '0700', '0701', '0702' ) |
||||||
|
AND update_time > #{updateTime} |
||||||
|
</select> |
||||||
|
|
||||||
|
|
||||||
|
</mapper> |
||||||
@ -0,0 +1,43 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are met: |
||||||
|
* |
||||||
|
* Redistributions of source code must retain the above copyright notice, |
||||||
|
* this list of conditions and the following disclaimer. |
||||||
|
* Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* Neither the name of the dreamlu.net developer nor the names of its |
||||||
|
* contributors may be used to endorse or promote products derived from |
||||||
|
* this software without specific prior written permission. |
||||||
|
* Author: Chill 庄骞 (smallchill@163.com) |
||||||
|
*/ |
||||||
|
package org.springblade.modules.monitor.service; |
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService; |
||||||
|
import org.springblade.modules.monitor.entity.ConfigMonitor; |
||||||
|
import org.springblade.modules.monitor.vo.ConfigMonitorVO; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* 服务器监控基础配置表 服务类 |
||||||
|
* |
||||||
|
* @author BladeX |
||||||
|
* @since 2022-02-12 |
||||||
|
*/ |
||||||
|
public interface IConfigMonitorService extends IService<ConfigMonitor> { |
||||||
|
|
||||||
|
public void updateMonitorInfo(); |
||||||
|
|
||||||
|
void monitoringEquip(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 树形结构 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
List<ConfigMonitorVO> tree(); |
||||||
|
} |
||||||
@ -0,0 +1,217 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are met: |
||||||
|
* |
||||||
|
* Redistributions of source code must retain the above copyright notice, |
||||||
|
* this list of conditions and the following disclaimer. |
||||||
|
* Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* Neither the name of the dreamlu.net developer nor the names of its |
||||||
|
* contributors may be used to endorse or promote products derived from |
||||||
|
* this software without specific prior written permission. |
||||||
|
* Author: Chill 庄骞 (smallchill@163.com) |
||||||
|
*/ |
||||||
|
package org.springblade.modules.monitor.service.impl; |
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject; |
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
||||||
|
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; |
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
||||||
|
import lombok.RequiredArgsConstructor; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
import org.apache.commons.lang.StringUtils; |
||||||
|
import org.apache.commons.lang.time.DateFormatUtils; |
||||||
|
import org.apache.commons.lang.time.DateUtils; |
||||||
|
import org.springblade.common.constant.MonitorConstant; |
||||||
|
import org.springblade.common.utils.HttpUtil; |
||||||
|
import org.springblade.common.utils.IpUtil; |
||||||
|
import org.springblade.core.mp.base.BaseEntity; |
||||||
|
import org.springblade.core.tool.node.ForestNodeMerger; |
||||||
|
import org.springblade.core.tool.utils.StringUtil; |
||||||
|
import org.springblade.modules.monitor.entity.ConfigMonitor; |
||||||
|
import org.springblade.modules.monitor.mapper.ConfigMonitorMapper; |
||||||
|
import org.springblade.modules.monitor.service.IConfigMonitorService; |
||||||
|
import org.springblade.modules.monitor.vo.ConfigMonitorVO; |
||||||
|
import org.springframework.beans.factory.annotation.Value; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
import java.util.*; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
/** |
||||||
|
* 服务器监控基础配置表 服务实现类 |
||||||
|
* |
||||||
|
* @author BladeX |
||||||
|
* @since 2022-02-12 |
||||||
|
*/ |
||||||
|
@Service |
||||||
|
@Slf4j |
||||||
|
@RequiredArgsConstructor |
||||||
|
public class ConfigMonitorServiceImpl extends ServiceImpl<ConfigMonitorMapper, ConfigMonitor> implements IConfigMonitorService { |
||||||
|
|
||||||
|
|
||||||
|
@Value("${monitor.url}") |
||||||
|
private String monitorUrl; |
||||||
|
|
||||||
|
private final HttpUtil httpUtil; |
||||||
|
|
||||||
|
@Override |
||||||
|
public void updateMonitorInfo() { |
||||||
|
try { |
||||||
|
LambdaQueryWrapper<ConfigMonitor> queryWrapper = null; |
||||||
|
queryWrapper = new LambdaQueryWrapper<>(); |
||||||
|
queryWrapper.eq(BaseEntity::getIsDeleted,"0"); |
||||||
|
List<ConfigMonitor> list = baseMapper.selectList(queryWrapper); |
||||||
|
if(CollectionUtils.isNotEmpty(list)){ |
||||||
|
for(ConfigMonitor monitor : list){ |
||||||
|
if(StringUtil.isNotBlank(monitor.getIp())&&StringUtil.isNotBlank(monitor.getFormula())){ |
||||||
|
JSONObject params = new JSONObject(); |
||||||
|
params.put("query",monitor.getFormula()); |
||||||
|
String s = httpUtil.doGet(monitorUrl, params); |
||||||
|
String[] strs = s.split("\""); |
||||||
|
String result = strs[strs.length-2]; |
||||||
|
monitor.setResult(result); |
||||||
|
baseMapper.updateById(monitor); |
||||||
|
log.info("调用api结果:"+s); |
||||||
|
log.info("最后获取结果:"+result); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
log.error("获取服务器监控信息报错:" + e.getMessage()); |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void monitoringEquip() { |
||||||
|
//查询所有设备
|
||||||
|
Date nowDate = new Date(); |
||||||
|
Date time = DateUtils.addMinutes(nowDate,-30); |
||||||
|
LambdaQueryWrapper<ConfigMonitor> queryWrapper = new LambdaQueryWrapper<>(); |
||||||
|
queryWrapper.eq(ConfigMonitor::getType, MonitorConstant.EQUIP); |
||||||
|
queryWrapper.eq(BaseEntity::getIsDeleted,0); |
||||||
|
List<ConfigMonitor> list = baseMapper.selectList(queryWrapper); |
||||||
|
//按照父级id分组
|
||||||
|
Map<Long,List<ConfigMonitor>> map = list.stream().collect(Collectors.groupingBy(ConfigMonitor::getParentId)); |
||||||
|
for(Map.Entry<Long,List<ConfigMonitor>> entry : map.entrySet()){ |
||||||
|
Long parentId = entry.getKey(); |
||||||
|
List<ConfigMonitor> monitorList = entry.getValue(); |
||||||
|
//获取更新时间间隔大于30分钟的数据
|
||||||
|
List<ConfigMonitor> breakList = monitorList.stream().filter(item->{ |
||||||
|
return item.getUpdateTime().compareTo(time) < 0; |
||||||
|
}).collect(Collectors.toList()); |
||||||
|
//如果所有设备都坏了,直接排查父级问题;否则修改设备状态为异常
|
||||||
|
//modbus设备排查服务、网关;mqtt设备排查服务、mqtt服务、dtu;bacnet设备是通过广播直连,如果全部设备都有问题,直接排查网络问题;
|
||||||
|
if(breakList.size() == monitorList.size()){ |
||||||
|
List<Long> parentIdList = new ArrayList<>(); |
||||||
|
parentIdList = getParentIdList(parentIdList,parentId); |
||||||
|
Collections.reverse(parentIdList); |
||||||
|
boolean flag = true; |
||||||
|
for(Long id : parentIdList){ |
||||||
|
//通过标识位来判断当前是否应该静默
|
||||||
|
if(flag){ |
||||||
|
LambdaQueryWrapper<ConfigMonitor> wrapper = new LambdaQueryWrapper<>(); |
||||||
|
wrapper.eq(ConfigMonitor::getId,id); |
||||||
|
wrapper.eq(BaseEntity::getIsDeleted,0); |
||||||
|
ConfigMonitor configMonitor = baseMapper.selectOne(wrapper); |
||||||
|
//服务排查
|
||||||
|
if(configMonitor.getType().equals(MonitorConstant.SERVICE) && configMonitor.getResult().equals(MonitorConstant.RESULT)){ |
||||||
|
flag = false; |
||||||
|
configMonitor.setStatus(MonitorConstant.STATUS_2); |
||||||
|
configMonitor.setUpdateTime(nowDate); |
||||||
|
baseMapper.updateById(configMonitor); |
||||||
|
parentId = id; |
||||||
|
continue; |
||||||
|
} |
||||||
|
//mqtt服务排查
|
||||||
|
if(configMonitor.getType().equals(MonitorConstant.MIDDLEWARE) && configMonitor.getMonitorType().equals(MonitorConstant.MQTT)){ |
||||||
|
//通过查询所有mqtt相关设备来判断mqtt服务是否正常
|
||||||
|
int count = baseMapper.findMqttEquipCount(DateFormatUtils.format(time,"yyyy-MM-dd HH:mm:ss")); |
||||||
|
//如果count=0说明所有mqtt相关设备都没取到数,可证明mqtt出现问题
|
||||||
|
if(count == 0){ |
||||||
|
flag = false; |
||||||
|
parentId = id; |
||||||
|
configMonitor.setStatus(MonitorConstant.STATUS_2); |
||||||
|
configMonitor.setUpdateTime(nowDate); |
||||||
|
baseMapper.updateById(configMonitor); |
||||||
|
continue; |
||||||
|
} |
||||||
|
} |
||||||
|
//网关排查 --适用于modbus 空调面板 lora网关;mqtt dtu;http 空开照明 通讯模块;
|
||||||
|
if(configMonitor.getType().equals(MonitorConstant.MIDDLEWARE) && configMonitor.getMonitorType().equals(MonitorConstant.GATEWAY) && StringUtils.isNotEmpty(configMonitor.getIp())){ |
||||||
|
//ping网关ip,如果能ping通,则证明是网关本身有问题,如果ping不通,说明通信有问题
|
||||||
|
boolean isNormal = IpUtil.isIPReachable(configMonitor.getIp()); |
||||||
|
if(isNormal){ |
||||||
|
configMonitor.setStatus(MonitorConstant.STATUS_2); |
||||||
|
}else{ |
||||||
|
configMonitor.setStatus(MonitorConstant.STATUS_3); |
||||||
|
} |
||||||
|
configMonitor.setUpdateTime(nowDate); |
||||||
|
baseMapper.updateById(configMonitor); |
||||||
|
} |
||||||
|
}else{ |
||||||
|
//如果是静默,根据parentId将所有子节点状态改为静默
|
||||||
|
LambdaUpdateWrapper<ConfigMonitor> updateWrapper = new LambdaUpdateWrapper<>(); |
||||||
|
updateWrapper.eq(ConfigMonitor::getParentId,parentId); |
||||||
|
ConfigMonitor configMonitor = new ConfigMonitor(); |
||||||
|
configMonitor.setStatus(MonitorConstant.STATUS_4); |
||||||
|
configMonitor.setUpdateTime(nowDate); |
||||||
|
baseMapper.update(configMonitor,updateWrapper); |
||||||
|
parentId = id; |
||||||
|
} |
||||||
|
} |
||||||
|
//将所有设备状态改为静默
|
||||||
|
breakList.forEach(item ->{ |
||||||
|
item.setStatus(MonitorConstant.STATUS_4); |
||||||
|
item.setUpdateTime(nowDate); |
||||||
|
baseMapper.updateById(item); |
||||||
|
}); |
||||||
|
}else{ |
||||||
|
for(ConfigMonitor configMonitor : breakList){ |
||||||
|
configMonitor.setStatus(MonitorConstant.STATUS_2); |
||||||
|
baseMapper.updateById(configMonitor); |
||||||
|
} |
||||||
|
//将父级id设备状态更新为正常
|
||||||
|
LambdaQueryWrapper<ConfigMonitor> wrapper = new LambdaQueryWrapper<>(); |
||||||
|
wrapper.eq(ConfigMonitor::getId,parentId); |
||||||
|
wrapper.eq(BaseEntity::getIsDeleted,0); |
||||||
|
ConfigMonitor configMonitor = baseMapper.selectOne(wrapper); |
||||||
|
configMonitor.setStatus(MonitorConstant.STATUS_1); |
||||||
|
baseMapper.updateById(configMonitor); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<ConfigMonitorVO> tree() { |
||||||
|
return ForestNodeMerger.merge(baseMapper.tree()); |
||||||
|
} |
||||||
|
|
||||||
|
public List<Long> getParentIdList(List<Long> parentIdList,Long parentId){ |
||||||
|
parentIdList.add(parentId); |
||||||
|
if(parentId != 0){ |
||||||
|
LambdaQueryWrapper<ConfigMonitor> queryWrapper = new LambdaQueryWrapper<>(); |
||||||
|
queryWrapper.eq(ConfigMonitor::getId,parentId); |
||||||
|
queryWrapper.eq(BaseEntity::getIsDeleted,0); |
||||||
|
ConfigMonitor configMonitor = baseMapper.selectOne(queryWrapper); |
||||||
|
parentId = configMonitor.getParentId(); |
||||||
|
//服务器不需要排查,所以只需要到服务层面就可以
|
||||||
|
if(configMonitor.getType().equals(MonitorConstant.SERVICE)){ |
||||||
|
return parentIdList; |
||||||
|
} |
||||||
|
getParentIdList(parentIdList,parentId); |
||||||
|
} |
||||||
|
return parentIdList; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,25 @@ |
|||||||
|
package org.springblade.modules.monitor.task; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import org.springblade.modules.monitor.service.IConfigMonitorService; |
||||||
|
import org.springframework.scheduling.annotation.Scheduled; |
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
@Component |
||||||
|
@AllArgsConstructor |
||||||
|
public class MonitorTaskJob { |
||||||
|
private final IConfigMonitorService configMonitorService; |
||||||
|
|
||||||
|
@Scheduled(cron ="0 0 0 1/1 * ? ") |
||||||
|
public void updateMonitorInfo(){ |
||||||
|
configMonitorService.updateMonitorInfo(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Scheduled(cron ="0 0/5 * * * ? ") |
||||||
|
public void monitoringEquip(){ |
||||||
|
configMonitorService.monitoringEquip(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,64 @@ |
|||||||
|
|
||||||
|
package org.springblade.modules.monitor.vo; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude; |
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize; |
||||||
|
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; |
||||||
|
import io.swagger.annotations.ApiModel; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.EqualsAndHashCode; |
||||||
|
import org.springblade.core.tool.node.INode; |
||||||
|
import org.springblade.modules.monitor.entity.ConfigMonitor; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* 视图实体类 |
||||||
|
* |
||||||
|
* @author Chill |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
@EqualsAndHashCode(callSuper = true) |
||||||
|
@ApiModel(value = "ConfigMonitorVO对象", description = "ConfigMonitorVO对象") |
||||||
|
public class ConfigMonitorVO extends ConfigMonitor implements INode<ConfigMonitorVO> { |
||||||
|
private static final long serialVersionUID = 1L; |
||||||
|
|
||||||
|
/** |
||||||
|
* 主键ID |
||||||
|
*/ |
||||||
|
@JsonSerialize(using = ToStringSerializer.class) |
||||||
|
private Long id; |
||||||
|
|
||||||
|
/** |
||||||
|
* 父节点ID |
||||||
|
*/ |
||||||
|
@JsonSerialize(using = ToStringSerializer.class) |
||||||
|
private Long parentId; |
||||||
|
|
||||||
|
/** |
||||||
|
* 子孙节点 |
||||||
|
*/ |
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY) |
||||||
|
private List<ConfigMonitorVO> children; |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否有子孙节点 |
||||||
|
*/ |
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY) |
||||||
|
private Boolean hasChildren; |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<ConfigMonitorVO> getChildren() { |
||||||
|
if (this.children == null) { |
||||||
|
this.children = new ArrayList<>(); |
||||||
|
} |
||||||
|
return this.children; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 上级机构 |
||||||
|
*/ |
||||||
|
private String parentName; |
||||||
|
|
||||||
|
} |
||||||
Loading…
Reference in new issue