使用oshi获取服务器的参数信息

2024-06-23 02:32

本文主要是介绍使用oshi获取服务器的参数信息,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景

最近我们负责的一个电网行业的业务平台,出现了一个非常奇葩的问题。这个项目涉及到软件平台厂家、服务器厂家、存储厂家以及真正的用户等四方关系,而我们主要负责软件平台的研发工作。平台正常运行了2年多了,去年年底存储盘阵中出现历史巡检数据丢失或者无法使用的诡异问题,软件、服务以及存储各方对根据运行日志进行了审计,各自都说没有问题,接着,请了比较权威的第三方测评单位,召开了5次讨论会,也没有分析出真正的原因,给出了一个***看似非常弱智的原因***,最后只能几家摊钱恢复数据(因为每家只能证明自身没有问题,并不能证明问题真正的原因是什么环节,所以只能摊钱)。

解决方案

俗话说:“吃一堑长一智”。业务平台作为应用层,是最接近用户的。平台一出问题,给用户的第一印象就是这个平台太烂了,又出问题了。为了以后出现问题,软件平台可以对问题进行实时追踪和根据历史数据运行记录进行审计,便于更快速的缩小问题范围,更精确的定位问题。
我们计划从数据监控和服务监控两个大维度进行实时监控;从巡检数据的上传、下载以及变更等操作详细记录用户的操作痕迹。

实时获取服务器的参数信息

介绍

OSHI是Java的免费的基于JNA的(本机)操作系统和硬件信息库。它不需要安装任何其他本机库,并且旨在提供一种跨平台的实现来检索系统信息,例如OS版本,进程,内存和CPU使用率,磁盘和分区,设备,传感器等。

oshi支持的功能

  • 计算机系统和固件,底板
  • 操作系统和版本/内部版本
  • 物理(核心)和逻辑(超线程)CPU
  • 系统和每个处理器的负载百分比和滴答计数器
  • CPU正常运行时间,进程和线程
  • 进程正常运行时间,CPU,内存使用率
  • 已使用/可用的物理和虚拟内存
  • 挂载的文件系统(类型,可用空间和总空间)
  • 磁盘驱动器(型号,序列号,大小)和分区
  • 网络接口(IP,带宽输入/输出)
  • 电池状态(电量百分比,剩余时间)
  • 连接的显示器(带有EDID信息)
  • USB设备
  • 传感器(温度,风扇速度,电压)

具体实现

我们的业务平台是采用Spring boot开发的,故此主要是通过Springboot集成oshi来获取需要实时关注的参数信息。

1、引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 获取系统信息 --><dependency><groupId>com.github.oshi</groupId><artifactId>oshi-core</artifactId><version>3.9.1</version></dependency><!--常用工具类 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency><!-- 阿里JSON解析器 --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.47</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
2、分别定义参数模型

我们主要关注主服务器的CPU、内存、以及所挂在的存储盘阵的空间容量使用情况等信息,具体模型如下:

2.1 CPU模型
public class Cpu
{/*** 核心数*/private int cpuNum;/*** CPU总的使用率*/private double total;/*** CPU系统使用率*/private double sys;/*** CPU用户使用率*/private double used;/*** CPU当前等待率*/private double wait;/*** CPU当前空闲率*/private double free;public int getCpuNum(){return cpuNum;}public void setCpuNum(int cpuNum){this.cpuNum = cpuNum;}public double getTotal(){return Arith.round(Arith.mul(total, 100), 2);}public void setTotal(double total){this.total = total;}public double getSys(){return Arith.round(Arith.mul(sys / total, 100), 2);}public void setSys(double sys){this.sys = sys;}public double getUsed(){return Arith.round(Arith.mul(used / total, 100), 2);}public void setUsed(double used){this.used = used;}public double getWait(){return Arith.round(Arith.mul(wait / total, 100), 2);}public void setWait(double wait){this.wait = wait;}public double getFree(){return Arith.round(Arith.mul(free / total, 100), 2);}public void setFree(double free){this.free = free;}@Overridepublic String toString() {return "Cpu{" +"cpuNum=" + getCpuNum() +", total=" + getTotal() +", sys=" + getSys() +", used=" + getUsed() +", wait=" + getWait() +", free=" + getFree() +'}';}
}
2.2 内存模型
public class Mem
{/*** 内存总量*/private double total;/*** 已用内存*/private double used;/*** 剩余内存*/private double free;public double getTotal(){return Arith.div(total, (1024 * 1024 * 1024), 2);}public void setTotal(long total){this.total = total;}public double getUsed(){return Arith.div(used, (1024 * 1024 * 1024), 2);}public void setUsed(long used){this.used = used;}public double getFree(){return Arith.div(free, (1024 * 1024 * 1024), 2);}public void setFree(long free){this.free = free;}public double getUsage(){return Arith.mul(Arith.div(used, total, 4), 100);}@Overridepublic String toString() {return "Mem{" +"total=" + getTotal() +", used=" + getUsed() +", free=" + getFree() +'}';}
}
2.3 存储盘阵模型
public class SysFile
{/*** 盘符路径*/private String dirName;/*** 盘符类型*/private String sysTypeName;/*** 文件类型*/private String typeName;/*** 总大小*/private String total;/*** 剩余大小*/private String free;/*** 已经使用量*/private String used;/*** 资源的使用率*/private double usage;@Overridepublic String toString() {return "SysFile{" +"dirName='" + dirName + '\'' +", sysTypeName='" + sysTypeName + '\'' +", typeName='" + typeName + '\'' +", total='" + total + '\'' +", free='" + free + '\'' +", used='" + used + '\'' +", usage=" + usage +'}';}
}
2.4 获取服务器参数的主体方法
public class Server
{private static final int OSHI_WAIT_SECOND = 1000;/*** CPU相关信息*/private Cpu cpu = new Cpu();/*** 內存相关信息*/private Mem mem = new Mem();/*** 服务器相关信息*/private Sys sys = new Sys();/*** 磁盘相关信息*/private List<SysFile> sysFiles = new LinkedList<>();public Cpu getCpu(){return cpu;}public void setCpu(Cpu cpu){this.cpu = cpu;}public Mem getMem(){return mem;}public void setMem(Mem mem){this.mem = mem;}public Sys getSys(){return sys;}public void setSys(Sys sys){this.sys = sys;}public List<SysFile> getSysFiles(){return sysFiles;}public void setSysFiles(List<SysFile> sysFiles){this.sysFiles = sysFiles;}public void copyTo() throws Exception{SystemInfo si = new SystemInfo();HardwareAbstractionLayer hal = si.getHardware();setCpuInfo(hal.getProcessor());setMemInfo(hal.getMemory());setSysInfo();setSysFiles(si.getOperatingSystem());}/*** 设置CPU信息*/private void setCpuInfo(CentralProcessor processor){// CPU信息long[] prevTicks = processor.getSystemCpuLoadTicks();Util.sleep(OSHI_WAIT_SECOND);long[] ticks = processor.getSystemCpuLoadTicks();long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()];long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()];long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()];long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()];long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()];long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()];long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()];long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()];long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;cpu.setCpuNum(processor.getLogicalProcessorCount());cpu.setTotal(totalCpu);cpu.setSys(cSys);cpu.setUsed(user);cpu.setWait(iowait);cpu.setFree(idle);}/*** 设置内存信息*/private void setMemInfo(GlobalMemory memory){mem.setTotal(memory.getTotal());mem.setUsed(memory.getTotal() - memory.getAvailable());mem.setFree(memory.getAvailable());}/*** 设置服务器信息*/private void setSysInfo(){Properties props = System.getProperties();sys.setComputerName(IpUtils.getHostName());sys.setComputerIp(IpUtils.getHostIp());sys.setOsName(props.getProperty("os.name"));sys.setOsArch(props.getProperty("os.arch"));sys.setUserDir(props.getProperty("user.dir"));}/*** 设置磁盘信息*/private void setSysFiles(OperatingSystem os){FileSystem fileSystem = os.getFileSystem();OSFileStore[] fsArray = fileSystem.getFileStores();for (OSFileStore fs : fsArray){long free = fs.getUsableSpace();long total = fs.getTotalSpace();long used = total - free;SysFile sysFile = new SysFile();sysFile.setDirName(fs.getMount());sysFile.setSysTypeName(fs.getType());sysFile.setTypeName(fs.getName());sysFile.setTotal(convertFileSize(total));sysFile.setFree(convertFileSize(free));sysFile.setUsed(convertFileSize(used));sysFile.setUsage(Arith.mul(Arith.div(used, total, 4), 100));System.out.println(sysFile);sysFiles.add(sysFile);}}/*** 字节转换* * @param size 字节大小* @return 转换后值*/public String convertFileSize(long size){long kb = 1024;long mb = kb * 1024;long gb = mb * 1024;if (size >= gb){return String.format("%.1f GB", (float) size / gb);}else if (size >= mb){float f = (float) size / mb;return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f);}else if (size >= kb){float f = (float) size / kb;return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f);}else{return String.format("%d B", size);}}
}
2.5 控制层
/*** 服务器监控* */
@RestController
@RequestMapping(value = "/monitor/server")
public class ServerController{@GetMapping(value = "list")public String server() throws Exception{JSONObject jsonObject = new JSONObject();Server server = new Server();server.copyTo();return JSON.toJSONString(server);}
}
2.6 运行结果
2020-03-13 16:27:22.454 DEBUG 11272 --- [nio-8088-exec-1] o.s.web.servlet.DispatcherServlet        : enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data
2020-03-13 16:27:22.454  INFO 11272 --- [nio-8088-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 5 ms
2020-03-13 16:27:22.463 DEBUG 11272 --- [nio-8088-exec-1] o.s.web.servlet.DispatcherServlet        : GET "/monitor/server/list", parameters={}
2020-03-13 16:27:22.466 DEBUG 11272 --- [nio-8088-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to com.server.htzw.monitor.controller.ServerController#server()
SysFile{dirName='F:\', sysTypeName='NTFS', typeName='本地固定磁盘 (F:)', total='700.0 GB', free='607.6 GB', used='92.4 GB', usage=13.2}
SysFile{dirName='C:\', sysTypeName='NTFS', typeName='本地固定磁盘 (C:)', total='226.7 GB', free='162.2 GB', used='64.5 GB', usage=28.46}
SysFile{dirName='E:\', sysTypeName='NTFS', typeName='本地固定磁盘 (E:)', total='237.1 GB', free='141.5 GB', used='95.6 GB', usage=40.33}
SysFile{dirName='H:\', sysTypeName='NTFS', typeName='本地固定磁盘 (H:)', total='1863.0 GB', free='218.0 GB', used='1645.0 GB', usage=88.3}
SysFile{dirName='D:\', sysTypeName='NTFS', typeName='本地固定磁盘 (D:)', total='100.0 GB', free='98.7 GB', used='1.3 GB', usage=1.3}
SysFile{dirName='G:\', sysTypeName='NTFS', typeName='本地固定磁盘 (G:)', total='1063.0 GB', free='1057.8 GB', used='5.2 GB', usage=0.49}
Memory=:Mem{total=63.89, used=16.02, free=47.87}
CPU=:Cpu{cpuNum=8, total=812500.0, sys=2.28, used=1.54, wait=0.0, free=96.16}
sysInfo=:Sys{computerName='AFODY-003091210', computerIp='10.0.4.55', userDir='F:\monitor', osName='Windows 10', osArch='amd64'}
{"cpu":{"cpuNum":8,"free":64.26,"sys":10.89,"total":800000.0,"used":24.8,"wait":0.0},"mem":{"free":47.59,"total":63.89,"usage":25.5,"used":16.29},"sys":{"computerIp":"10.0.4.55","computerName":"AFODY-003091210","osArch":"amd64","osName":"Windows 10","userDir":"F:\\monitor"},"sysFiles":[{"dirName":"F:\\","free":"607.6 GB","sysTypeName":"NTFS","total":"700.0 GB","typeName":"本地磁盘 (F:\\)","usage":13.2,"used":"92.4 GB"},{"dirName":"C:\\","free":"162.1 GB","sysTypeName":"NTFS","total":"226.7 GB","typeName":"Windows10 (C:\\)","usage":28.5,"used":"64.6 GB"},{"dirName":"E:\\","free":"141.5 GB","sysTypeName":"NTFS","total":"237.1 GB","typeName":"本地磁盘 (E:\\)","usage":40.33,"used":"95.6 GB"},{"dirName":"H:\\","free":"218.0 GB","sysTypeName":"NTFS","total":"1863.0 GB","typeName":"Seagate Backup Plus Drive (H:\\)","usage":88.3,"used":"1645.0 GB"},{"dirName":"D:\\","free":"98.7 GB","sysTypeName":"NTFS","total":"100.0 GB","typeName":" (D:\\)","usage":1.3,"used":"1.3 GB"},{"dirName":"G:\\","free":"1057.8 GB","sysTypeName":"NTFS","total":"1063.0 GB","typeName":" (G:\\)","usage":0.49,"used":"5.2 GB"}]}

这篇关于使用oshi获取服务器的参数信息的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1086056

相关文章

VScode连接远程Linux服务器环境配置图文教程

《VScode连接远程Linux服务器环境配置图文教程》:本文主要介绍如何安装和配置VSCode,包括安装步骤、环境配置(如汉化包、远程SSH连接)、语言包安装(如C/C++插件)等,文中给出了详... 目录一、安装vscode二、环境配置1.中文汉化包2.安装remote-ssh,用于远程连接2.1安装2

Java中使用Java Mail实现邮件服务功能示例

《Java中使用JavaMail实现邮件服务功能示例》:本文主要介绍Java中使用JavaMail实现邮件服务功能的相关资料,文章还提供了一个发送邮件的示例代码,包括创建参数类、邮件类和执行结... 目录前言一、历史背景二编程、pom依赖三、API说明(一)Session (会话)(二)Message编程客

C++中使用vector存储并遍历数据的基本步骤

《C++中使用vector存储并遍历数据的基本步骤》C++标准模板库(STL)提供了多种容器类型,包括顺序容器、关联容器、无序关联容器和容器适配器,每种容器都有其特定的用途和特性,:本文主要介绍C... 目录(1)容器及简要描述‌php顺序容器‌‌关联容器‌‌无序关联容器‌(基于哈希表):‌容器适配器‌:(

使用Python实现高效的端口扫描器

《使用Python实现高效的端口扫描器》在网络安全领域,端口扫描是一项基本而重要的技能,通过端口扫描,可以发现目标主机上开放的服务和端口,这对于安全评估、渗透测试等有着不可忽视的作用,本文将介绍如何使... 目录1. 端口扫描的基本原理2. 使用python实现端口扫描2.1 安装必要的库2.2 编写端口扫

使用Python实现操作mongodb详解

《使用Python实现操作mongodb详解》这篇文章主要为大家详细介绍了使用Python实现操作mongodb的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、示例二、常用指令三、遇到的问题一、示例from pymongo import MongoClientf

SQL Server使用SELECT INTO实现表备份的代码示例

《SQLServer使用SELECTINTO实现表备份的代码示例》在数据库管理过程中,有时我们需要对表进行备份,以防数据丢失或修改错误,在SQLServer中,可以使用SELECTINT... 在数据库管理过程中,有时我们需要对表进行备份,以防数据丢失或修改错误。在 SQL Server 中,可以使用 SE

使用Python合并 Excel单元格指定行列或单元格范围

《使用Python合并Excel单元格指定行列或单元格范围》合并Excel单元格是Excel数据处理和表格设计中的一项常用操作,本文将介绍如何通过Python合并Excel中的指定行列或单... 目录python Excel库安装Python合并Excel 中的指定行Python合并Excel 中的指定列P

浅析Rust多线程中如何安全的使用变量

《浅析Rust多线程中如何安全的使用变量》这篇文章主要为大家详细介绍了Rust如何在线程的闭包中安全的使用变量,包括共享变量和修改变量,文中的示例代码讲解详细,有需要的小伙伴可以参考下... 目录1. 向线程传递变量2. 多线程共享变量引用3. 多线程中修改变量4. 总结在Rust语言中,一个既引人入胜又可

golang1.23版本之前 Timer Reset方法无法正确使用

《golang1.23版本之前TimerReset方法无法正确使用》在Go1.23之前,使用`time.Reset`函数时需要先调用`Stop`并明确从timer的channel中抽取出东西,以避... 目录golang1.23 之前 Reset ​到底有什么问题golang1.23 之前到底应该如何正确的

C#实现系统信息监控与获取功能

《C#实现系统信息监控与获取功能》在C#开发的众多应用场景中,获取系统信息以及监控用户操作有着广泛的用途,比如在系统性能优化工具中,需要实时读取CPU、GPU资源信息,本文将详细介绍如何使用C#来实现... 目录前言一、C# 监控键盘1. 原理与实现思路2. 代码实现二、读取 CPU、GPU 资源信息1.