news 2026/7/12 18:50:41

Day20 Spring Boot Actuator监控体系:生产可观测性标配

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Day20 Spring Boot Actuator监控体系:生产可观测性标配

专栏:《Java后端工程师进阶之路》从CRUD到AI工程师的完整跃迁路径(Day 20/ 90):从"服务挂了才发现"到"服务还没挂就知道",差的不是运气,是一套像样的监控。

场景再现:"线上交易系统响应超时,CPU飙到90%。jstack抓了一堆线程快,最后发现是一个第三方回调接口挂了,线程池全堵在那儿等超时。

答案很扎心——系统没有暴露任何可观测的指标。就像一个黑箱,外面的人只能通过"坏了没"来判断好坏。

后来全面接入了 Spring Boot Actuator,配合 Prometheus + Grafana 搭了一套监控体系。从那以后,服务还没挂,钉钉上就先弹告警了。


二、Actuator 到底是个什么东西

Actuator 是 Spring Boot 官方提供的生产级监控模块。它用一句话概括就是:给你的 Spring Boot 应用装上各种"传感器",把 JVM、Web 容器、数据库连接、自定义业务指标全部暴露出来,供外部监控系统消费。

一句话记住它的定位:Actuator 不是监控系统,它是被监控的那一端。它负责"生产数据",Prometheus 负责"采集数据",Grafana 负责"展示数据"。

2.1 快速接入

Spring Boot 2.x / 3.x 项目,加一个依赖就够了:

<!-- pom.xml --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>

什么配置都不写,启动项目,访问 http://localhost:8080/actuator,你会看到所有默认暴露的端点:

{ "_links": { "self": { "href": "http://localhost:8080/actuator", "templated": false }, "health": { "href": "http://localhost:8080/actuator/health", "templated": false }, "health-path": { "href": "http://localhost:8080/actuator/health/{*path}", "templated": true } } }

默认只暴露了health这一个端点——这是 Spring Boot 的安全策略,细节信息不能随便给人看。

2.2 端点全家福

Actuator 自带了 20+ 个内置端点,我挑几个你一定会用到的:

端点作用一句话讲清楚
/health健康检查服务还活着吗?数据库连得上吗?Redis通吗?
/metrics指标体系JVM内存用了多少?HTTP请求QPS多少?
/info应用信息版本号、构建时间、Git Commit Hash
/env环境变量当前生效的配置项有哪些,值是多少
/loggers日志级别不重启就能调日志级别
/threaddump线程转储等同于jstack,在线看线程状态
/heapdump堆转储等同于jmap,下载.hprof文件分析
/beansBean清单所有Spring Bean以及它们的依赖关系
/mappings请求映射所有@RequestMapping的路由信息

这些端点咋一看像是"调试工具合集",但当你把它们接入监控系统之后,价值就完全不一样了。


三、实战一:健康检查——不只是"活没活着"

很多团队把/actuator/health配在 K8s 的 Liveness Probe 上,返回 200 就认为服务健康。但这远远不够

看一个真实场景:你的服务启动正常,HTTP 端口也在监听,但 Redis 连接池因为网络抖动全部断开。这时候/health如果只返回{"status": "UP"},你的负载均衡器会继续把流量打过来,然后所有需要 Redis 的请求全部报错。

正确的做法:启用详细健康检查。

# application.yml management: endpoint: health: show-details: always # 生产环境建议用 when-authorized show-components: always endpoints: web: exposure: include: health,metrics,prometheus

然后在项目中引入对应的 HealthIndicator:

// 这是 Spring Boot 自带的,引入 starter-data-redis 后自动注册 // 你也可以自定义: import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.stereotype.Component; @Component public class PaymentGatewayHealthIndicator implements HealthIndicator { @Override public Health health() { // 模拟检查第三方支付网关连通性 boolean reachable = checkPaymentGateway(); if (reachable) { return Health.up() .withDetail("gateway", "alipay") .withDetail("latency_ms", 120) .build(); } return Health.down() .withDetail("gateway", "alipay") .withDetail("error", "Connection timeout after 5000ms") .build(); } private boolean checkPaymentGateway() { // 实际项目中,这里发一个 HTTP HEAD 请求探测 return true; } }

接入后,/actuator/health的返回就会是这样:

{ "status": "UP", "components": { "db": { "status": "UP", "details": { "database": "MySQL", "validationQuery": "isValid()" } }, "redis": { "status": "UP", "details": { "version": "7.0.15" } }, "paymentGateway": { "status": "UP", "details": { "gateway": "alipay", "latency_ms": 120 } }, "diskSpace": { "status": "UP", "details": { "total": 500123123712, "free": 320456789012 } } } }

这下运维同事就不用来问你"Redis 是不是挂了"——看一眼健康检查页面,哪个组件出了问题一目了然。

关键知识点:

  • show-details: always在生产环境有安全风险(暴露内部组件细节),建议用when-authorized,配合 Spring Security 做身份校验
  • 自定义 HealthIndicator 一定要快速返回(< 1秒),不要在健康检查里做耗时操作
  • K8s Readiness Probe 比 Liveness Probe 更适合依赖健康检查——服务"活着",但暂时不能接流量

四、实战二:Metrics 指标——给系统装上仪表盘

/actuator/metrics是 Actuator 最值钱的功能。它基于Micrometer这个门面框架,屏蔽了下游监控系统的差异——你用 Prometheus、InfluxDB、Datadog 还是 Graphite,代码完全不用改。

4.1 看一眼默认指标

访问/actuator/metrics会列出所有指标名称(不直接显示值)。要查看具体某个指标,需要加名字:

GET /actuator/metrics/jvm.memory.used

返回:

{ "name": "jvm.memory.used", "measurements": [ { "statistic": "VALUE", "value": 2.3846912E8 } ], "availableTags": [ { "tag": "area", "values": ["heap", "nonheap"] }, { "tag": "id", "values": ["G1 Survivor Space", "G1 Eden Space", ...] } ] }

这里插一句:JVM 领域的几个核心指标你心里要有数:

指标前缀关注什么告警阈值建议
jvm.memory.used/jvm.memory.max堆内存使用率> 85% 告警
jvm.gc.pauseGC 暂停时间P99 > 200ms 告警
jvm.threads.live活跃线程数持续增长 > 500 排查
http.server.requestsHTTP 请求延迟/错误率P99 > 1s 或错误率 > 1%
tomcat.threads.busyTomcat 工作线程繁忙度> 80% 准备扩容

4.2 自定义业务指标

系统指标看完,你自己的业务指标更重要。比如支付接口的调用量、成功率、耗时。

import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Timer; import org.springframework.web.bind.annotation.*; import java.util.concurrent.TimeUnit; @RestController @RequestMapping("/api/payment") public class PaymentController { private final MeterRegistry meterRegistry; private final Timer paymentTimer; private final Counter paymentSuccessCounter; private final Counter paymentFailCounter; public PaymentController(MeterRegistry meterRegistry) { this.meterRegistry = meterRegistry; // Timer 自动记录调用次数、总耗时、最大耗时 this.paymentTimer = Timer.builder("business.payment.request") .description("支付接口请求耗时") .publishPercentileHistogram(true) // 启用直方图,支持 P50/P90/P99 .register(meterRegistry); // Counter 只增不减 this.paymentSuccessCounter = Counter.builder("business.payment.result") .tag("status", "success") .register(meterRegistry); this.paymentFailCounter = Counter.builder("business.payment.result") .tag("status", "fail") .register(meterRegistry); } @PostMapping("/pay") public String pay(@RequestBody PayRequest request) { return paymentTimer.record(() -> { try { // 业务逻辑... String result = doActualPayment(request); paymentSuccessCounter.increment(); return result; } catch (Exception e) { paymentFailCounter.increment(); throw e; } }); } private String doActualPayment(PayRequest request) { // 实际支付逻辑 return "success"; } }

这里有三个常用的 Micrometer 指标类型你必须掌握:

  • Counter:只增不减的计数器。适合计次——请求量、错误数、成功数
  • Gauge:瞬时值,可升可降。当前连接数、队列长度、缓存命中率
  • Timer:记录耗时 + 调用次数。接口延迟、数据库查询耗时
// Gauge 示例:监控线程池队列长度 Gauge.builder("threadpool.queue.size", threadPoolExecutor, ThreadPoolExecutor::getQueueSize) .register(meterRegistry);

4.3 关键配置:别让指标成为性能瓶颈

Actuator 默认配置不一定适合生产环境,下面这个配置我每个项目都会调:

management: metrics: export: prometheus: enabled: true step: 30s # 指标推送间隔,默认1分钟 distribution: percentiles-histogram: http.server.requests: true # 开启 HTTP 请求延迟直方图 slo: http.server.requests: 50ms, 100ms, 200ms, 500ms, 1s # 自定义延迟分桶 endpoints: web: exposure: include: health,metrics,prometheus

几个踩过的坑:

  • percentiles-histogram会大幅度增加指标数据的基数(每个分桶值都产生一套数据),Prometheus 存储压力会上去。如果指标量太大,建议用slo指定有限分桶,而不是全开
  • step设太短(如 5s),Prometheus 抓取频率跟不上会导致数据重复或丢失
  • 不要把 Actuator 端口直接暴露到公网,至少加一层 Spring Security 或独立管理端口

五、实战三:Prometheus + Grafana 构建监控大屏

Actuator 暴露指标只是第一步,真正让数据"活起来"的是 Prometheus + Grafana。

5.1 接入 Prometheus

<dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency>

然后访问/actuator/prometheus,你会看到标准 Prometheus 格式的指标数据:

# HELP jvm_memory_used_bytes The number of used bytes # TYPE jvm_memory_used_bytes gauge jvm_memory_used_bytes{area="heap",id="G1 Eden Space",} 1.2345678E8 jvm_memory_used_bytes{area="heap",id="G1 Survivor Space",} 1.048576E7 ... # HELP business_payment_request_seconds_max # TYPE business_payment_request_seconds_max gauge business_payment_request_seconds_max{application="payment-service",} 0.523

5.2 Prometheus 抓取配置

# prometheus.yml scrape_configs: - job_name: 'payment-service' metrics_path: '/actuator/prometheus' scrape_interval: 30s static_configs: - targets: ['localhost:8080'] labels: application: 'payment-service' env: 'production'

5.3 Grafana 大屏

Grafana 里导入 JVM 监控模板(Dashboard ID: 4701 或者 12856),10分钟就能搭出这样的效果(用文字描述):

  • 左上:服务实例数、运行时长、CPU使用率、堆内存使用率(数字面板)
  • 中间:GC 暂停时间趋势图、GC 次数/频率
  • 下排:HTTP QPS + P99延迟曲线、错误率趋势
  • 右侧:自定义业务指标(支付量、成功率)

5.4 告警规则

光看不够,还要配告警。Prometheus 告警规则示例:

# alerts.yml groups: - name: spring-boot-alerts rules: - alert: HighHeapMemoryUsage expr: sum(jvm_memory_used_bytes{area="heap"}) / sum(jvm_memory_max_bytes{area="heap"}) > 0.85 for: 5m labels: severity: warning annotations: summary: "堆内存使用率超过85%" - alert: HighErrorRate expr: rate(http_server_requests_seconds_count{status=~"5.."}[5m]) / rate(http_server_requests_seconds_count[5m]) > 0.01 for: 3m labels: severity: critical annotations: summary: "HTTP 5xx 错误率超过1%"

再配合 Alertmanager 把告警推到钉钉/企业微信/飞书,这样凌晨三点的电话就换成了一条消息推送。


六、实战四:自定义 Endpoint——暴露你想要的任何信息

Actuator 不仅提供了 20+ 个内置端点,还允许你自定义端点。比如你想暴露当前系统的业务配置快照:

import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.stereotype.Component; import java.util.Map; @Component @Endpoint(id = "businessConfig") public class BusinessConfigEndpoint { @ReadOperation public Map<String, Object> getConfig() { return Map.of( "maxOrderAmount", 50000, "supportedPaymentMethods", new String[]{"alipay", "wechat", "unionpay"}, "maintenanceMode", false, "currentVersion", "3.2.1" ); } }

别忘了在配置里暴露它:

management: endpoints: web: exposure: include: health,metrics,prometheus,businessConfig

现在访问/actuator/businessConfig,直接拿到业务配置快照。这个能力在排查问题时特别有用——不用翻代码、不用查数据库,一个 HTTP 请求就知道当前系统以什么参数在运行。

@Endpoint还支持@WriteOperation@DeleteOperation,可以实现运行时动态调整参数。比如你做了一个特性开关,线上出了问题需要紧急关闭某个功能,直接调端点就行,不用重启。


七、生产环境 Checklist

这套监控体系上线前,对照下面这个清单逐项检查:

1. 安全防护

  • 生产环境不要用show-details: always,改用when-authorized
  • Actuator 端点加 Spring Security 认证,或者配置独立管理端口management.server.port: 8081
  • /heapdump/threaddump生产环境单独鉴权,不要和/health混在一起

2. 性能考量

  • percentiles-histogram按需开启,不要为了"好看"全开——Prometheus 的时序数据量会暴涨
  • 自定义 HealthIndicator 的方法必须快速返回(< 1s),不要在里面做 HTTP 调用等阻塞操作。如果必须检查远程服务,用异步 + 缓存结果
  • 检查/actuator/metrics返回的指标列表,删除不需要的指标以减少内存占用

3. 运维配套

  • Grafana 大屏至少包含:JVM 堆内存、GC 暂停、HTTP QPS/P99、5xx 错误率、自定义核心业务指标
  • 告警规则至少覆盖:堆内存 > 85%、错误率 > 1%、实例宕机
  • 编写运维 Runbook:每个告警对应的排查步骤(好比"堆内存高 →jmap -histo查大对象 → 定位代码")

很多团队把监控当成"锦上添花"的东西,项目赶进度的时候最先砍掉的就是它。但我的经验是:你花在监控上的每一分钟,都会在凌晨三点加倍还给你。

Actuator 的接入成本极低——加一个依赖、写几行配置、挂一个 Grafana 模板,半天就能搞定。但它带来的价值是持续性的:你不再靠"用户投诉"来发现故障,不再靠"猜"来定位问题。你看得到系统的心跳、呼吸、每一次抖动。

这就是"可观测性"的本质:不是出了问题才知道,而是提前看到风险在酝酿。


金句:好的监控不会让你的系统不挂,但会让你在它挂之前就知道它快撑不住了。


下篇预告(Day 21):《Spring事件机制:观察者模式在企业级解耦中的应用》——你会发现,原来不用 MQ、不用 RPC,Spring 自己就藏着一个优雅的组件解耦利器。明天见。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/12 18:49:34

给排水必须记住的常用八大知识点!

给排水必须记住的常用八大知识点! 1 给水要求水压 ①给水入口: 一层,10m;二层,12m;三层及以上层按4(n+1),n为层数。 ②给水: 住宅分户水表前的水压一般宜0.10~0.15MPa; 住宅入户给水压力大于0.35MPa应减压; 给水分区静水压不宜大于0.45MPa; 卫生器具给水配件最大…

作者头像 李华
网站建设 2026/7/12 18:46:41

3步打造你的专属Windows时间管理神器:Catime实战指南

3步打造你的专属Windows时间管理神器&#xff1a;Catime实战指南 【免费下载链接】Catime &#x1f48c;A tiny (995KB) but mighty timer in **pure C** ! — almost no memory usage!❤️‍&#x1f525; Supports clock, countdown, stopwatch, Pomodoro, and fully customi…

作者头像 李华
网站建设 2026/7/12 18:40:13

c++: 哈希表的实现

一、哈希的概念 哈希(hash)⼜称散列&#xff0c;是⼀种组织数据的⽅式。从译名来看&#xff0c;有散乱排列的意思。本质就是通过哈希函数把关键字Key跟存储位置建⽴⼀个映射关系&#xff0c;查找时通过这个哈希函数计算出Key存储的位置&#xff0c;进⾏快速查找。 二、哈希的实…

作者头像 李华
网站建设 2026/7/12 18:39:58

架构解析:ImageSharp内存映射技术实现超大图像零拷贝处理

架构解析&#xff1a;ImageSharp内存映射技术实现超大图像零拷贝处理 【免费下载链接】ImageSharp :camera: A modern, cross-platform, 2D Graphics library for .NET 项目地址: https://gitcode.com/gh_mirrors/im/ImageSharp 技术挑战与行业痛点分析 在现代数字图像…

作者头像 李华
网站建设 2026/7/12 18:39:53

MetaTube SDK Go测试策略:单元测试、集成测试与端到端测试

MetaTube SDK Go测试策略&#xff1a;单元测试、集成测试与端到端测试 【免费下载链接】metatube-sdk-go MetaTube SDK & API Server in Golang 项目地址: https://gitcode.com/gh_mirrors/me/metatube-sdk-go MetaTube SDK Go作为一款专业的元数据获取和图像处理Go…

作者头像 李华