SpringBoot实战:用OSHI打造你的服务器健康监控面板(附完整代码)

张开发
2026/4/18 16:22:25 15 分钟阅读

分享文章

SpringBoot实战:用OSHI打造你的服务器健康监控面板(附完整代码)
SpringBoot实战用OSHI打造你的服务器健康监控面板附完整代码在当今的互联网应用中服务器健康监控已成为保障系统稳定运行的关键环节。想象一下当你的应用突然出现性能瓶颈时如果能第一时间获取CPU、内存、JVM等关键指标问题定位效率将大幅提升。本文将带你使用SpringBoot和OSHI库构建一个功能完善的服务器监控系统从基础数据采集到可视化展示再到异常告警打造全方位的监控解决方案。1. 环境准备与OSHI基础OSHIOperating System and Hardware Information是一个基于JNA的Java库能够跨平台获取系统和硬件信息。相比传统的Sigar等方案OSHI无需安装额外本地库真正实现了开箱即用。首先在pom.xml中添加依赖dependency groupIdcom.github.oshi/groupId artifactIdoshi-core/artifactId version6.4.0/version /dependency基础使用示例SystemInfo si new SystemInfo(); HardwareAbstractionLayer hal si.getHardware(); // 获取CPU信息 CentralProcessor processor hal.getProcessor(); System.out.println(CPU核心数: processor.getLogicalProcessorCount()); // 获取内存信息 GlobalMemory memory hal.getMemory(); System.out.println(总内存: memory.getTotal() / 1024 / 1024 MB);提示OSHI支持Windows、Linux、macOS等多种操作系统但不同平台获取的具体指标可能略有差异。2. SpringBoot集成与数据封装为了在SpringBoot中更好地使用OSHI我们需要设计合理的数据结构。以下是核心实体类的设计Data public class ServerInfo { private CpuInfo cpu; private MemoryInfo memory; private JvmInfo jvm; private ListDiskInfo disks; private SystemInfo system; Data public static class CpuInfo { private Integer cores; private Double systemLoad; private Double userLoad; private Double idlePercentage; private String model; } Data public static class MemoryInfo { private Long total; private Long available; private Long used; private Double usageRate; } // 其他内部类... }实现数据采集服务Service public class MonitorService { private final SystemInfo systemInfo new SystemInfo(); private final HardwareAbstractionLayer hardware systemInfo.getHardware(); public ServerInfo collect() { ServerInfo info new ServerInfo(); info.setCpu(collectCpuInfo()); info.setMemory(collectMemoryInfo()); info.setJvm(collectJvmInfo()); info.setDisks(collectDiskInfo()); return info; } private CpuInfo collectCpuInfo() { CentralProcessor processor hardware.getProcessor(); long[] ticks processor.getSystemCpuLoadTicks(); Util.sleep(1000); // 必须间隔采样 long[] newTicks processor.getSystemCpuLoadTicks(); CpuInfo cpu new CpuInfo(); cpu.setCores(processor.getLogicalProcessorCount()); cpu.setModel(processor.toString()); // 计算各类CPU使用率... return cpu; } }3. 实时监控与数据持久化要实现真正的监控系统我们需要定时采集数据并存储。Spring的Scheduled任务非常适合这种场景Scheduled(fixedRate 5000) public void monitor() { ServerInfo info monitorService.collect(); // 存储到数据库或时序数据库 monitoringRepository.save(info); // 检查阈值触发告警 checkThresholds(info); }对于数据存储InfluxDB或Prometheus等时序数据库是不错的选择。以下是InfluxDB集成的示例Configuration public class InfluxDbConfig { Bean public InfluxDB influxDB() { return InfluxDBFactory.connect(http://localhost:8086, admin, password) .setDatabase(monitoring) .enableBatch(); } } Service RequiredArgsConstructor public class InfluxDbService { private final InfluxDB influxDB; public void write(ServerInfo info) { Point point Point.measurement(server) .time(System.currentTimeMillis(), TimeUnit.MILLISECONDS) .addField(cpu_usage, info.getCpu().getSystemLoad()) .addField(memory_usage, info.getMemory().getUsageRate()) .build(); influxDB.write(point); } }4. 可视化与告警系统有了数据后我们需要直观的展示方式。SpringBoot结合Thymeleaf或前端框架可以轻松实现Controller RequestMapping(/monitor) public class MonitorController { private final MonitorService monitorService; GetMapping(/dashboard) public String dashboard(Model model) { model.addAttribute(info, monitorService.getLatest()); return monitor/dashboard; } GetMapping(/history) ResponseBody public ListServerInfo getHistory( RequestParam(required false) DateTimeFormat(iso ISO.DATE_TIME) LocalDateTime from, RequestParam(required false) DateTimeFormat(iso ISO.DATE_TIME) LocalDateTime to) { return monitorService.getHistory(from, to); } }前端使用ECharts展示折线图// 在dashboard.html中 fetch(/monitor/history) .then(res res.json()) .then(data { const chart echarts.init(document.getElementById(cpu-chart)); chart.setOption({ xAxis: { type: time }, yAxis: { type: value }, series: [{ data: data.map(item [item.timestamp, item.cpu.systemLoad]), type: line }] }); });告警系统实现Service RequiredArgsConstructor public class AlertService { private final NotificationService notificationService; private final AlertConfigRepository configRepo; public void checkThresholds(ServerInfo info) { configRepo.findAll().forEach(config - { double value getMetricValue(info, config.getMetric()); if (value config.getThreshold()) { notificationService.sendAlert( config.getAlertName(), String.format(%s超过阈值: %.2f %.2f, config.getMetric(), value, config.getThreshold()) ); } }); } private double getMetricValue(ServerInfo info, String metric) { switch (metric) { case cpu.usage: return info.getCpu().getSystemLoad(); case memory.usage: return info.getMemory().getUsageRate(); // 其他指标... default: return 0; } } }5. 高级功能与性能优化在实际生产环境中我们还需要考虑以下高级功能多服务器监控Configuration public class RemoteMonitorConfig { Bean public ListRemoteMonitor remoteMonitors() { return List.of( new RemoteMonitor(server1, http://server1:8080/monitor/api), new RemoteMonitor(server2, http://server2:8080/monitor/api) ); } } Service RequiredArgsConstructor public class ClusterMonitorService { private final ListRemoteMonitor monitors; public MapString, ServerInfo monitorCluster() { return monitors.stream() .parallel() .collect(Collectors.toMap( RemoteMonitor::getName, monitor - restTemplate.getForObject( monitor.getUrl(), ServerInfo.class ) )); } }性能优化技巧使用缓存减少频繁采集的开销异步处理数据存储和告警检查合理设置采集间隔生产环境建议5-10秒Cacheable(value serverInfo, key current) public ServerInfo getCurrentInfo() { return collect(); } Async public void asyncSave(ServerInfo info) { repository.save(info); }安全考虑Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers(/monitor/**).hasRole(ADMIN) .and().httpBasic(); } }6. 完整代码示例最后我们提供一个完整的REST API实现RestController RequestMapping(/api/monitor) RequiredArgsConstructor public class MonitorApiController { private final MonitorService monitorService; GetMapping(/current) public ServerInfo getCurrent() { return monitorService.getCurrentInfo(); } GetMapping(/history) public ListServerInfo getHistory( RequestParam DateTimeFormat(iso ISO.DATE_TIME) LocalDateTime start, RequestParam DateTimeFormat(iso ISO.DATE_TIME) LocalDateTime end) { return monitorService.getHistory(start, end); } GetMapping(/alerts) public ListAlert getActiveAlerts() { return monitorService.getActiveAlerts(); } }前端调用示例// 使用Vue.js示例 new Vue({ el: #app, data: { serverInfo: {}, history: [] }, mounted() { this.fetchData(); setInterval(this.fetchData, 5000); }, methods: { fetchData() { axios.get(/api/monitor/current) .then(response this.serverInfo response.data); } } })在实际项目中我们团队发现OSHI的CPU使用率计算需要特别注意采样间隔最初没有加入间隔时间导致数据不准确。另外当监控多台服务器时采用异步并行采集可以显著提升效率。

更多文章