关注程序员的故事,一起用技术改变世界
OSHI介绍
OSHI是一个基于JNA的免费的本地操作系统和Java的硬件信息库。它不需要安装任何额外的本机库,旨在提供跨平台的实现来检索系统信息,如操作系统版本、进程、内存和CPU使用情况、磁盘和分区、设备、传感器等。
支持的功能
计算机系统和固件,底板
操作系统和版本/内部版本
物理(核心)和逻辑(超线程)CPU,处理器组,NUMA节点
系统和每个处理器的负载,使用情况滴答计数器,中断,正常运行时间
进程正常运行时间,CPU,内存使用情况,用户/组,命令行参数,线程详细信息
已使用/可用的物理和虚拟内存
挂载的文件系统(类型,可用空间和总空间,选项,读取和写入)
磁盘驱动器(型号,序列号,大小,读取和写入)和分区
网络接口(IP,带宽输入/输出),网络参数,TCP / UDP统计信息
电池状态(电量百分比,剩余时间,电量使用情况统计信息)
USB设备
连接的显示器(带有EDID信息),图形和声卡
某些硬件上的传感器(温度,风扇速度,电压)
第一步:SpringBoot项目添加依赖:
com.github.oshigroupId> oshi-coreartifactId> 3.9.1version> dependency>
第二步:创建CPU,虚拟机,内存,系统,系统文件等系统基础类:
CPU:
package com.company.api.server; import com.company.util.Arith; /** * CPU相关信息 * @author zengxueqi * @since 2020/07/14 */ 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; } }
虚拟机:
package com.company.api.server; import com.company.util.Arith; import com.company.util.util.DateUtils; import java.lang.management.ManagementFactory; /** * JVM相关信息 * @author zengxueqi * @since 2020/07/14 */ public class Jvm { /** * 当前JVM占用的内存总数(M) */ private double total; /** * JVM最大可用内存总数(M) */ private double max; /** * JVM空闲内存(M) */ private double free; /** * JDK版本 */ private String version; /** * JDK路径 */ private String home; public double getTotal() { return Arith.div(total, (1024 * 1024), 2); } public void setTotal(double total) { this.total = total; } public double getMax() { return Arith.div(max, (1024 * 1024), 2); } public void setMax(double max) { this.max = max; } public double getFree() { return Arith.div(free, (1024 * 1024), 2); } public void setFree(double free) { this.free = free; } public double getUsed() { return Arith.div(total - free, (1024 * 1024), 2); } public double getUsage() { return Arith.mul(Arith.div(total - free, total, 4), 100); } /** * 获取JDK名称 */ public String getName() { return ManagementFactory.getRuntimeMXBean().getVmName(); } public String getVersion() { return version; } public void setVersion(String version) { this.version = version; } public String getHome() { return home; } public void setHome(String home) { this.home = home; } /** * JDK启动时间 */ public String getStartTime() { return DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.getServerStartDate()); } /** * JDK运行时间 */ public String getRunTime() { return DateUtils.getDatePoor(DateUtils.getNowDate(), DateUtils.getServerStartDate()); } }
内存:
package com.company.api.server; import com.company.util.Arith; /** * 內存相关信息 * @author zengxueqi * @since 2020/07/14 */ 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); } }
系统:
package com.company.api.server; /** * 系统相关信息 * @author zengxueqi * @since 2020/07/14 */ public class Sys { /** * 服务器名称 */ private String computerName; /** * 服务器Ip */ private String computerIp; /** * 项目路径 */ private String userDir; /** * 操作系统 */ private String osName; /** * 系统架构 */ private String osArch; public String getComputerName() { return computerName; } public void setComputerName(String computerName) { this.computerName = computerName; } public String getComputerIp() { return computerIp; } public void setComputerIp(String computerIp) { this.computerIp = computerIp; } public String getUserDir() { return userDir; } public void setUserDir(String userDir) { this.userDir = userDir; } public String getOsName() { return osName; } public void setOsName(String osName) { this.osName = osName; } public String getOsArch() { return osArch; } public void setOsArch(String osArch) { this.osArch = osArch; } }
系统文件:
package com.company.api.server; /** * 系统文件相关信息 * @author zengxueqi * @since 2020/07/14 */ public class SysFile { /** * 盘符路径 */ private String dirName; /** * 盘符类型 */ private String sysTypeName; /** * 文件类型 */ private String typeName; /** * 总大小 */ private String total; /** * 剩余大小 */ private String free; /** * 已经使用量 */ private String used; /** * 资源的使用率 */ private double usage; public String getDirName() { return dirName; } public void setDirName(String dirName) { this.dirName = dirName; } public String getSysTypeName() { return sysTypeName; } public void setSysTypeName(String sysTypeName) { this.sysTypeName = sysTypeName; } public String getTypeName() { return typeName; } public void setTypeName(String typeName) { this.typeName = typeName; } public String getTotal() { return total; } public void setTotal(String total) { this.total = total; } public String getFree() { return free; } public void setFree(String free) { this.free = free; } public String getUsed() { return used; } public void setUsed(String used) { this.used = used; } public double getUsage() { return usage; } public void setUsage(double usage) { this.usage = usage; } }
封装服务器监控系统:
package com.company.api.server; import com.company.util.Arith; import com.company.util.util.IpUtils; import oshi.SystemInfo; import oshi.hardware.CentralProcessor; import oshi.hardware.CentralProcessor.TickType; import oshi.hardware.GlobalMemory; import oshi.hardware.HardwareAbstractionLayer; import oshi.software.os.FileSystem; import oshi.software.os.OSFileStore; import oshi.software.os.OperatingSystem; import oshi.util.Util; import java.net.UnknownHostException; import java.util.LinkedList; import java.util.List; import java.util.Properties; /** * 服务器相关信息 * @author zengxueqi * @since 2020/07/14 */ public class Server { private static final int OSHI_WAIT_SECOND = 1000; /** * CPU相关信息 */ private Cpu cpu = new Cpu(); /** * 內存相关信息 */ private Mem mem = new Mem(); /** * JVM相关信息 */ private Jvm jvm = new Jvm(); /** * 服务器相关信息 */ private Sys sys = new Sys(); /** * 磁盘相关信息 */ private List 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 Jvm getJvm() { return jvm; } public void setJvm(Jvm jvm) { this.jvm = jvm; } public Sys getSys() { return sys; } public void setSys(Sys sys) { this.sys = sys; } public List getSysFiles() { return sysFiles; } public void setSysFiles(List sysFiles) { this.sysFiles = sysFiles; } public void copyTo() throws Exception { SystemInfo si = new SystemInfo(); HardwareAbstractionLayer hal = si.getHardware(); setCpuInfo(hal.getProcessor()); setMemInfo(hal.getMemory()); setSysInfo(); setJvmInfo(); 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")); } /** * 设置Java虚拟机 */ private void setJvmInfo() throws UnknownHostException { Properties props = System.getProperties(); jvm.setTotal(Runtime.getRuntime().totalMemory()); jvm.setMax(Runtime.getRuntime().maxMemory()); jvm.setFree(Runtime.getRuntime().freeMemory()); jvm.setVersion(props.getProperty("java.version")); jvm.setHome(props.getProperty("java.home")); } /** * 设置磁盘信息 */ 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)); 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); } } }
创建浮点数运算工具类:
package com.company.util; import java.math.BigDecimal; import java.math.RoundingMode; /** * 精确的浮点数运算 * @author zengxueqi * @since 2020/07/14 */ public class Arith { /** * 默认除法运算精度 */ private static final int DEF_DIV_SCALE = 10; /** * 这个类不能实例化 */ private Arith() { } /** * 提供精确的加法运算。 * @param v1 被加数 * @param v2 加数 * @return 两个参数的和 */ public static double add(double v1, double v2) { BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.add(b2).doubleValue(); } /** * 提供精确的减法运算。 * @param v1 被减数 * @param v2 减数 * @return 两个参数的差 */ public static double sub(double v1, double v2) { BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.subtract(b2).doubleValue(); } /** * 提供精确的乘法运算。 * @param v1 被乘数 * @param v2 乘数 * @return 两个参数的积 */ public static double mul(double v1, double v2) { BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.multiply(b2).doubleValue(); } /** * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 * 小数点以后10位,以后的数字四舍五入。 * @param v1 被除数 * @param v2 除数 * @return 两个参数的商 */ public static double div(double v1, double v2) { return div(v1, v2, DEF_DIV_SCALE); } /** * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 * 定精度,以后的数字四舍五入。 * @param v1 被除数 * @param v2 除数 * @param scale 表示表示需要精确到小数点以后几位。 * @return 两个参数的商 */ public static double div(double v1, double v2, int scale) { if (scale < 0) { throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); if (b1.compareTo(BigDecimal.ZERO) == 0) { return BigDecimal.ZERO.doubleValue(); } return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue(); } /** * 提供精确的小数位四舍五入处理。 * @param v 需要四舍五入的数字 * @param scale 小数点后保留几位 * @return 四舍五入后的结果 */ public static double round(double v, int scale) { if (scale < 0) { throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b = new BigDecimal(Double.toString(v)); BigDecimal one = new BigDecimal("1"); return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue(); } }
第三步:创建api接口:
package com.company.mission.controller; import com.company.api.base.ResultT; import com.company.api.server.Server; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * 服务器监控 * @author zengxueqi * @since 2020/07/14 */ @RestController @RequestMapping("/monitor") public class ServerController { /** * 获取服务器监控信息 * @param * @return com.company.api.base.ResultT * @author zengxueqi * @since 2020/7/14 */ @PostMapping("/server") public ResultT getInfo() throws Exception { Server server = new Server(); server.copyTo(); return ResultT.ok(server); } }
第四步:启动SpringBoot服务,访问API地址:
API地址(根据自己的项目来):http://127.0.0.1:9004/mission/monitor/server
API接口响应数据如下:
{ "code": 0, "msg": "业务处理成功", "content": { "cpu": { "cpuNum": 8, "total": 80300.0, "sys": 4.61, "used": 13.45, "wait": 0.0, "free": 81.94 }, "mem": { "total": 8.0, "used": 6.22, "free": 1.78, "usage": 77.71 }, "jvm": { "total": 656.0, "max": 1820.5, "free": 161.44, "version": "1.8.0_191", "home": "/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre", "name": "Java HotSpot(TM) 64-Bit Server VM", "startTime": "2020-07-14 10:30:46", "usage": 75.39, "used": 494.56, "runTime": "0天1小时5分钟" }, "sys": { "computerName": "zengxueqis-MacBook-Air.local", "computerIp": "127.0.0.1", "userDir": "/Users/zengxueqi/IdeaProjects/mission", "osName": "Mac OS X", "osArch": "x86_64" }, "sysFiles": [ { "dirName": "/", "sysTypeName": "apfs", "typeName": "mac os", "total": "79.4 GB", "free": "24.0 GB", "used": "55.4 GB", "usage": 69.8 }, { "dirName": "/System/Volumes/Data", "sysTypeName": "apfs", "typeName": "mac os - 数据", "total": "79.4 GB", "free": "24.0 GB", "used": "55.4 GB", "usage": 69.8 }, { "dirName": "/private/var/vm", "sysTypeName": "apfs", "typeName": "VM", "total": "79.4 GB", "free": "24.0 GB", "used": "55.4 GB", "usage": 69.8 }, { "dirName": "/Volumes/Untitled", "sysTypeName": "ntfs", "typeName": "Untitled", "total": "38.3 GB", "free": "17.2 GB", "used": "21.0 GB", "usage": 54.94 }, { "dirName": "/Volumes/Untitled 1", "sysTypeName": "ntfs", "typeName": "Untitled 1", "total": "38.7 GB", "free": "19.7 GB", "used": "19.0 GB", "usage": 48.97 }, { "dirName": "/Volumes/软件", "sysTypeName": "ntfs", "typeName": "软件", "total": "171.0 GB", "free": "163.4 GB", "used": "7.6 GB", "usage": 4.46 }, { "dirName": "/Volumes/other", "sysTypeName": "apfs", "typeName": "other", "total": "170.1 GB", "free": "164.6 GB", "used": "5.5 GB", "usage": 3.22 }, { "dirName": "/Volumes/文档", "sysTypeName": "ntfs", "typeName": "文档", "total": "170.0 GB", "free": "166.9 GB", "used": "3.1 GB", "usage": 1.81 }, { "dirName": "/Volumes/娱乐", "sysTypeName": "ntfs", "typeName": "娱乐", "total": "170.0 GB", "free": "159.8 GB", "used": "10.2 GB", "usage": 5.98 }, { "dirName": "/Volumes/办公", "sysTypeName": "ntfs", "typeName": "办公", "total": "170.0 GB", "free": "168.9 GB", "used": "1.1 GB", "usage": 0.63 } ] } }
通过API接口返回的数据可以看出,OSHI获取到的服务器数据还是非常的详细的,OSHI可以跨平台查看服务器信息,其中cpu负载信息为当前占用CPU的时间。需要在一段时间内获取两次,然后相减得出这段时间内所占用的时间。这段时间除以总占用时间就是占用百分比。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.