先下载sigar:http://sigar.hyperic.com/
将sigar-bin\lib目录下文件放到classpath中
1 pom
<dependency>
<groupId>org.fusesource</groupId>
<artifactId>sigar</artifactId>
<version>${sigar.version}</version>
</dependency>
2 配置到spring
@Slf4j
@Configuration
public class SigarConfig {
static {
try {
initSigar();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 初始化sigar的配置文件
*/
public static void initSigar() throws IOException {
SigarLoader loader = new SigarLoader(Sigar.class);
String lib = null;
try {
lib = loader.getLibraryName();
log.info("init sigar so文件====================="+lib);
} catch (ArchNotSupportedException var7) {
log.error("initSigar() error:{}",var7.getMessage());
}
ResourceLoader resourceLoader = new DefaultResourceLoader();
Resource resource = resourceLoader.getResource("classpath:/sigar.so/" + lib);
if (resource.exists()) {
InputStream is = resource.getInputStream();
File tempDir = new File("./log");
if (!tempDir.exists()){
tempDir.mkdirs();
}
BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(new File(tempDir, lib), false));
int lentgh = 0;
while ((lentgh = is.read()) != -1){
os.write(lentgh);
}
is.close();
os.close();
System.setProperty("org.hyperic.sigar.path", tempDir.getCanonicalPath());
}
}
}
3 api
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.hyperic.sigar.*;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 服务器监控
*
* @author 111
* @since 20200401
*/
@Slf4j
@RestController
@RequestMapping("/test")
public class Test{
@Resource
private RedisTemplate redisTemplate;
@ApiOperation(value = "监控信息", notes = "监控信息")
@GetMapping("/test")
public MonitorVO info() throws Exception {
MonitorVO monitorVO = new MonitorVO();
Sigar sigar = new Sigar();
monitorVO.setCpu(cpuPerc(sigar));
monitorVO.setMemory(memory(sigar));
monitorVO.setDisk(file(sigar));
// 网络流量:查询最近
List<NetVO> list = redisTemplate.opsForList().range(Constant.MONITOR_NET, Constant.ZERO_LONG, (Constant.MONITOR_NET_GET - 1));
monitorVO.setNetList(list);
try{
sigar.close();
}catch (Exception e){
log.error("sigar close失败"+e.getMessage(), e);
}
return monitorVO;
}
/**
* 内存
*/
private MemoryVO memory(Sigar sigar) throws SigarException {
MemoryVO memoryVO = new MemoryVO();
// 使用sigar获取内存
Mem mem = sigar.getMem();
double memTotal = mem.getTotal();
double memRam = mem.getRam();
double memUsed = mem.getActualUsed();
double memFree = mem.getActualFree();
double memUsedPerc = mem.getUsedPercent();
memoryVO.setMemory(String.format("%.2f", memTotal / 1024 / 1024 / 1024) + "GB");
memoryVO.setMemRam(String.format("%.2f", memRam / 1024) + "GB");
memoryVO.setMemUsed(String.format("%.2f", memUsed / 1024 / 1024 / 1024) + "GB");
memoryVO.setMemFrees(String.format("%.2f", memFree / 1024 / 1024 / 1024) + "GB");
memoryVO.setMemoryUsage(String.format("%.2f", memUsedPerc) + "%");
return memoryVO;
}
/**
* cpu使用率
*/
private static CpuVO cpuPerc(Sigar sigar) throws SigarException {
CpuPerc cpu = sigar.getCpuPerc();
CpuVO cpuVO = new CpuVO();
cpuVO.setUser(CpuPerc.format(cpu.getUser()));
cpuVO.setSys(CpuPerc.format(cpu.getSys()));
cpuVO.setWait(CpuPerc.format(cpu.getWait()));
cpuVO.setNice(CpuPerc.format(cpu.getNice()));
cpuVO.setIdle(CpuPerc.format(cpu.getIdle()));
cpuVO.setCombined(CpuPerc.format(cpu.getCombined()));
return cpuVO;
}
private DiskVO file(Sigar sigar) throws Exception {
DiskVO diskVO = new DiskVO();
long total = 0L;
long free = 0L;
long avail = 0L;
long used = 0L;
FileSystem fslist[] = sigar.getFileSystemList();
for (int i = 0; i < fslist.length; i++) {
FileSystem fs = fslist[i];
FileSystemUsage usage = null;
try {
usage = sigar.getFileSystemUsage(fs.getDirName());
} catch (SigarException e) {
log.info("{}-- 不可用",fs.getDirName());
continue;
}
switch (fs.getType()) {
case 0:
break;
case 1:
break;
case 2:
// 文件系统总大小
total += usage.getTotal();
// 文件系统剩余大小
free += usage.getFree();
// 文件系统可用大小
avail += usage.getAvail();
// 文件系统已经使用量
used += usage.getUsed();
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
default:
break;
}
}
diskVO.setTotal(String.format("%.2f", total / 1024 / 1024D) + "GB");
diskVO.setFree(String.format("%.2f", free / 1024 / 1024D) + "GB");
diskVO.setAvail(String.format("%.2f", avail / 1024 / 1024D) + "GB");
diskVO.setUsed(String.format("%.2f", used / 1024 / 1024D) + "GB");
diskVO.setUsePercent(String.format("%.2f", 100D * used / total) + "%");
return diskVO;
}
}
4 定时任务:定时将网络流量写入到redis
import cn.hutool.core.date.SystemClock;
import lombok.extern.slf4j.Slf4j;
import org.hyperic.sigar.NetInterfaceConfig;
import org.hyperic.sigar.NetInterfaceStat;
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import javax.annotation.Resource;
import java.util.Date;
import java.util.Objects;
/**
* 网络net流量定时任务
*
*/
@Slf4j
@Configuration
@EnableScheduling
public class NetScheduleTask {
@Resource
private RedisTemplate redisTemplate;
@Value("${monitor.switch}")
private Boolean monitorSwitch;
@Scheduled(cron = "${monitor.cron}")
private void task() {
if(isLocal()){
// 此处简短实现不执行。 实际上定时任务还在执行
log.info("window环境,停止定时任务……");
return;
}
if(monitorSwitch){
long start = SystemClock.now();
log.info("网络net流量定时任务start……");
run();
log.info("网络net流量定时任务end,耗时:{}ms……", (SystemClock.now()-start));
}
}
/**
* 执行
*/
private void run(){
Date now = new Date();
// 获取当前时间下的网络状态
NetVO net = null;
try{
net = net();
}catch (Exception e){
log.error("定时任务异常:{}", e.getMessage());
return;
}
net.setCurrentTime(now);
// 取出redis数据
Long size = redisTemplate.opsForList().size("redis的key");
if(Objects.isNull(size) || 0 == size){
// 说明list为空
net.setCurrentRxPackets(0L);
net.setCurrentTxPackets(0L);
net.setCurrentRxBytes(0L);
net.setCurrentTxBytes(0L);
redisTemplate.opsForList().leftPush("redis的key", net);
return;
}
// 小于限制的长度时,取出最后一个:计算本次取数
Object index = redisTemplate.opsForList().index("redis的key", 0L);
NetVO netVO = (NetVO)index;
net.setCurrentRxPackets(net.getRxPackets() - netVO.getRxPackets());
net.setCurrentTxPackets(net.getTxPackets() - netVO.getTxPackets());
net.setCurrentRxBytes(net.getRxBytes() - netVO.getRxBytes());
net.setCurrentTxBytes(net.getTxBytes() - netVO.getTxBytes());
redisTemplate.opsForList().leftPush("redis的key", net);
// 长度限制
if(3000 <= size){
redisTemplate.opsForList().trim("redis的key", 0L, (3000 -1));
}
}
/**
* 主机网络信息
*/
private NetVO net() throws SigarException {
NetVO netVO = new NetVO();
long rxPackets = 0L, txPackets = 0L, rxBytes = 0L, txBytes = 0L;
Sigar sigar = new Sigar();
String ifNames[] = sigar.getNetInterfaceList();
for (int i = 0; i < ifNames.length; i++) {
String name = ifNames[i];
NetInterfaceConfig ifconfig = sigar.getNetInterfaceConfig(name);
if ((ifconfig.getFlags() & 1L) <= 0L) {
continue;
}
NetInterfaceStat ifstat = sigar.getNetInterfaceStat(name);
// 接收的总包裹数
rxPackets += ifstat.getRxPackets();
// 发送的总包裹数
txPackets += ifstat.getTxPackets();
//接收到的总字节数
rxBytes += ifstat.getRxBytes();
//发送的总字节数
txBytes += ifstat.getTxBytes();
}
netVO.setRxPackets(rxPackets);
netVO.setTxPackets(txPackets);
netVO.setRxBytes(rxBytes);
netVO.setTxBytes(txBytes);
return netVO;
}
/**
* 是否window运行,true代表window
*/
public static boolean isLocal(){
return System.getProperties().getProperty("os.name").toUpperCase().contains("WINDOWS");
}
}
5 VO
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 监控vo
*
*/
@Data
public class MonitorVO {
@ApiModelProperty("cpu")
private CpuVO cpu;
@ApiModelProperty("内存")
private MemoryVO memory;
@ApiModelProperty("硬盘")
private DiskVO disk;
@ApiModelProperty("网络流量")
private List<NetVO> netList;
}
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* cpu vo
*
*/
@Data
public class CpuVO {
@ApiModelProperty("CPU用户使用率")
private String user;
@ApiModelProperty("CPU系统使用率")
private String sys;
@ApiModelProperty("CPU当前等待率")
private String wait;
@ApiModelProperty("CPU当前错误率")
private String nice;
@ApiModelProperty("CPU当前空闲率")
private String idle;
@ApiModelProperty("CPU总的使用率")
private String combined;
}
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 内存 vo
*
*/
@Data
public class MemoryVO {
@ApiModelProperty("内存总量")
private String memory;
@ApiModelProperty("内存使用量")
private String memRam;
@ApiModelProperty("使用中")
private String memUsed;
@ApiModelProperty("可用")
private String memFrees;
@ApiModelProperty("内存使用率")
private String memoryUsage;
}
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 内存 vo
*
*/
@Data
public class DiskVO {
@ApiModelProperty("总容量")
private String total;
@ApiModelProperty("剩余大小")
private String free;
@ApiModelProperty("可用大小")
private String avail;
@ApiModelProperty("已使用大小")
private String used;
@ApiModelProperty("资源利用率")
private String usePercent;
}
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* 流量 vo
*
*/
@Data
public class NetVO {
@ApiModelProperty("当前时间")
private Date currentTime;
@ApiModelProperty("当前接收包裹数")
private Long currentRxPackets;
@ApiModelProperty("当前发送包裹数")
private Long currentTxPackets;
@ApiModelProperty("当前接收字节数")
private Long currentRxBytes;
@ApiModelProperty("当前发送字节数")
private Long currentTxBytes;
@ApiModelProperty("接收总包裹数")
private Long rxPackets;
@ApiModelProperty("发送总包裹数")
private Long txPackets;
@ApiModelProperty("接收总字节数")
private Long rxBytes;
@ApiModelProperty("发送总字节数")
private Long txBytes;
}
6 返回结果示例
{
"code": 200,
"data": {
"cpu": {
"user": "5.0%",
"sys": "0.7%",
"wait": "0.0%",
"nice": "0.0%",
"idle": "94.1%",
"combined": "5.8%"
},
"memory": {
"memory": "7.89GB",
"memRam": "7.89GB",
"memUsed": "4.80GB",
"memFrees": "3.08GB",
"memoryUsage": "60.89%"
},
"disk": {
"total": "1050.75GB",
"free": "936.43GB",
"avail": "936.43GB",
"used": "114.32GB",
"usePercent": "10.88%"
},
"netList": [
{
"currentTime": "2020-04-01 13:27:00",
"currentRxPackets": 359,
"currentTxPackets": 503,
"currentRxBytes": 85184,
"currentTxBytes": 102932,
"rxPackets": 51143,
"txPackets": 73517,
"rxBytes": 7123010,
"txBytes": 12409005
},
{
"currentTime": "2020-04-01 13:26:30",
"currentRxPackets": 407,
"currentTxPackets": 561,
"currentRxBytes": 166228,
"currentTxBytes": 147497,
"rxPackets": 50784,
"txPackets": 73014,
"rxBytes": 7037826,
"txBytes": 12306073
}
]
},
"msg": "OK"
}
补充:
VO中的NetVO,包裹和字节类型可优化改造为BigInteger