服务器监控功能(3种方案)
服务器监控功能(3种方案)
- 一、Actuator监控
- 1. 添加依赖
- 2. application.yaml配置
- 3. 启动项目,访问
- 二、SpringBoot Admin(单体)
- 1. Admin Server 端
- 2. Admin Client 端
- 三、OSHI
- 1. pom.xml依赖
- 2. 接口返回数据
- 3. 代码
1. 添加依赖Actuator是Springboot提供的用来对应用系统进行自省和监控的功能模块,借助于Actuator开发者可以很方便地对应用系统某些监控指标进行查看、统计等。
部署简单、直接调接口拿值、数据较分散,需处理
2. application.yaml配置.springframeork.boot spring-boot-starter-actuator
#actuator监控配置 management: endpoints: eb: exposure: #默认值访问health,info端点 用可以包含全部端点 include: '' #配置路径 base-path: /system/actuator endpoint: health: #获得健康检查中所有指标的详细信息 sho-details: alays3. 启动项目,访问
以下显示的路径,都是可以被健康检查的指标
其中谷歌浏览器显示格式为 JSON,是因为下载了 JSON-handle 插件
-
访问路径项目路径+actuator配置路径
-
Actuator健康项
可监控的信息包含应用状态、内存、线程、堆栈等等,比较全面的监控了 Spring Boot 应用的整个生命周期。
在Spring Boot Actuator的基础上提供简洁的可视化WEB UI
SpringBoot Admin 分为服务端(spring-boot-admin-server)和客户端(spring-boot-admin-client),客户端就是指需要被监控的应用端(项目启动位置)
1. Admin Server 端-
新建一个项目模块,项目依赖
de.codecentric spring-boot-admin-starter-server2.1.0 .springframeork.boot spring-boot-starter-eb -
application.yaml 配置文件
# 配置tomcat访问端口 server: port: 8000
-
启动类
import de.codecentric.boot.admin.server.config.EnableAdminServer; import .springframeork.boot.SpringApplication; import .springframeork.boot.autoconfigure.EnableAutoConfiguration; import .springframeork.context.annotation.Configuration; @Configuration @EnableAutoConfiguration @EnableAdminServer public class AdminServerApplication { public static void main(String[] args) { SpringApplication.run(AdminServerApplication.class, args); } }
-
访问浏览器 http://localhost:8000
-
在原本项目基础上,添加依赖
de.codecentric spring-boot-admin-starter-client2.1.0 .springframeork.boot spring-boot-starter-eb -
配置文件
# 配置访问端口 server: port: 20211 spring: application: name: Admin Client # 配置AdminServer的地址 boot: admin: client: url: http://localhost:8000 # 打开客户端的监控 management: endpoints: eb: exposure: include:
-
客户端启动类
@SpringBootApplication public class AdminClientApplication { public static void main(String[] args) { SpringApplication.run(AdminClientApplication.class, args); } }
-
先启动服务端,再启动客户端
启动 Client 端,Admin 服务端会自动检查到客户端的变化,并展示其应用
页面会展示被监控的服务列表,点击详项目名称会进入此应用的详细监控信息
1. pom.xml依赖基于JNA的免费的本地操作系统和Java的硬件信息库,可以跨平台,获取监控信息简单
2. 接口返回数据 3. 代码.github.oshi oshi-core5.6.0
-
Controller
import .lzby.tqj.dto.AjaxResult; import .lzby.tqj.entity.Server; import io.sagger.; import .springframeork.eb.bind.annotation.; @CrossOrigin(origins = "", maxAge = 3600) @Api(tags = "系统-服务器监控") @RestController @RequestMapping("/monitor/server") public class ServerController { @ApiOperation(value = "获得服务器相关信息", notes = "获得服务器相关信息") @PostMapping(value = "/getInfo") public AjaxResult getInfo() thros Exception { Server server = ne Server(); server.copyTo(); return AjaxResult.suess(server); } }
-
entity - Server
package .lzby.tqj.entity; import .lzby.tqj.mon.IpUtils; import .lzby.tqj.mon.util.Arith; import .lzby.tqj.entity.server.; import oshi.; import java..IAddress; import java.util.; public class Server { private static final int OSHI_WAIT_SECOND = 1000; // CPU相关信息 private Cpu cpu = ne Cpu(); // 內存相关信息 private Mem mem = ne Mem(); // JVM相关信息 private Jvm jvm = ne Jvm(); // 服务器相关信息 private Sys sys = ne Sys(); // 磁盘相关信息 private List
sysFiles = ne 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() thros Exception { SystemInfo si = ne SystemInfo(); HardareAbstractionLayer hal = si.getHardare(); setCpuInfo(hal.getProcessor()); setMemInfo(hal.getMemory()); setSysInfo(); setJvmInfo(); setSysFiles(si.getOperatingSystem()); } 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 ioait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()]; long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()]; long totalCpu = user + nice + cSys + idle + ioait + irq + softirq + steal; cpu.setCpuNum(processor.getLogicalProcessorCount()); cpu.setTotal(totalCpu); cpu.setSys(cSys); cpu.setUsed(user); cpu.setWait(ioait); 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(getHostName()); sys.setComputerIp(getHostIp()); sys.setOsName(props.getProperty("os.name")); sys.setOsArch(props.getProperty("os.arch")); sys.setUserDir(props.getProperty("user.dir")); } private void setJvmInfo() thros UnknonHostException { 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(); List fsArray = fileSystem.getFileStores(); for (OSFileStore fs : fsArray) { long free = fs.getUsableSpace(); long total = fs.getTotalSpace(); long used = total - free; SysFile sysFile = ne 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); } } 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); } } public static String getHostIp() { try { return IAddress.getLocalHost().getHostAddress(); } catch (UnknonHostException e) { } return "127.0.0.1"; } public static String getHostName() { try { return IAddress.getLocalHost().getHostName(); } catch (UnknonHostException e) { } return "未知"; } } -
entity - Cpu
package .lzby.tqj.entity.server; import .lzby.tqj.mon.util.Arith; public class Cpu { // 核心数 private int cpuNum; // CPU总的使用率 private double total; // CPU系统使用率 private double sys; // CPU用户使用率 private double used; // CPU当前等待率 private double ait; // 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(ait / total, 100), 2); } public void setWait(double ait){ this.ait = ait; } public double getFree(){ return Arith.round(Arith.mul(free / total, 100), 2); } public void setFree(double free){ this.free = free; } }
-
entity - Mem
package .lzby.tqj.entity.server; import .lzby.tqj.mon.util.Arith; 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); } }
-
entity - Jvm
package .lzby.tqj.entity.server; import java.lang.management.ManagementFactory; import .lzby.tqj.mon.util.Arith; import .lzby.tqj.mon.util.DateUtils; 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.getNoDate(), DateUtils.getServerStartDate()); } }
-
entity - Jvm
package .lzby.tqj.entity.server; import lombok.Data; @Data public class Sys{ // 服务器名称 private String puterName; // 服务器Ip private String puterIp; // 项目路径 private String userDir; // 操作系统 private String osName; // 系统架构 private String osArch; }
-
工具类 Arith
package .lzby.tqj.mon.util; import java.math.BigDecimal; import java.math.RoundingMode; public class Arith{ private static final int DEF_DIV_SCALE = 10; private Arith(){} public static double add(double v1, double v2){ BigDecimal b1 = ne BigDecimal(Double.toString(v1)); BigDecimal b2 = ne BigDecimal(Double.toString(v2)); return b1.add(b2).doublevalue(); } public static double mul(double v1, double v2){ BigDecimal b1 = ne BigDecimal(Double.toString(v1)); BigDecimal b2 = ne BigDecimal(Double.toString(v2)); return b1.multiply(b2).doublevalue(); } public static double div(double v1, double v2, int scale){ if (scale < 0){ thro ne IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b1 = ne BigDecimal(Double.toString(v1)); BigDecimal b2 = ne BigDecimal(Double.toString(v2)); if (b1.pareTo(BigDecimal.ZERO) == 0){ return BigDecimal.ZERO.doublevalue(); } return b1.divide(b2, scale, RoundingMode.HALF_UP).doublevalue(); } public static double round(double v, int scale){ if (scale < 0){ thro ne IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b = ne BigDecimal(Double.toString(v)); BigDecimal one = ne BigDecimal("1"); return b.divide(one, scale, RoundingMode.HALF_UP).doublevalue(); } }
空调维修
- 海信电视维修站 海信电视维修站点
- 格兰仕空调售后电话 格兰仕空调维修售后服务电
- 家电售后服务 家电售后服务流程
- 华扬太阳能维修 华扬太阳能维修收费标准表
- 三菱电机空调维修 三菱电机空调维修费用高吗
- 美的燃气灶维修 美的燃气灶维修收费标准明细
- 科龙空调售后服务 科龙空调售后服务网点
- 华帝热水器维修 华帝热水器维修常见故障
- 康泉热水器维修 康泉热水器维修故障
- 华凌冰箱维修电话 华凌冰箱维修点电话
- 海尔维修站 海尔维修站点地址在哪里
- 北京海信空调维修 北京海信空调售后服务
- 科龙空调维修 科龙空调维修故障
- 皇明太阳能售后 皇明太阳能售后维修点
- 海信冰箱售后服务 海信冰箱售后服务热线电话
- 海尔热水器服务热线