完成运行时数据上报

This commit is contained in:
柏码の讲师 2023-12-11 16:28:36 +08:00
parent c40a66802a
commit 13a15db7d2
11 changed files with 190 additions and 3 deletions

View File

@ -32,6 +32,10 @@
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.alibaba.fastjson2</groupId> <groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId> <artifactId>fastjson2</artifactId>

View File

@ -0,0 +1,30 @@
package com.example.config;
import com.example.task.MonitorJobBean;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Slf4j
@Configuration
public class QuartzConfiguration {
@Bean
public JobDetail jobDetailFactoryBean() {
return JobBuilder.newJob(MonitorJobBean.class)
.withIdentity("monitor-task")
.storeDurably()
.build();
}
@Bean
public Trigger cronTriggerFactoryBean(JobDetail detail) {
CronScheduleBuilder cron = CronScheduleBuilder.cronSchedule("*/10 * * * * ?");
return TriggerBuilder.newTrigger()
.forJob(detail)
.withIdentity("monitor-trigger")
.withSchedule(cron)
.build();
}
}

View File

@ -0,0 +1,17 @@
package com.example.entity;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class RuntimeDetail {
long timestamp;
double cpuUsage;
double memoryUsage;
double diskUsage;
double networkUpload;
double networkDownload;
double diskRead;
double diskWrite;
}

View File

@ -0,0 +1,26 @@
package com.example.task;
import com.example.entity.RuntimeDetail;
import com.example.utils.MonitorUtils;
import com.example.utils.NetUtils;
import jakarta.annotation.Resource;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
@Component
public class MonitorJobBean extends QuartzJobBean {
@Resource
MonitorUtils monitor;
@Resource
NetUtils net;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
RuntimeDetail runtimeDetail = monitor.monitorRuntimeDetail();
net.updateRuntimeDetails(runtimeDetail);
}
}

View File

@ -1,9 +1,12 @@
package com.example.utils; package com.example.utils;
import com.example.entity.BaseDetail; import com.example.entity.BaseDetail;
import com.example.entity.RuntimeDetail;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import oshi.SystemInfo; import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.HWDiskStore;
import oshi.hardware.HardwareAbstractionLayer; import oshi.hardware.HardwareAbstractionLayer;
import oshi.hardware.NetworkIF; import oshi.hardware.NetworkIF;
import oshi.software.os.OperatingSystem; import oshi.software.os.OperatingSystem;
@ -12,6 +15,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.NetworkInterface; import java.net.NetworkInterface;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date;
import java.util.Objects; import java.util.Objects;
import java.util.Properties; import java.util.Properties;
@ -40,6 +44,62 @@ public class MonitorUtils {
.setIp(ip); .setIp(ip);
} }
public RuntimeDetail monitorRuntimeDetail() {
double statisticTime = 0.5;
try {
HardwareAbstractionLayer hardware = info.getHardware();
NetworkIF networkInterface = Objects.requireNonNull(this.findNetworkInterface(hardware));
CentralProcessor processor = hardware.getProcessor();
double upload = networkInterface.getBytesSent(), download = networkInterface.getBytesRecv();
double read = hardware.getDiskStores().stream().mapToLong(HWDiskStore::getReadBytes).sum();
double write = hardware.getDiskStores().stream().mapToLong(HWDiskStore::getWriteBytes).sum();
long[] ticks = processor.getSystemCpuLoadTicks();
Thread.sleep((long) (statisticTime * 1000));
networkInterface = Objects.requireNonNull(this.findNetworkInterface(hardware));
upload = (networkInterface.getBytesSent() - upload) / statisticTime;
download = (networkInterface.getBytesRecv() - download) / statisticTime;
read = (hardware.getDiskStores().stream().mapToLong(HWDiskStore::getReadBytes).sum() - read) / statisticTime;
write = (hardware.getDiskStores().stream().mapToLong(HWDiskStore::getWriteBytes).sum() - write) / statisticTime;
double memory = (hardware.getMemory().getTotal() - hardware.getMemory().getAvailable()) / 1024.0 / 1024 / 1024;
double disk = Arrays.stream(File.listRoots())
.mapToLong(file -> file.getTotalSpace() - file.getFreeSpace()).sum() / 1024.0 / 1024 / 1024;
return new RuntimeDetail()
.setCpuUsage(this.calculateCpuUsage(processor, ticks))
.setMemoryUsage(memory)
.setDiskUsage(disk)
.setNetworkUpload(upload / 1024)
.setNetworkDownload(download / 1024)
.setDiskRead(read / 1024/ 1024)
.setDiskWrite(write / 1024 / 1024)
.setTimestamp(new Date().getTime());
} catch (Exception e) {
log.error("读取运行时数据出现问题", e);
}
return null;
}
private double calculateCpuUsage(CentralProcessor processor, long[] prevTicks) {
long[] ticks = processor.getSystemCpuLoadTicks();
long nice = ticks[CentralProcessor.TickType.NICE.getIndex()]
- prevTicks[CentralProcessor.TickType.NICE.getIndex()];
long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()]
- prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
long softIrq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()]
- prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()]
- prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()]
- prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
long cUser = ticks[CentralProcessor.TickType.USER.getIndex()]
- prevTicks[CentralProcessor.TickType.USER.getIndex()];
long ioWait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()]
- prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()]
- prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
long totalCpu = cUser + nice + cSys + idle + ioWait + irq + softIrq + steal;
return (cSys + cUser) * 1.0 / totalCpu;
}
private NetworkIF findNetworkInterface(HardwareAbstractionLayer hardware) { private NetworkIF findNetworkInterface(HardwareAbstractionLayer hardware) {
try { try {
for (NetworkIF network : hardware.getNetworkIFs()) { for (NetworkIF network : hardware.getNetworkIFs()) {

View File

@ -4,12 +4,12 @@ import com.alibaba.fastjson2.JSONObject;
import com.example.entity.BaseDetail; import com.example.entity.BaseDetail;
import com.example.entity.ConnectionConfig; import com.example.entity.ConnectionConfig;
import com.example.entity.Response; import com.example.entity.Response;
import com.example.entity.RuntimeDetail;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.net.http.HttpClient; import java.net.http.HttpClient;
import java.net.http.HttpRequest; import java.net.http.HttpRequest;
@ -62,6 +62,13 @@ public class NetUtils {
} }
} }
public void updateRuntimeDetails(RuntimeDetail detail) {
Response response = this.doPost("/runtime", detail);
if(!response.success()) {
log.warn("更新运行时状态时,接收到服务端的异常响应内容: {}", response.message());
}
}
private Response doPost(String url, Object data) { private Response doPost(String url, Object data) {
try { try {
String rawData = JSONObject.from(data).toJSONString(); String rawData = JSONObject.from(data).toJSONString();

View File

@ -3,6 +3,7 @@ package com.example.controller;
import com.example.entity.RestBean; import com.example.entity.RestBean;
import com.example.entity.dto.Client; import com.example.entity.dto.Client;
import com.example.entity.vo.request.ClientDetailVO; import com.example.entity.vo.request.ClientDetailVO;
import com.example.entity.vo.request.RuntimeDetailVO;
import com.example.service.ClientService; import com.example.service.ClientService;
import com.example.utils.Const; import com.example.utils.Const;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@ -28,4 +29,11 @@ public class ClientController {
service.updateClientDetail(vo, client); service.updateClientDetail(vo, client);
return RestBean.success(); return RestBean.success();
} }
@PostMapping("/runtime")
public RestBean<Void> updateRuntimeDetails(@RequestAttribute(Const.ATTR_CLIENT) Client client,
@RequestBody @Valid RuntimeDetailVO vo) {
service.updateRuntimeDetail(vo, client);
return RestBean.success();
}
} }

View File

@ -0,0 +1,25 @@
package com.example.entity.vo.request;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class RuntimeDetailVO {
@NotNull
long timestamp;
@NotNull
double cpuUsage;
@NotNull
double memoryUsage;
@NotNull
double diskUsage;
@NotNull
double networkUpload;
@NotNull
double networkDownload;
@NotNull
double diskRead;
@NotNull
double diskWrite;
}

View File

@ -29,7 +29,7 @@ public class RequestLogFilter extends OncePerRequestFilter {
@Resource @Resource
SnowflakeIdGenerator generator; SnowflakeIdGenerator generator;
private final Set<String> ignores = Set.of("/swagger-ui", "/v3/api-docs"); private final Set<String> ignores = Set.of("/swagger-ui", "/v3/api-docs", "/monitor/runtime");
@Override @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

View File

@ -3,6 +3,7 @@ package com.example.service;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.example.entity.dto.Client; import com.example.entity.dto.Client;
import com.example.entity.vo.request.ClientDetailVO; import com.example.entity.vo.request.ClientDetailVO;
import com.example.entity.vo.request.RuntimeDetailVO;
public interface ClientService extends IService<Client> { public interface ClientService extends IService<Client> {
String registerToken(); String registerToken();
@ -10,4 +11,5 @@ public interface ClientService extends IService<Client> {
Client findClientByToken(String token); Client findClientByToken(String token);
boolean verifyAndRegister(String token); boolean verifyAndRegister(String token);
void updateClientDetail(ClientDetailVO vo, Client client); void updateClientDetail(ClientDetailVO vo, Client client);
void updateRuntimeDetail(RuntimeDetailVO vo, Client client);
} }

View File

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.entity.dto.Client; import com.example.entity.dto.Client;
import com.example.entity.dto.ClientDetail; import com.example.entity.dto.ClientDetail;
import com.example.entity.vo.request.ClientDetailVO; import com.example.entity.vo.request.ClientDetailVO;
import com.example.entity.vo.request.RuntimeDetailVO;
import com.example.mapper.ClientDetailMapper; import com.example.mapper.ClientDetailMapper;
import com.example.mapper.ClientMapper; import com.example.mapper.ClientMapper;
import com.example.service.ClientService; import com.example.service.ClientService;
@ -76,9 +77,16 @@ public class ClientServiceImpl extends ServiceImpl<ClientMapper, Client> impleme
} }
} }
private Map<Integer, RuntimeDetailVO> currentRuntime = new ConcurrentHashMap<>();
@Override
public void updateRuntimeDetail(RuntimeDetailVO vo, Client client) {
currentRuntime.put(client.getId(), vo);
System.out.println(vo);
}
private void addClientCache(Client client) { private void addClientCache(Client client) {
clientIdCache.put(client.getId(), client); clientIdCache.put(client.getId(), client);
clientTokenCache.put(client.getToken(), client);
} }
private int randomClientId() { private int randomClientId() {