CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
Spring Boot 实战入门/课时/Actuator 与健康检查
RawBlame
课时目录16 节

Spring Boot 实战入门

  1. 01Spring Boot 是什么
  2. 02Starter 与自动配置
  3. 03配置与 Profile
  4. 04IoC 与依赖注入
  5. 05Bean 作用域与生命周期
  6. 06Spring AOP 入门
  7. 07Spring MVC 与 REST
  8. 08参数校验与异常处理
  9. 09JDBC 与 MyBatis
  10. 10Spring Data JPA 入门
  11. 11事务管理
  12. 12Spring Security 基础
  13. 13JWT 与 API 鉴权
  14. 14单元测试与 MockMvc
  15. 15Actuator 与健康检查
  16. 16综合练习与进阶路线

Actuator 与健康检查

/actuator/health、指标与运维直觉。

25 分钟

Actuator 与健康检查

这一课你将能做到

  1. 启用 Actuator 并暴露常用端点,读懂 /actuator/health 的聚合检查结果
  2. 自定义 HealthIndicator,把「自己的关键依赖」纳入健康判定
  3. 建立生产环境暴露端点的安全边界(白名单 + 独立端口思路)

为什么要学

应用在服务器上跑着,你怎么知道它「还活着」?数据库连不上了、磁盘满了、线程池打爆了——这些问题用户先发现还是你先发现,决定了你是「值班工程师」还是「救火队长」。

Actuator 是 Spring Boot 内置的运维窗口:一组开箱即用的端点,汇报健康状态、运行指标、环境配置。Kubernetes 的存活探针、Nginx 的健康检查、告警系统,全部对接这些端点。生产事故里最常见的第一动作就是 curl /actuator/health——这一课让你具备这个动作背后的全部知识。

先建立图像

                    ┌──── /actuator/health      应用活着吗?依赖都通吗?
运维/监控/K8s  ────→ ├──── /actuator/metrics     内存、线程、QPS 多少?
                    ├──── /actuator/env         当前生效的配置是什么?
                    └──── /actuator/loggers     日志级别能不能运行时改?
                                ↑
                    Actuator = 应用的「体检报告 + 仪表盘」

默认只开两个端点:health(健康)和 info(应用信息)。其余端点默认关闭是有意设计——env、heapdump 这类端点能泄露配置甚至内存快照,历史上多次成为安全事件主角。暴露原则先记住一句话:开发全开无妨,生产白名单 + 防护。

常用端点作用生产建议
/health聚合健康状态(DB、Redis、磁盘…)暴露,供探针
/info应用版本、构建信息暴露
/metrics各类运行指标(只列名,不吐值)仅内网
/env环境变量与配置(含密码脱敏)禁止外网
/loggers查询/修改日志级别仅内网,紧急调级神器
/threaddump、/heapdump线程/内存快照禁止外网,排查卡死用

跟着做

步骤 1:引入依赖,体验默认行为

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

重启后:

curl http://localhost:8080/actuator/health
# {"status":"UP"}

UP 表示应用与所有已注册的健康检查全部通过。再访问 /actuator/metrics 会 404——没暴露,这就是默认的保守姿态。

步骤 2:暴露端点与查看健康细节

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,loggers    # 白名单式暴露,勿用 include: '*'
  endpoint:
    health:
      show-details: always       # 显示各组件细节;生产常配 show-components + 角色限制
      show-components: always
  info:
    env:
      enabled: true

重启后再看 health(当前项目连着 H2):

{
  "status": "UP",
  "components": {
    "db": { "status": "UP", "details": { "database": "H2", "validationQuery": "isValid()" } },
    "diskSpace": { "status": "UP", "details": { "total": 512110190592, "free": 214748364800 } },
    "ping": { "status": "UP" }
  }
}

自动聚合机制:类路径上有 DataSource,db 检查自动加入;有 Redis 客户端,redis 检查自动加入——又是第 2 课自动配置的条件装配套路。任一组件 DOWN,整体 status 变 DOWN,探针立刻能发现。

⚠️ 细节安全提示:show-details: always 会暴露库名等内部信息,生产更常见做法是 when-authorized(需认证才显示细节)。

步骤 3:自定义 HealthIndicator

场景:你的服务依赖一个第三方「文件转码服务」,它挂了应用整体应报 DOWN:

package com.example.taskflow.health;

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;

import java.net.HttpURLConnection;
import java.net.URI;

@Component("transcode")                  // Bean 名去掉 HealthIndicator 后缀 = 端点里的组件名
public class TranscodeHealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
        try {
            HttpURLConnection conn = (HttpURLConnection)
                    URI.create("http://localhost:9999/ping").toURL().openConnection();
            conn.setConnectTimeout(500);
            conn.setReadTimeout(500);
            if (conn.getResponseCode() == 200) {
                return Health.up().withDetail("provider", "transcode-v1").build();
            }
            return Health.down().withDetail("httpCode", conn.getResponseCode()).build();
        } catch (Exception e) {
            // 依赖不可达:DOWN + 原因,报警系统靠 status 聚合发现它
            return Health.down(e).build();
        }
    }
}

访问 /actuator/health,components 里多出 "transcode"。把这个依赖停掉再访问:

{
  "status": "DOWN",
  "components": {
    "db": { "status": "UP" },
    "transcode": { "status": "DOWN" }
  }
}

一个非关键依赖把整个应用标成 DOWN 是否合理? 不一定——它不该导致 K8s 重启你的 Pod。进阶做法:用 StatusAggregator 自定义聚合策略,或关键存活性检查(liveness)与非关键就绪检查(readiness)分开(Boot 3.1+ 的探针端点 /actuator/health/liveness、/readiness 已内置这套概念)。

步骤 4:用 metrics 观察运行状态

curl http://localhost:8080/actuator/metrics            # 指标名列表
curl http://localhost:8080/actuator/metrics/jvm.memory.used
curl http://localhost:8080/actuator/metrics/http.server.requests

http.server.requests 返回:

{
  "name": "http.server.requests",
  "measurements": [
    { "statistic": "COUNT", "value": 42.0 },
    { "statistic": "TOTAL_TIME", "value": 3.86 },
    { "statistic": "MAX", "value": 0.21 }
  ],
  "availableTags": [
    { "tag": "uri", "values": ["/api/tasks", "/api/auth/login"] },
    { "tag": "status", "values": ["200", "400", "401"] }
  ]
}

COUNT/TOTAL_TIME 一除就是平均耗时,按 tag 下钻可定位慢接口。底层是 Micrometer(指标门面):同样这些指标换个导出器就能进 Prometheus + Grafana——「微服务监控三件套」的地基就是本课内容。自定义业务指标一行代码:

private final Counter taskCreateCounter;

public TaskService(MeterRegistry registry, TaskMapper taskMapper) {
    this.taskCreateCounter = registry.counter("taskflow.task.created");
    this.taskMapper = taskMapper;
}

// 业务方法里:taskCreateCounter.increment();

步骤 5:loggers 端点——不重启改日志级别

线上排查问题需要把某包临时调成 DEBUG,不想重启(会中断服务):

# 查当前级别
curl http://localhost:8080/actuator/loggers/com.example.taskflow
# {"configuredLevel":"INFO","effectiveLevel":"INFO"}

# 运行时改为 DEBUG
curl -X POST http://localhost:8080/actuator/loggers/com.example.taskflow \
     -H "Content-Type: application/json" -d '{"configuredLevel":"DEBUG"}'

# 排查完改回来
curl -X POST http://localhost:8080/actuator/loggers/com.example.taskflow \
     -H "Content-Type: application/json" -d '{"configuredLevel":"INFO"}'

这是运维高频操作:日志级别运行时可调,且改回只需一个请求。

步骤 6:生产暴露的安全边界

management:
  server:
    port: 9090                # 管理端口与业务端口分离,防火墙只对内网开放 9090
  endpoints:
    web:
      exposure:
        include: health,info  # 生产白名单:最少暴露

四层防线按序落:①最少暴露(只开 health/info)→ ②端口分离(9090 不对公网)→ ③网关/防火墙限制来源 IP → ④如需公网可达则挂认证(Security 放行 /actuator/health 其余拦截)。经典反面教材:env 端点直接暴露公网 + show-details 全开 = 配置(即使脱敏)与内部结构对外可见。检查本站生产环境的 actuator 配置,你会看到同样的白名单思路。

讲清楚要点

  1. 健康检查的价值在「自动化发现」:人盯日志是抢救,探针轮询 /health 是预防。聚合语义很简单——任一组件 DOWN 则整体 DOWN,监控体系只看这一个字段。
  2. 端点暴露是安全决策不是技术决策:include 白名单逐个评估,env/heapdump/threaddump 默认不出内网。历史上大量数据泄露事故来自「actuator 全开 + 无认证」。
  3. Micrometer 是指标的事实标准:Actuator 的 metrics 只是 Micrometer 的一层出口;写业务指标用 MeterRegistry,未来无论接 Prometheus 还是 CloudWatch 都不用改代码。
  4. liveness 与 readiness 语义分离(K8s 必备认知):liveness 回答「进程死了要不要重启」(只查进程自身),readiness 回答「能不能接流量」(可以包含依赖)。把非关键依赖混进 liveness 会造成「依赖抖动 → 无限重启」的生产事故。
  5. info 端点适合放版本与构建元数据:配置 spring-boot-maven-plugin 的 build-info 目标后,/actuator/info 返回版本、构建时间——「线上跑的到底是哪个版本」从此一查便知。

你可能会懵的地方

  • 为什么默认只开 health 和 info? 其余端点会暴露配置、线程栈、内存转储,属于敏感信息。Actuator 的默认哲学是「安全优先」,按需白名单暴露。

  • /health 显示 UP 就代表业务正常吗? 只代表「进程活着、注册过的依赖可达」。业务异常(如某个接口全 500)要看 metrics 的错误率与日志。健康检查是「心电图」,不是「全身 CT」。

  • DOWN 状态会导致什么连锁反应? 取决于谁在读:K8s liveness 探针会重启 Pod,负载均衡会摘除节点,告警系统会通知人。因此「哪些依赖进 health、进哪个探针」必须谨慎设计——上一条的三件套意义正在于此。

  • 生产上想看 env 但不能暴露端点怎么办? 通过运维通道:跳板机内网 curl、或日志里打关键配置摘要。原则不变——敏感配置的可见性要收敛到有权限的人。

  • Actuator 和 Prometheus/Grafana 什么关系? Actuator 提供指标数据(Micrometer 格式),Prometheus 定时抓取(/actuator/prometheus 需引 micrometer-registry-prometheus 依赖)存储,Grafana 查询展示与告警。三层分工:产生数据 → 收集存储 → 可视化告警。

错法对照

错法问题正解
include: '*' 暴露所有端点到公网env/heapdump 泄露配置与内存生产白名单 + 内网端口
health 的 show-details: always 且无认证库名、组件细节对外可见when-authorized 或生产收敛
非关键依赖纳入 liveness 检查依赖抖动导致 Pod 无限重启关键依赖进 liveness,其余进 readiness
自定义 HealthIndicator 里做慢查询/health 被拖慢,探针超时误判 DOWN缓存结果或轻量探测
想接监控就自己写 /metrics 接口重复造轮子且格式不统一Micrometer + 官方 registry 依赖

卡点急救

  1. /actuator/health 返回 404:actuator 依赖没引入;或 context-path/管理端口配置导致路径变了(management.endpoints.web.base-path 默认 /actuator);或 Security 拦截了——把 health 加入 permitAll。
  2. 整体 status 是 DOWN 但不知道谁挂了:details 没显示是因为 show-details 默认 never,开发环境配 always 定位;生产用 when-authorized + 认证查看。
  3. 加了 @Component 的自定义 HealthIndicator 没出现:Bean 名以 HealthIndicator 结尾才被自动发现(transcodeHealthIndicator),或直接实现接口时确认在扫描包内。
  4. health 响应很慢拖垮探针:检查自定义 Indicator 的超时设置与数据库连接池余量;对慢依赖改用带缓存的异步探测。

面试常问

  • Actuator 的作用?说说你了解的端点。 生产监控与运维端点集合:health(聚合健康)、info(构建元数据)、metrics(Micrometer 指标)、env(配置)、loggers(运行时调日志级别)、threaddump/heapdump(故障排查)。强调「默认最小暴露 + 白名单」的安全实践。

  • 健康检查机制是怎样的?如何自定义? HealthIndicator 接口聚合:内置组件(DB/Redis/磁盘)由自动配置按类路径条件注册,任一 DOWN 则整体 DOWN;自定义实现 HealthIndicator 返回 Health.up()/down() 并附细节。K8s 场景区分 liveness/readiness 探针端点。

  • 如何保障 Actuator 端点的安全? 最小暴露白名单、管理端口分离且防火墙限内网、接入 Security 认证、show-details 按角色授权;绝不允许 env/heapdump 无认证暴露公网。

  • 你们怎么搭建监控体系? Micrometer 埋点(框架自动 + 业务自定义 Counter/Timer)→ Prometheus 抓取 /actuator/prometheus → Grafana 看板与告警规则;日志侧 filebeat/Loki 聚合,链路侧 SkyWalking/Zipkin——指标、日志、链路三支柱。

自测三问

  1. 默认暴露哪两个端点?为什么其他端点默认关闭?
  2. 写一个自定义 HealthIndicator 需要实现什么接口?返回什么对象?Bean 命名有什么讲究?
  3. liveness 和 readiness 探针的语义区别是什么?把 Redis 检查放进 liveness 有什么风险?

小结一句话

Actuator 是应用的运维仪表盘:health 聚合依赖状态、metrics 经 Micrometer 通向监控体系——暴露多少、谁能看,是和「怎么用」同等重要的安全决策。

延伸

  • Spring Boot 官方文档:Actuator
  • Micrometer 官方文档
  • 下一课:综合练习与进阶路线——把 15 课攒下的零件组装成一个完整项目。
加载本节练习…
← 上一课单元测试与 MockMvc下一课 →综合练习与进阶路线