资讯动态

SpringBoot服务器监控系统:从指标采集到实时告警的完整实战

发布时间:2026/10/18 2:36:10 来源:尧图企业网站定制
我在学生机房里看到过太多次这样的场景凌晨两点一台服务器把整个实验环境带崩第二天一早所有人对着黑屏发呆却没人说得清故障从什么时候开始、哪个进程先出了事。后来我在某高校实验室做了这套基于SpringBoot的服务器运维监控系统用课余时间断断续续写了三周把“事后救火”变成了“提前看到苗头”。这篇文章就是这套系统的完整拆解从需求、技术选型、核心模块到踩坑记录适合正在准备计算机毕业设计、又不想只做个增删改查管理系统的同学。1. 这个选题到底想解决什么问题——系统日志和管理系统都不够用1.1 机房管理员最需要的核心场景一台服务器会出问题的方式远比想象中多。CPU被打满、内存耗尽、磁盘写满、某个端口悄悄挂了、数据库连接数涨到临界值、日志里突然刷出大量异常。这些故障有一个共同特点都不是瞬间发生的而是有一个缓慢积累的过程。普遍做法是看系统日志。但系统日志的问题是量大、格式杂、级别不准等你在几百行日志里找到关键错误服务可能已经不可用了。另一个做法是做个数据管理系统把服务器信息、IP、责任人存进MySQL本质上只是把Excel搬到了网页上对运维没有任何实质帮助。这套SpringBoot运维监控系统要解决的是三个核心问题能不能自动拿到服务器的运行指标能不能在指标异常时及时通知到人能不能看到历史趋势、定位故障时间点能做到这三点系统才具备真正的运维价值也正好对应了毕业设计里“数据采集、数据处理、数据展示”三个模块的要求。1.2 为什么这个选题难度刚刚好毕设选题最怕两头极端。太简单论文没东西写答辩老师问两句就露馅太难核心算法啃不动整套系统做不完。服务器运维监控恰好是中间档。技术上它用到SpringBoot做服务端、WebSocket做实时推送、时序数据库存指标数据、规则引擎做告警判断每一样都是企业级开发里常用的技术栈但每一样的深度都可以控制在“够用”的层面。我可以把Agent端采集器的设计、告警规则的数据结构、指标存储的聚合策略写得很细这些都是有真实业务背景的内容不愁论文没有论述素材。更重要的是这套系统有明确的验收标准一台真实服务器接入后能看到实时曲线、能触发告警、能在故障恢复后收到恢复通知。它不是一个“看起来能跑”的Demo而是真正可以用来观察实验室服务器状态的工具。这个验收点对毕设答辩来说非常关键。2. 技术选型不是越新越好是每个组件都有自己的活2.1 为什么SpringBoot只做服务层不做采集层最开始我确实想过用SpringBoot一个框架包打天下采集、存储、告警、展示全写在同一个工程里。后来发现这是个典型的架构错误SpringBoot是应用开发框架擅长的是对外提供API、处理业务逻辑、管理对象生命周期而服务器指标的采集是一个周期性、轻量级、高并发的任务两者的节奏天然不一致。拆开之后结构清晰了很多。采集这层我用了独立的Agent程序部署在每一台被监控的服务器上按固定周期调用系统接口读取CPU、内存、磁盘、网络数据然后通过HTTP接口上报给SpringBoot服务端。SpringBoot服务端只做三件事接收指标数据、写入时序数据库、根据规则计算是否触发告警。前端通过REST接口和WebSocket连接服务端拿到最新的监控状态。这样拆带来的直接好处是替换成本低。Agent端将来想换成Prometheus的exporter或者用Telegraf做采集器服务端几乎不用改。SpringBoot在这里的定位就是稳定的“数据汇聚与服务出口”这是它最擅长的角色。2.2 指标数据为什么不能直接塞进MySQL监控系统第一个版本我把CPU使用率、内存用量这些指标直接写进了MySQL表和字段都建好了存了两天数据之后发现问题来了监控指标是无休止的时间序列一台服务器每10秒产生一批数据每批几十个数值一天就是几十万行一周下来几百万行MySQL的查询开始肉眼可见地变慢。不是MySQL不行是数据模型不对。监控指标的核心特征是“写入多、按时间范围查询、基本不做更新、数据有生命周期”这天然适合时序数据库。我最终选择了InfluxDB存指标数据MySQL只保留用户信息、服务器资产信息、告警规则定义和告警记录。维度MySQLInfluxDB时序数据库模型关系型强调表和约束时序型强依赖时间和标签写入随机写入需要索引维护顺序追加写入天然适合高频写入查询常用条件过滤、联表常用时间范围聚合函数保留策略需要手动清理通过RP自动回收过期数据典型用途业务数据、规则配置监控指标、日志时序这个调整让整个系统的数据流变得非常合理。指标数据写入InfluxDB按照一天一个shard的粒度自动归档超过30天的数据自动过期。MySQL这边只有告警事件和规则配置数据量始终控制在一个很小的范围。2.3 指标采集的两种思路主动拉取和服务端推送在Agent设计上我参考过两种主流方案。第一种是服务端拉取模式典型代表是Prometheus服务端定期从每个被监控端点的HTTP接口抓取指标第二种是Agent主动上报模式被监控端主动把指标发到服务端。两者在工程上都有大量实践但对一套毕设系统来说Agent主动上报实现起来更直接。Agent主动上报意味着端口方向不用额外暴露服务端不用维护“谁在监控、谁下线了”的长列表Agent启动后注册一次然后凭心跳保持在线状态服务端只知道“收到数据就是在线的”。这个模型对实验室这种经常开关机的场景最友好——一台服务器被关机重启等新开机后Agent自动恢复上报中间不需要人工介入。3. 指标体系设计先定好采集对象才能谈监控告警3.1 主机层指标要采集到什么程度监控系统最基础的指标来自操作系统层我按资源类型拆成了五组内容。CPU相关核心数、使用率、空闲率、1分钟/5分钟/15分钟负载。负载这个指标容易被忽略但它是判断系统是否过载的最快信号。内存相关总量、已用、可用、缓冲区和缓存占用、Swap使用率。磁盘相关每个挂载点或根分区的总量、已用、使用率、IO读写速率还有inode使用率——inode耗尽时磁盘明明还有空间但新文件就是创建不了。网络相关入流量、出流量、TCP连接数、丢包率。除了资源指标还要有进程和端口级别的检测。我做了两件事一是指定关键进程的存活检测看CPU、内存占用是否超过阈值二是对指定端口做TCP连通性检测端口挂了直接判定服务异常。这些指标加起来大概三十多个全部通过一个统一的标签体系关联到“服务器ID 类别 指标名”。3.2 应用层指标JVM和HTTP探测是增值点如果只看主机指标这套系统说到底就是一台“服务器监控仪表盘”和专门的监控软件没有区别。为了让论文有差异化我加了两个应用层采集维度HTTP服务探测和JVM监控。HTTP探测的思路很简单Agent定期对某个HTTP接口发起GET请求记录响应时间、HTTP状态码、返回内容长度。状态码非200或者响应时间超过阈值就触发告警。这个功能在毕设答辩时很好演示——把某个Web服务的接口地址配置进去停掉服务观察系统在几十秒内弹出告警。JVM监控则是为Java应用量身定做的Agent通过JMX接口读取目标JVM进程的堆内存使用、非堆内存、GC次数和耗时、活跃线程数。和指标数据一样这些数据也带上时间戳写入时序数据库前端可以画出JVM内存趋势曲线。这部分内容在论文里可以单独开一节讲“应用性能监控的扩展设计”是提升技术深度的加分项。3.3 指标元模型用标签代替一大堆固定字段刚开始设计指标数据结构的时候我犯过一个错每个指标定义一个字段CPU idleCPU、CPU userCPU、memory used、memory total……字段一多代码里全是冗长的赋值逻辑想加一个新监控项要改表、改实体类、改采集器。后来我改成了一套“指标键值对”模型每个指标点由指标名(measurement)、标签(tags)、字段(fields)、时间戳(timestamp)四部分组成。CPU使用率就是metriccpu_usage标签包括server_id和cpu_id内存使用率是metricmem_usage标签只带server_id。上报接口不再为每个指标写单独的字段而是一次提交一整批数据点后端用统一的解析逻辑处理。这个设计参考了InfluxDB的行协议简化程度足够将来接入更多监控项时只需要新增指标名不用改存储结构。4. 核心功能模块的工程实现从采集器到告警引擎4.1 采集器周期任务与系统信息读取Agent端我用Java写了一个轻量级采集进程核心是一个基于ScheduledExecutorService的调度器。每10秒采集一次基础资源指标每30秒做一次进程存活检测和HTTP探测每60秒刷新一次磁盘IO状态。调度周期不能全部统一频率太高Agent自身消耗会干扰监控数据频率太低故障发现的时效性又不够。操作系统信息的读取我用了OSHI库。这是一个成熟的跨平台系统信息库一条调用就能拿到CPU使用率、内存状态、磁盘分区和IO数据省去了很多直接解析/proc和/sys的细节。对于纯Java技术栈的毕设来说这是最稳的选择——曾经试过自己解析Linux的/proc/stat文件虽然也能算出来但在虚拟机上跑一段时间就会发现数值不够稳定OSHI在这方面处理得更成熟。上报逻辑上Agent每隔一个周期攒一批指标通过HTTP POST消息推送给服务端。考虑到实验室的网络环境偶尔故障请求里加了超时和重试机制超时设为5秒重试最多3次重试失败的本地缓存最后再补推。4.2 服务端接收与持久化先写MQ还是直接入库服务端接收指标数据我最初的实现是在Controller里同步写入InfluxDB。压测之后发现性能瓶颈明显数据量上来时InfluxDB写入耗时波动前端接口响应也跟着变慢。后来在Kafka和内存队列之间纠结过一阵考虑到毕设系统的规模引入Kafka反而会让部署变复杂最终用了一个阻塞队列做中间缓冲。Controller接收到指标后先把数据扔进一个容量较大的BlockingQueue由单独的数据持久化线程消费队列并批量写入InfluxDB。这样接收接口只负责收数据不做耗时操作接口响应时间从平均几十毫秒降到了几毫秒。批量写入时按InfluxDB行协议拼接字符串一次批量提交几百条数据点写入吞吐完全够用。4.3 告警规则引擎不是简单的if-else告警是这套系统最核心的功能不能做成“内存使用率大于80%就发邮件”这种写死的逻辑。我设计了一套可配置的告警规则体系每条规则由这些字段组成目标服务器、监控指标、比较条件大于/小于/等于、阈值、持续时长、告警级别、通知方式。持续时长这个参数很容易被忽略但它极其重要。内存使用率可能在某个瞬间冲到85%下一秒就回落这种瞬时尖峰不应该触发告警。我实现的逻辑是告警状态机有“正常、待确认、告警中、已恢复”四个状态。当指标达到阈值后不是立即告警而是进入“待确认”状态并开始计时持续超过设定时长比如3分钟才真正触发告警。告警触发后才记录事件、发送通知、置为“告警中”。当指标回落到阈值以下再持续一段时间判定为“已恢复”发送恢复通知并关闭事件。这个状态机的存在让告警系统有实际可用性不然会被误报折磨到怀疑人生的。4.4 统计规则用代码怎么表达告警规则的判断我抽象成一个独立的RuleEvaluator组件。每一条规则解析后生成一个Evaluator对象服务端每隔一个评估周期把新到的指标和所有在线服务器的规则跑一遍匹配。为了控制计算量规则按“服务器指标名”做了索引只有命中对应指标的数据才会去执行比较逻辑。规则的数据结构大概是这样的public class AlertRule { private Long id; private Long serverId; private String metricName; private String operator; // gt, lt, eq private Double threshold; private Integer durationSec; // 持续多少秒才触发 private Integer level; // 1: 提示, 2: 警告, 3: 严重 private String notifyChannels; // email, webhook }评估时判断是否持续超阈值用一个简单的时间窗口记录每条规则维护一个“违规起始时间”每次指标正常就把这个时间清空每次超阈值且为空就记为当前时间然后计算“当前时间 - 违规起始时间 durationSec”是否成立。这个实现逻辑轻量效果和滑动窗口基本等价代码量少很多还容易在论文里描述清楚。4.5 通知渠道邮件和Webhook双通道告警通知我实现了邮件和Webhook两种渠道。邮件走JavaMailSender把告警级别、服务器名称、指标名、当前值、阈值、触发时间组织成邮件正文发出去。Webhook则向配置的URL推送一个JSON消息体这样将来可以对接企业微信机器人或钉钉机器人做成实时告警推送。比较有意思的是通知的可靠性问题。邮件发送失败时需要缓存通知内容用一个定时任务做补偿发送。这个细节放在论文里是很好的工程化体现——学生在毕设里能考虑到“消息发送失败后如何补偿”本身就说明有生产环境的思维。5. 前端可视化实时曲线远比数字刷新有说服力5.1 仪表盘设计一张页面看所有服务器状态前端我用了一个经典的技术组合Vue作为前端框架ECharts渲染图表WebSocket实现实时推送。页面结构分三层最顶部是全局状态栏显示在线服务器数量、告警总数、最近告警列表中间部分是服务器卡片列表每台服务器一张卡片显示基础状态点击进详情页后才是单个服务器的完整监控视图。详情页布局以时间序列图为骨架CPU使用率、内存使用率、磁盘使用率、网络出入速率分别是一张曲线图全部按时间轴对齐。鼠标滑过可以查看任意时刻的具体数值。这套交互逻辑虽然不复杂但非常直观——答辩的时候只要展示“曲线平滑上升→到达阈值线→告警弹窗出现”这一条链路系统的价值就能被老师完全理解。5.2 WebSocket推送与轮询的取舍初始方案用的是前端轮询每5秒请求一次REST接口拿最新指标。实测后发现两个问题查询稍大时接口响应会超过1秒页面多个图表同时刷新时明显卡顿另一个是HTTP轮询存在大量无效请求而监控场景里大部分时间内指标变化并不大。后来改成了WebSocket长连接。服务端在指标数据写入后将最新指标值按“指标名服务器ID”维度缓存到内存然后每隔几秒向前端推送一次批量数据。前端收到数据后直接调用ECharts的appendData方法动态追加数据点。这样页面始终是最新数据后台压力反而比轮询方式更小。WebSocket在SpringBoot里用内置的WebSocketHandler就能实现不需要额外引入Netty之类的框架依赖非常轻。5.3 ECharts动态图表的几个小细节动态追加数据的实现有3个容易踩坑的细节。第一是X轴的处理。ECharts的time轴不会自动增量显示如果不对X轴配置设置min和max的自动滚动一段时间后数据点会全部挤成一团。我通过设置xAxis的min和max为当前时间的滑动窗口实现了图表滚动效果。第二是数据积压的问题。页面长时间开着时如果不限制数据量前端内存会不断增长。我做了容量控制保留最近1小时的数据点超出部分直接从数据源数组中移除。第三是图表格式化。CPU这些值本身是浮点数展示时保留一位小数就够了网络速率显示成Mbps。格式化代码虽然不起眼但直接影响演示效果。6. 部署、自动发现与踩坑记录6.1 服务器自动发现是怎么做的监控系统要能真正用起来不能每新增一台服务器就要去数据库中手动插入一条资产记录然后再单独部署Agent。我实现了一个简单的被动发现机制。Agent启动后会上报一个注册包包含主机名、IP、操作系统类型、Agent版本号。服务端收到注册包后先用“主机名IP”查数据库如果存在记录就更新Agent状态为在线如果不存在就新增一条服务器资产记录默认状态为“待确认”。管理员收到通知后可以在页面上确认该服务器是否纳入监控确认后即可配置告警规则。这套机制在毕设规模下非常合适。那台服务器重装系统、IP变了Agent重新部署后会自动更新关联记录不会变成一条脏数据。心跳超时的服务器会被标记为“离线”页面显示灰色同时在状态栏计数里减去。6.2 部署时最容易翻车的几个地方整个系统部署下来有很多非业务逻辑的坑每个都值得单独提一下。第一个是时区问题。InfluxDB默认使用UTC时间MySQL使用本地时间两个库的时间差8小时指标查询出来的曲线图和告警记录根本对不上。解决方法是连接配置上统一指定Asia/Shanghai时区包括JDBC连接串和InfluxDB客户端配置都加时区参数。第二个是虚拟机的CPU使用率计算。OSHI默认按所有逻辑核心平均的方式计算使用率但宿主机多核超线程的虚拟化场景下数据会显得偏高。后来我改成按实际CPU核心数加权计算更符合物理机的直觉理解。第三个是防火墙端口。SpringBoot服务端默认8080端口Agent上报接口和数据面板共用这个端口一般不会冲突。但如果用8081做调试端口就很容器被云平台安全规则拦截掉。第四个是告警风暴。有一次测试时把阈值调低了一台服务器连续30分钟持续触发告警邮件列表刷了几十封。后来我做了冷却机制同一规则从告警中恢复到再次告警之间设5分钟冷却期告警中的规则即使持续超阈值也不再重复发通知。这个是所有监控系统必须有的机制没有它在生产环境会直接被打爆。6.3 Agent的离线判断与自愈心跳机制我设在每15秒上报一次基础状态。服务端有一个定时任务每分钟扫描一次所有在线Agent发现最后心跳时间超过60秒就把对应服务器标记为离线并触发离线告警。这里有一个“自愈”的逻辑需要仔细定义。实验室服务器经常因为重启、休眠变成短暂离线如果立刻发告警邮件噪音太大。我的做法是标记离线后先进入一个观察期如果连续3次心跳检测都未恢复才真正判定为离线如果观察期内恢复心跳自动取消离线标记。这个机制实际上就是在分布式系统里常见的“短暂故障与永久故障分离处理”思想写论文时可以展开讲。7. 扩展方向与答辩现场的心得7.1 这套系统的三个自然扩展方向第一个方向是接入Prometheus生态。当前系统是自己实现了Agent采集协议如果要往生产级演进可以把Agent替换成Prometheus Node Exporter服务端通过PromQL查询数据获得更成熟的指标采集和报警表达式能力。这个改造不推翻现有代码只需要把数据接入层换成Prometheus的HTTP API。第二个方向是加入历史数据对比和预测。当前系统只能看实时和历史曲线如果能基于过去N天的同期数据做基线预测在指标偏离基线时提前预警会比单纯阈值告警更智能。这个方向适合想加入算法元素的同学也是论文里非常好的研究点。第三个方向是告警关联分析。多台服务器同时出问题时往往是某个上游服务故障引发连锁反应。把告警按时间窗口聚类自动推断故障的传播链路就属于智能运维AIOps的范畴了虽然系统实现起来工程量大但作为论文的“展望与不足”非常合适。7.2 如果让我重新做一次会改掉哪些设计一个很明确的点是我不想再手写完整的Agent采集逻辑了。经过了整套开发流程我认识到成熟的采集器在覆盖度和稳定性上远远超出个人实现。如果有机会重新来我会优先把基础资源采集交给开源组件把个人精力集中在告警引擎、数据可视化、WebSocket推送这些真正的业务逻辑上。这样系统的高可用性和可演示性都会更强论文里能够深入写的内容反而更多。另一个修改点是引入消息队列。当前用Java内存队列做指标缓冲虽然解决了同步写入的性能问题但Agent上报高峰和数据库写入高峰之间缺少有效的削峰手段。如果系统规模一旦扩大内存队列满了之后会丢数据。下一版要么引入Kafka要么用Redis的Stream做缓冲这是数据链路可靠性的关键一环。7.3 答辩时容易提到的追问与应对毕设答辩最常见的问题是“这套系统有什么是别人没有的”如果只回答“我做了一个监控系统”老师大概率不满意。我建议把重点放在两个细节上一是告警状态机的设计这个是从生产级监控系统里抽象出来的完整状态闭环体现了系统思维二是Agent自动注册与心跳机制这意味着系统具备了“大规模节点自动纳管”的能力。这两点都是真实的工程问题不是“为毕设而设计的”。被问到工作量时要把整个链路说清楚一份需求分析、一套SpringBoot服务端、一套Agent采集程序、一个Vue前端、一个规则引擎、一份部署文档。老师想要的不是“项目很大”而是“你清楚自己每部分是怎么做出来的”。这比项目本身复杂与否更关键。这套系统的核心价值在于它让我真正理解了“监控”这个运维体系的运行机制。以前我以为监控就是画曲线图做完才明白准确及时的告警、可靠的数据存储、合理的指标建模每一层都是一门学问。做毕业设计最大的收获并不是写出多少行代码而是把一个说不清楚的概念逐步变成了一个能看得见、用得上的工具。在实验室里的那台服务器上看到自己的系统弹出恢复通知的那一刻我觉得这项目值了。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑