第1章:Spring Boot Actuator 概述
1.1 什么是 Spring Boot Actuator
| 概念名称 | 说明 | 注意事项 |
|---|
| Spring Boot Actuator | 是 Spring Boot 提供的一个用于监控和管理应用程序的模块,通过暴露一系列预定义的 HTTP 或 JMX 端点(endpoints),帮助开发者了解应用的运行状态、性能指标、配置信息等。 | Actuator 本身不开启任何安全防护,生产环境中必须配合安全措施使用。 |
| 端点(Endpoint) | Actuator 提供的每一个监控功能入口,如 /health、/info、/metrics 等,每个端点对应一类运行时数据。 | 并非所有端点默认都对外暴露,部分敏感端点需手动启用。 |
| 生产就绪(Production-ready) | Actuator 的设计目标是让应用具备”生产就绪”能力,即无需额外开发即可获得基础监控能力。 | “生产就绪”不等于”生产可用”,仍需结合安全、权限、网络策略进行加固。 |
1.2 Actuator 的核心作用与应用场景
| 核心作用 | 说明 | 典型应用场景 |
|---|
| 应用健康检查 | 通过 /health 端点判断应用是否正常运行,常用于 Kubernetes、Docker 等容器平台的探针检测。 | 容器编排系统中的 Liveness 和 Readiness 探针。 |
| 运行时指标收集 | 通过 /metrics 获取 JVM 内存、线程、HTTP 请求延迟等性能数据,便于性能分析和告警。 | 集成 Prometheus + Grafana 实现可视化监控。 |
| 配置与环境查看 | 通过 /env 和 /configprops 查看当前生效的配置项和环境变量,便于排查配置问题。 | 开发调试阶段快速验证配置是否生效。 |
| 自动配置诊断 | 通过 /conditions 查看自动配置的启用/未启用原因,辅助理解 Spring Boot 自动装配机制。 | 分析为何某个自动配置未生效。 |
| Bean 依赖关系查看 | 通过 /beans 查看容器中所有 Bean 及其依赖关系,有助于理解应用结构。 | 调试循环依赖或 Bean 注入失败问题。 |
| 日志级别动态调整 | 通过 /loggers 动态修改日志级别,无需重启应用即可开启 DEBUG 日志。 | 生产环境临时开启详细日志进行问题排查。 |
1.3 生产环境使用建议与安全注意事项
| 建议/注意事项 | 说明 | 风险提示 |
|---|
| 仅暴露必要端点 | 通过 management.endpoints.web.exposure.include 显式指定需要暴露的端点,避免全部暴露。 | 暴露过多端点可能导致敏感信息泄露(如数据库连接、内部服务地址)。 |
| 敏感端点访问控制 | 对 /env、/beans、/shutdown 等敏感端点启用身份认证(如 Spring Security)。 | 未授权访问可能导致配置篡改、应用关闭等严重后果。 |
| 使用独立管理端口 | 配置 management.server.port 使用独立端口运行 Actuator 端点,与主应用隔离。 | 共用端口可能增加攻击面,独立端口可配合防火墙限制访问来源。 |
| 禁用危险端点 | 如非必要,禁用 /shutdown 端点(设置 management.endpoint.shutdown.enabled=false)。 | 启用后可通过 POST 请求关闭应用,极易被滥用。 |
| 启用 HTTPS | 在生产环境中为 Actuator 端点启用 HTTPS 加密传输。 | HTTP 明文传输可能被中间人窃取监控数据。 |
| 避免暴露在公网 | Actuator 端点应仅限内网或运维网络访问,禁止直接暴露在公网。 | 公网暴露极大增加被扫描和攻击的风险。 |
第2章:快速入门与环境搭建
2.1 添加 Actuator 依赖(Maven/Gradle)
| 构建工具 | 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| Maven | 添加依赖 | 在 pom.xml 中添加 <dependency> | 引入 Spring Boot Actuator 模块 | <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency> | 确保项目已继承 spring-boot-starter-parent 或正确配置 dependencyManagement。 |
| Gradle | 添加依赖 | 在 build.gradle 中使用 implementation | 引入 Spring Boot Actuator 模块 | dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
} | 使用 Gradle Kotlin DSL 时语法略有不同,应写为 implementation("org.springframework.boot:spring-boot-starter-actuator")。 |
2.2 启用和暴露健康端点(health)
| 配置项 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 启用 health 端点 | management.endpoint.health.enabled=true | 启用 health 端点功能(默认已启用) | application.yml:
management:
endpoint:
health:
enabled: true | 通常无需显式配置,除非之前被禁用。 |
| 暴露 health 端点(Web) | management.endpoints.web.exposure.include=health | 将 health 端点通过 HTTP 暴露 | application.yml:
management:
endpoints:
web:
exposure:
include: health | 若需暴露多个端点,可用逗号分隔,如 health,info,metrics。 |
| 显示详细健康信息 | management.endpoint.health.show-details=always / never / when-authorized | 控制是否显示健康详情 | application.yml:
management:
endpoint:
health:
show-details: when-authorized | 生产环境建议设为 when-authorized 或 never,避免信息泄露。 |
| 按角色控制详情显示 | management.endpoint.health.roles=admin | 指定查看详细信息所需的角色 | management:
endpoint:
health:
roles: admin | 需配合 Spring Security 使用,否则无效。 |
2.3 访问默认端点并查看响应
| 端点路径 | HTTP 方法 | 用途 | 访问示例 | 响应示例(简化) | 注意事项 |
|---|
/actuator/health | GET | 查看应用健康状态 | curl http://localhost:8080/actuator/health | {"status":"UP"} | 若集成数据库、Redis 等,会显示各组件状态。 |
/actuator/info | GET | 查看自定义应用信息 | curl http://localhost:8080/actuator/info | {"app":{"name":"demo","version":"1.0"}} | 需在 application.yml 中配置 info.* 属性。 |
/actuator | GET | 查看所有暴露的端点链接 | curl http://localhost:8080/actuator | {"_links":{"self":{...},"health":{...}}} | 返回 HAL 格式导航信息,便于程序发现端点。 |
/actuator/env | GET | 查看运行时环境变量 | curl http://localhost:8080/actuator/env | {"activeProfiles":[],"propertySources":[...]} | 包含大量敏感信息,生产环境务必保护。 |
/actuator/metrics | GET | 查看可用指标列表 | curl http://localhost:8080/actuator/metrics | {"names":["jvm.memory.used","http.server.requests",...]} | 可进一步访问具体指标,如 /actuator/metrics/jvm.memory.used。 |
注意:默认上下文路径为 /actuator,可通过 management.endpoints.web.base-path 修改。
第3章:核心端点详解
3.1 /health:应用健康状态监控
| 方法/配置 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 查看健康状态 | GET /actuator/health | 获取应用整体健康状态 | curl http://localhost:8080/actuator/health | 默认只返回 status(UP/DOWN/OUT_OF_SERVICE) |
| 显示详细健康信息 | management.endpoint.health.show-details=always | 强制显示所有健康详情 | management:
endpoint:
health:
show-details: always | 生产环境不推荐使用 always,建议使用 when-authorized |
| 授权后显示详情 | management.endpoint.health.show-details=when-authorized | 登录后可查看健康详情 | management:
endpoint:
health:
show-details: when-authorized | 需配合 Spring Security 实现认证 |
| 自定义健康指示器 | 实现 HealthIndicator 接口 | 添加自定义健康检查逻辑 | java\npublic class CustomHealthIndicator implements HealthIndicator {\n @Override\n public Health health() {\n return Health.up().withDetail("custom", "OK").build();\n }\n} | Bean 名称需以 “HealthIndicator” 结尾,如 databaseHealthIndicator |
| 健康组配置 | management.endpoint.health.group.custom.include=customHealth | 将自定义健康指示器归入特定组 | management:
endpoint:
health:
group:
custom:
include: customHealth | 可创建多个健康组用于不同场景(如 readiness、liveness) |
3.2 /info:自定义应用信息展示
| 方法/配置 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 配置静态信息 | info.<key>=<value> | 在配置文件中定义应用信息 | yaml\ninfo:\n app:\n name: MyApp\n version: 1.0.0\n build:\n time: 2025-09-28 | 支持嵌套结构,会自动转换为 JSON 响应 |
| Maven 项目自动填充 | ${} 占位符 | 从 pom.xml 读取项目信息 | yaml\ninfo:\n app:\n name: ${project.name}\n version: ${project.version} | 需启用 resource filtering,如 Maven 的 <filtering>true</filtering> |
| Gradle 项目填充 | 使用 build-info 插件 | 生成 build-info.properties | bootBuildInfo {} | 在 build.gradle 中应用插件 spring-boot-plugin |
| 动态信息提供 | 实现 InfoContributor 接口 | 提供运行时动态信息 | java\npublic class BuildTimeInfoContributor implements InfoContributor {\n @Override\n public void contribute(Info.Builder builder) {\n builder.withDetail("build.time", System.currentTimeMillis());\n }\n} | 可用于添加构建时间、Git 提交哈希等 |
3.3 /metrics:应用性能指标获取
| 方法/配置 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 查看指标列表 | GET /actuator/metrics | 获取所有可用指标名称 | curl http://localhost:8080/actuator/metrics | 返回指标名称数组 |
| 查看具体指标 | GET /actuator/metrics/<metric> | 获取指定指标的当前值和标签 | curl http://localhost:8080/actuator/metrics/jvm.memory.used | 可附加 tags 参数过滤,如 ?tag=area:heap |
| JVM 内存指标 | jvm.memory.used, jvm.memory.max | 监控 JVM 各区域内存使用情况 | /actuator/metrics/jvm.memory.used | 包含 heap、non-heap、各代空间 |
| HTTP 请求指标 | http.server.requests | 监控所有 HTTP 请求的响应时间、次数 | /actuator/metrics/http.server.requests | 自动按 status、method、uri 等打标签 |
| 自定义指标注册 | MeterRegistry 提供的方法 | 注册自定义监控指标 | java\n@Autowired\nprivate MeterRegistry registry;\nregistry.counter("request.count").increment(); | 推荐通过依赖注入使用 MeterRegistry |
3.4 /env:运行时环境变量查看
| 方法/配置 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 查看所有环境属性 | GET /actuator/env | 获取所有 PropertySource 及其属性 | curl http://localhost:8080/actuator/env | 包含 application.yml、系统变量、命令行参数等 |
| 查看特定属性源 | GET /actuator/env/<name> | 获取指定属性源的全部属性 | curl http://localhost:8080/actuator/env/applicationConfig:[application.yml] | name 可从完整响应中获取 |
| 查看单个属性 | GET /actuator/env/<property> | 查询某个属性的值 | curl http://localhost:8080/actuator/env/server.port | 返回值可能被掩码(如密码类属性) |
| 属性掩码机制 | 默认行为 | 防止敏感信息泄露 | 属性名包含 password、secret、key 等会被掩码 | 可通过 management.info.env.ignore-names 自定义 |
| 修改运行时属性 | POST /actuator/env | 动态添加环境属性 | 需配合 @RefreshScope 使用 | 此操作非常危险,生产环境应禁用或严格保护 |
3.5 /beans:Spring 容器 Bean 信息
| 方法/配置 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 查看所有 Bean | GET /actuator/beans | 获取容器中所有 Bean 的定义和依赖关系 | curl http://localhost:8080/actuator/beans | 返回 JSON 包含 beanName、scope、type、dependencies 等 |
| Bean 名称 | - | 唯一标识一个 Bean | userService | 通常为类名首字母小写 |
| Bean 作用域 | singleton, prototype 等 | 定义 Bean 的生命周期 | scope: singleton | 大多数 Bean 为单例 |
| Bean 来源 | resource, definingClass | 指明 Bean 的配置位置 | definingClass: com.example.MyConfig | 有助于定位配置类 |
| 依赖关系 | dependencies[] | 列出该 Bean 依赖的其他 Bean | "dependencies": ["dataSource", "userRepository"] | 可用于分析依赖图 |
3.6 /conditions:自动配置条件报告
| 方法/配置 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 查看自动配置报告 | GET /actuator/conditions | 获取自动配置的评估结果 | curl http://localhost:8080/actuator/conditions | 显示哪些配置类被应用,哪些未被应用 |
positiveMatches | - | 条件匹配成功并启用的自动配置 | json\n"datasourceAutoConfiguration": {\n "notMatched": [],\n "matched": [ ... ]\n} | 表示该配置已生效 |
negativeMatches | - | 条件不匹配或被排除的自动配置 | json\n"RabbitAutoConfiguration": {\n "notMatched": [\n { "condition": "RabbitAvailableCondition", ... }\n ]\n} | 帮助理解为何某功能未启用 |
exclusions | - | 被显式排除的自动配置类 | @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) | 可在报告中看到排除原因 |
| 未满足条件 | condition, message | 显示具体未满足的条件 | "condition": "OnPropertyCondition", "message": "@ConditionalOnProperty missing my.feature.enabled" | 是排查自动配置问题的关键 |
3.7 /mappings:请求映射信息
| 方法/配置 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 查看所有映射 | GET /actuator/mappings | 获取所有 @RequestMapping 的端点信息 | curl http://localhost:8080/actuator/mappings | 包含 handler 方法、路径、HTTP 方法、生产者/消费者等 |
handler | - | 处理请求的 Controller 方法 | handler: "com.example.UserController#getUser(String)" | 显示类名和方法签名 |
predicate | - | 映射的匹配条件 | "predicate": "GET /user/{id}" | 包含路径、方法、参数等条件 |
details | - | 详细信息(如 produces, consumes) | produces: "application/json" | 用于理解内容协商行为 |
dispatcherType | REQUEST, ASYNC 等 | 请求分发类型 | dispatcherType: REQUEST | 通常为 REQUEST |
| 可读性 | - | 结构化展示所有接口 | 响应为树形结构,按 handler 分组 | 便于生成 API 文档或进行安全审计 |
3.8 /threads:线程状态快照
| 方法/配置 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 获取线程快照 | GET /actuator/threads | 获取当前 JVM 所有线程的状态信息 | curl http://localhost:8080/actuator/threads | 返回线程名、ID、状态、栈轨迹等 |
| 线程状态 | RUNNABLE, BLOCKED, WAITING 等 | 表示线程当前执行状态 | state: RUNNABLE | BLOCKED 可能表示锁竞争 |
| 栈轨迹 | stackTrace[] | 线程执行的调用栈 | json\n"stackTrace": [\n { "className": "com.example.Service", "methodName": "process" }\n] | 用于分析死锁或性能瓶颈 |
| 线程名称 | - | 线程的逻辑名称 | threadName: "http-nio-8080-exec-1" | Tomcat 线程池有固定命名模式 |
| 是否阻塞 | blockedCount, blockedTime | 统计线程被阻塞的次数和时间 | blockedCount: 5 | 高频阻塞可能影响性能 |
| 死锁检测 | deadlock | 标记是否存在死锁 | "deadlocked": false | 若为 true 需立即排查 |
3.9 /shutdown:优雅关闭应用(需启用)
| 方法/配置 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 启用 shutdown 端点 | management.endpoint.shutdown.enabled=true | 启用 shutdown 功能 | yaml\nmanagement:\n endpoint:\n shutdown:\n enabled: true | 默认为 false,必须显式启用 |
| 关闭应用 | POST /actuator/shutdown | 发送 POST 请求关闭应用 | curl -X POST http://localhost:8080/actuator/shutdown | 应用将正常关闭,执行销毁逻辑 |
| 响应内容 | - | 关闭前的确认信息 | {"message":"Shutting down, bye..."} | 成功关闭后服务不再响应 |
| 安全风险 | - | 可远程关闭应用 | 无 | 极其危险,生产环境严禁启用 |
| 替代方案 | - | 使用进程信号或容器管理 | kill -15 <pid> | 更安全的关闭方式 |
3.10 /loggers:日志级别动态调整
| 方法/配置 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 查看日志级别 | GET /actuator/loggers | 获取所有 logger 的当前级别 | curl http://localhost:8080/actuator/loggers | 包含 configuredLevel 和 effectiveLevel |
| 查看特定 logger | GET /actuator/loggers/<name> | 获取指定 logger 的级别 | curl http://localhost:8080/actuator/loggers/com.example | name 为包名或类名 |
| 修改日志级别 | POST /actuator/loggers/<name> | 动态设置 logger 级别 | bash\ncurl -X POST http://localhost:8080/actuator/loggers/com.example \\\n -H "Content-Type: application/json" \\\n -d '{"configuredLevel": "DEBUG"}' | 立即生效,无需重启 |
| 重置日志级别 | POST /actuator/loggers/<name> | 重置为默认级别 | { "configuredLevel": null } | 清除自定义设置 |
| 日志级别 | TRACE, DEBUG, INFO, WARN, ERROR | 日志严重程度等级 | configuredLevel: DEBUG | 设置过低可能导致日志爆炸 |
3.11 /heapdump:堆内存快照生成
| 方法/配置 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 生成堆转储 | GET /actuator/heapdump | 触发 JVM 生成 heap dump 文件 | curl http://localhost:8080/actuator/heapdump -o heap.hprof | 下载 hprof 格式文件 |
| 默认启用 | - | 通常默认启用 | 无需额外配置 | 可通过 management.endpoint.heapdump.enabled 控制 |
| 文件格式 | hprof | Java 堆内存快照标准格式 | heap.hprof | 可用 JVisualVM、Eclipse MAT 等工具分析 |
| 性能影响 | - | 生成期间应用暂停 | STW(Stop-The-World) | 大堆内存应用可能暂停数秒至数十秒 |
| 存储位置 | 临时目录 | 文件写入系统临时目录 | 由 JVM 决定 | 确保磁盘空间充足 |
| 安全控制 | - | 防止未授权下载 | 配合 Spring Security 保护 | 堆转储可能包含敏感数据 |
3.12 /prometheus:Prometheus 监控集成(需依赖)
| 方法/配置 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 添加 Micrometer Prometheus 依赖 | Maven/Gradle 依赖 | 启用 Prometheus 格式输出 | io.micrometer micrometer-registry-prometheus | 必须添加此依赖,否则端点 404 |
| 暴露 prometheus 端点 | management.endpoints.web.exposure.include=prometheus | 通过 Web 暴露 | yaml\nmanagement:\n endpoints:\n web:\n exposure:\n include: health,info,prometheus | 默认路径为 /actuator/prometheus |
| 访问指标 | GET /actuator/prometheus | 获取 Prometheus 格式指标 | curl http://localhost:8080/actuator/prometheus | 返回文本格式,每行一个指标 |
| Prometheus 格式 | - | 标准的 Prometheus 指标输出 | \n# HELP jvm_memory_used_bytes\njvm_memory_used_bytes{area="heap",...} 1.23e8 | 可被 Prometheus Server 抓取 |
| 配置抓取 | Prometheus 配置文件 | 添加 scrape job | yaml\n- job_name: 'spring_app'\n metrics_path: '/actuator/prometheus'\n static_configs:\n - targets: ['localhost:8080'] | 需在 Prometheus 中配置目标 |
第4章:端点配置与安全控制
4.1 配置端点的启用与暴露(Web/JMX)
| 配置项 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 启用端点(通用) | management.endpoint.<id>.enabled=true/false | 控制指定端点是否启用 | yaml\nmanagement:\n endpoint:\n shutdown:\n enabled: false | 默认多数端点已启用,shutdown 默认禁用 |
| Web 暴露包含 | management.endpoints.web.exposure.include=* 或列表 | 指定通过 HTTP 暴露的端点 | yaml\nmanagement:\n endpoints:\n web:\n exposure:\n include: health,info,metrics | 使用 * 会暴露所有启用的端点,生产环境慎用 |
| Web 暴露排除 | management.endpoints.web.exposure.exclude=<endpoints> | 排除特定端点不通过 HTTP 暴露 | yaml\nmanagement:\n endpoints:\n web:\n exposure:\n exclude: env,beans | 与 include 互斥,优先级更高 |
| JMX 暴露包含 | management.endpoints.jmx.exposure.include=* 或列表 | 指定通过 JMX 暴露的端点 | yaml\nmanagement:\n endpoints:\n jmx:\n exposure:\n include: * | JMX 通常用于本地监控工具(如 JConsole) |
| JMX 域名设置 | management.endpoint.jmx.domain | 设置 JMX MBean 的域名称 | yaml\nmanagement:\n endpoint:\n jmx:\n domain: org.springframework.boot | 默认为空,MBean 将在默认域注册 |
4.2 自定义端点访问路径(path)与基础路径(base-path)
| 配置项 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 自定义基础路径 | management.endpoints.web.base-path | 修改所有端点的根路径 | yaml\nmanagement:\n endpoints:\n web:\n base-path: /manage | 默认为 /actuator,修改后所有端点前缀变更 |
| 自定义单个端点路径 | management.endpoints.web.path-mapping.<id> | 为特定端点设置别名路径 | yaml\nmanagement:\n endpoints:\n web:\n path-mapping:\n health: /status\n prometheus: /metrics | 常用于 /prometheus 映射到 /metrics 以兼容 Prometheus 默认配置 |
| 禁用基础路径前缀 | management.server.servlet.context-path | 将管理端点与主应用共享上下文 | yaml\nmanagement:\n server:\n servlet:\n context-path: / | 结合 base-path 设置,可实现扁平路径结构 |
| 独立管理端口 | management.server.port | 在独立端口运行 Actuator | yaml\nmanagement:\n server:\n port: 8081 | 推荐生产环境使用,便于网络隔离和安全策略配置 |
| 上下文路径隔离 | management.server.servlet.context-path | 为管理服务设置独立上下文 | yaml\nmanagement:\n server:\n servlet:\n context-path: /admin | 需配合独立端口使用,避免冲突 |
4.3 敏感端点的安全保护(配合 Spring Security)
| 安全配置方式 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 基于角色访问控制 | HttpSecurity 配置 | 限制端点访问所需角色 | java\n@Configuration\npublic class SecurityConfig {\n @Bean\n public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {\n http\n .requestMatcher(EndpointRequest.toAnyEndpoint())\n .authorizeRequests()\n .anyRequest().hasRole("ACTUATOR")\n .and()\n .httpBasic();\n return http.build();\n }\n} | EndpointRequest.toAnyEndpoint() 匹配所有端点 |
| 白名单放行 | permitAll() | 允许公开访问某些端点 | java\nhttp\n .requestMatcher(EndpointRequest.to(HealthEndpoint.class, InfoEndpoint.class))\n .permitAll()\n .and()\n .requestMatcher(EndpointRequest.toAnyEndpoint())\n .hasRole("ACTUATOR") | 常用于开放 /health 和 /info 供探针调用 |
| 按端点类型过滤 | EndpointRequest.to() | 精确指定可访问的端点类型 | EndpointRequest.to(HealthEndpoint.class) | 接收一个或多个端点类作为参数 |
| 按端点 ID 过滤 | EndpointRequest.toNamed() | 按端点 ID(如 “beans”, “env”)过滤 | EndpointRequest.toNamed("health", "info") | 适用于无法导入具体类的场景 |
| 启用 CSRF 保护 | 默认启用 | 防止跨站请求伪造 | 无(默认行为) | 若使用表单或 POST 操作(如 /shutdown),需处理 CSRF Token |
| 禁用 CSRF(谨慎) | csrf().disable() | 禁用 CSRF(仅 API 场景) | http.csrf().disable() | 仅在纯 API、无状态服务中考虑,否则有安全风险 |
4.4 生产环境端点暴露最佳实践
| 最佳实践 | 说明 | 推荐配置示例 | 注意事项 |
|---|
| 最小化暴露原则 | 仅暴露必要的监控端点 | yaml\nmanagement:\n endpoints:\n web:\n exposure:\n include: health,info,prometheus | 避免暴露 env, beans, shutdown 等敏感端点 |
| 使用独立管理端口 | 将监控端点与业务接口隔离 | yaml\nmanagement:\n server:\n port: 8081 | 可结合防火墙策略,仅允许运维网络访问该端口 |
| 强制身份认证 | 所有敏感端点必须认证 | 配合 Spring Security,使用 HTTPS + Basic Auth 或 OAuth2 | 公网暴露必须启用认证 |
| 关闭危险端点 | 禁用可修改应用状态的端点 | yaml\nmanagement:\n endpoint:\n shutdown:\n enabled: false | shutdown 端点极易被滥用,生产环境应关闭 |
| 启用 HTTPS | 加密传输监控数据 | 配置 SSL 证书,使用 HTTPS 访问管理端口 | 防止监控数据在传输中被窃取 |
| 日志审计 | 记录所有对 Actuator 端点的访问 | 使用 AOP 或 WebFilter 记录请求日志 | 便于事后审计和追踪异常访问 |
| 定期审查暴露列表 | 随着应用演进重新评估暴露的端点 | 定期检查 exposure.include 列表 | 避免因历史配置导致不必要的暴露 |
第5章:自定义监控端点
5.1 使用 @Endpoint 创建自定义端点
| 注解/配置 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
@Endpoint | @Endpoint(id = "custom") | 定义一个自定义监控端点 | java\n@Endpoint(id = "custom")\npublic class CustomEndpoint { } | id 必须唯一,且只能包含小写字母、数字、连字符 |
@Component | Spring Bean 注解 | 将端点注册为 Spring 容器 Bean | java\n@Component\npublic class CustomEndpoint { } | 必须将端点类声明为 Bean,否则无法被发现 |
@WebEndpointExtension | Web 扩展 | 为已有端点添加 Web 操作 | java\n@WebEndpointExtension(endpoint = HealthEndpoint.class)\npublic class HealthWebExtension { } | 用于扩展内置端点的 Web 行为 |
@JmxEndpointExtension | JMX 扩展 | 为已有端点添加 JMX 操作 | java\n@JmxEndpointExtension(endpoint = HealthEndpoint.class)\npublic class HealthJmxExtension { } | 用于 JMX 场景的扩展 |
| 端点线程模型 | 同步执行 | 操作在请求线程中执行 | 无特殊配置 | 耗时操作应异步处理,避免阻塞 |
| 端点可用性 | 默认可用 | 端点在启用后即可访问 | 无需额外配置 | 可通过 @ReadOperation 等注解定义操作 |
5.2 使用 @ReadOperation 实现读取操作
| 注解/方法 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
@ReadOperation | 标注在方法上 | 定义一个可读操作(对应 HTTP GET) | java\n@ReadOperation\npublic Map<String, Object> getStatus() {\n Map<String, Object> result = new HashMap<>();\n result.put("status", "OK");\n result.put("timestamp", System.currentTimeMillis());\n return result;\n} | 方法返回值将自动序列化为 JSON 响应 |
| 返回类型 | 支持 POJO、Map、基本类型 | 定义响应数据结构 | public CustomStatus getStatus() { ... } | 推荐使用不可变对象或标准集合 |
| 无参数方法 | - | 最简单的读取操作 | public String getName() { return "MyApp"; } | 适用于获取静态或实时状态 |
| 响应状态码 | 默认 200 | 成功时返回 200 OK | 无 | 异常情况下自动返回 500 |
| 内容协商 | 自动支持 | 根据 Accept 头返回适当格式 | 通常为 application/json | Actuator 内部处理 |
| 性能要求 | 快速响应 | 读取操作应尽量轻量 | 避免在方法中执行耗时计算或远程调用 | 防止影响监控系统稳定性 |
5.3 使用 @WriteOperation 实现写入操作
| 注解/方法 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
@WriteOperation | 标注在方法上 | 定义一个可写操作(对应 HTTP POST) | java\n@WriteOperation\npublic Map<String, Object> updateConfig(@Selector String key, @Value String value) {\n config.put(key, value);\n return Map.of("result", "updated", "key", key);\n} | 用于修改应用状态,需谨慎使用 |
| 方法参数 | 支持多个参数 | 接收请求体或路径参数 | 参数可使用 @Value, @Selector 等注解 | 请求体需为 JSON 对象 |
| HTTP 方法 | POST | 触发写入操作 | bash\ncurl -X POST http://localhost:8080/actuator/custom \\\n -H "Content-Type: application/json" \\\n -d '{"key":"mode","value":"debug"}' | 必须使用 POST 方法 |
| 安全控制 | 必须保护 | 写入操作涉及状态变更 | 配合 Spring Security 强制认证 | 建议仅限管理员角色访问 |
| 幂等性 | 建议实现 | 多次执行应产生相同结果 | 设计时考虑幂等性 | 避免重复操作导致状态混乱 |
| 响应处理 | 返回操作结果 | 提供成功/失败反馈 | 返回包含状态信息的 JSON | 便于调用方判断操作结果 |
5.4 使用 @DeleteOperation 实现删除操作
| 注解/方法 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
@DeleteOperation | 标注在方法上 | 定义一个删除操作(对应 HTTP DELETE) | java\n@DeleteOperation\npublic Map<String, Object> clearCache(@Selector String cacheName) {\n cacheManager.getCache(cacheName).clear();\n return Map.of("result", "cleared", "cache", cacheName);\n} | 用于清除缓存、重置状态等操作 |
| 参数绑定 | @Selector | 从 URL 路径提取参数 | java\n@DeleteOperation\npublic void deleteItem(@Selector String id) { ... } | 类似于 RESTful 的路径变量 |
| HTTP 方法 | DELETE | 触发删除操作 | curl -X DELETE http://localhost:8080/actuator/custom/cache/user | 必须使用 DELETE 方法 |
| 安全性要求 | 极高 | 删除操作不可逆 | 必须启用身份认证和授权 | 建议记录操作日志 |
| 响应状态 | 200 或 204 | 成功删除返回 200(有响应体)或 204(无内容) | 可返回操作结果或直接 void | void 方法自动返回 204 |
| 使用场景 | 清理、重置 | 适用于缓存清理、计数器重置等 | 避免用于删除持久化数据 | 应限于运行时状态清理 |
5.5 自定义端点的参数传递与验证
| 参数方式 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
@Selector | 方法参数注解 | 从 URL 路径提取参数 | java\n@ReadOperation\npublic String getItem(@Selector String name) { ... } | 对应路径如 /actuator/custom/{name} |
@Value | 方法参数注解 | 从 JSON 请求体提取字段 | java\n@WriteOperation\npublic void update(@Value String value) { ... } | 请求体需为 { "value": "new-value" } |
| 复杂对象参数 | POJO 参数 | 接收完整的 JSON 对象 | public void updateConfig(ConfigUpdateRequest req) { ... } | 自动反序列化,支持嵌套结构 |
| 参数验证 | JSR-303 注解 | 对参数进行校验 | public void update(@NotBlank @Value String value) { ... } | 需引入 validation 依赖 |
| 异常处理 | 抛出 IllegalArgumentException | 参数无效时抛出异常 | if (value == null) throw new IllegalArgumentException("Value must not be null"); | Actuator 会自动转换为 400 响应 |
| 多参数组合 | 多个注解参数 | 同时使用路径和请求体参数 | java\n@WriteOperation\npublic void update(@Selector String id, @Value Map<String, Object> props) { ... } | 灵活支持复杂操作 |
| 默认值处理 | 方法内判断 | 提供参数默认值 | if (timeout == null) timeout = 5000; | 适用于可选参数 |
第6章:指标监控与 Micrometer 集成
6.1 Micrometer 核心概念(Meter、MeterRegistry、Timer、Counter 等)
| 概念 | 说明 | 注意事项 |
|---|
| Meter | 指标的基本单位,代表一个可测量的量(如计数、时间、值)。包含名称、标签(tags)和一组数据。 | 所有指标类型都实现 Meter 接口,是监控数据的最小单元。 |
| MeterRegistry | 指标注册中心,负责创建和管理所有 Meter 实例,并将其导出到监控系统(如 Prometheus)。 | 应用中通常只有一个全局的 MeterRegistry Bean,通过 @Autowired 注入使用。 |
| Counter | 单调递增计数器,用于记录事件发生的总次数(如 HTTP 请求数、错误数)。 | 只能增加,不能减少;适用于累计型指标。 |
| Gauge | 仪表,用于记录瞬时值(如当前在线用户数、队列长度)。可增可减。 | 通常通过回调函数定期采集值;适用于状态型指标。 |
| Timer | 计时器,用于记录操作的执行时间分布(如方法调用耗时、HTTP 响应时间)。 | 同时记录调用次数和总耗时,支持统计平均值、百分位等。 |
| DistributionSummary | 分布摘要,用于记录事件大小的分布情况(如请求体大小、响应字节数)。 | 类似 Timer,但不关注时间,而是关注任意数值的分布。 |
| Tag(标签) | 键值对,用于对指标进行维度切片(如 method=GET, uri=/api/user)。 | 是实现多维监控的关键,可组合使用进行数据筛选和聚合。 |
| MeterFilter | 指标过滤器,用于控制哪些 Meter 被注册、重命名、添加标签等。 | 可通过配置实现全局标签添加或指标过滤。 |
6.2 使用 Counter 记录事件次数
| 方法 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 创建 Counter | Counter.builder(name).register(registry) | 构建并注册一个计数器 | java\n@Autowired\nprivate MeterRegistry registry;\n\nCounter counter = Counter.builder("request.count")\n .tag("method", "GET")\n .description("Total number of GET requests")\n .register(registry); | 建议将 Counter 实例缓存为成员变量,避免重复创建 |
| 增加计数 | counter.increment() | 事件发生时增加计数 | counter.increment(); | 默认增加 1 |
| 指定增量 | counter.increment(double amount) | 增加指定数值 | counter.increment(2.5); | 支持浮点数,但通常用于整数计数 |
| 带标签计数 | registry.counter(name, tags) | 快速创建带标签的计数器 | registry.counter("request.count", "status", "success").increment(); | 适用于临时或简单计数场景 |
| 自动计数(HTTP) | 内置自动配置 | 自动记录 Spring MVC 请求 | 无需代码 | 通过 management.metrics.web.server.auto-time-requests=true 控制 |
| 性能影响 | 极低 | 原子操作,性能开销小 | 可在高频路径使用 | 避免在极端性能敏感场景滥用 |
6.3 使用 Gauge 监控实时值
| 方法 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 创建 Gauge | Gauge.builder(name, obj, function).register(registry) | 创建监控指定对象属性的 Gauge | java\nList<String> queue = new LinkedList<>();\nGauge.builder("queue.size", queue, List::size)\n .register(registry); | 函数应快速返回,避免阻塞 |
| 直接设置值 | Gauge.builder(name).register(registry, obj, function) | 通过对象和提取函数创建 | java\nGauge.builder("cpu.usage", osBean, bean -> bean.getSystemCpuLoad())\n .register(registry); | 适用于监控第三方库对象 |
| 静态值 Gauge | Gauge.builder(name).register(registry, valueRef) | 监控固定值或需手动更新的值 | java\nAtomicDouble value = new AtomicDouble(0);\nGauge.builder("custom.value", value, AtomicDouble::get)\n .register(registry); | 使用原子类保证线程安全 |
| 回调式 Gauge | 每次采集时执行回调 | 定期获取最新值 | 无(由 MeterRegistry 调用) | 采集频率由监控系统决定(如 Prometheus scrape interval) |
| 使用场景 | 状态监控 | 队列长度、缓存大小、连接数等 | 避免用于高频变化的瞬时值 | 采集间隔内变化可能丢失 |
| 注意事项 | 非线程安全 | 回调函数需保证线程安全 | 使用同步容器或原子类 | 防止并发访问导致异常 |
6.4 使用 Timer 记录执行时间
| 方法 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 创建 Timer | Timer.builder(name).register(registry) | 构建并注册一个计时器 | java\nTimer timer = Timer.builder("method.duration")\n .tag("method", "process")\n .description("Time spent in processing")\n .register(registry); | 建议缓存实例 |
| 记录耗时 | timer.record(Duration) | 手动记录一段耗时 | timer.record(Duration.ofMillis(100)); | 适用于已知耗时的场景 |
| 自动计时(代码块) | timer.record(() -> {...}) | 自动记录代码块执行时间 | java\ntimer.record(() -> {\n // 业务逻辑\n process();\n}); | 最常用的方式,自动处理开始/结束 |
| 手动开始/结束 | Timer.Sample | 手动控制计时开始和结束 | java\nTimer.Sample sample = Timer.start(registry);\n// ...\nsample.stop(timer); | 适用于跨方法或异步场景 |
| 获取统计值 | timer.takeSnapshot() | 获取当前统计快照 | java\nSnapshot snap = timer.takeSnapshot();\ndouble mean = snap.mean(TimeUnit.MILLISECONDS); | 用于内部监控或告警 |
| 百分位支持 | 需配置 | 启用百分位统计(如 p95, p99) | management.metrics.distribution.percentiles.<name>=0.95,0.99 | 默认关闭,开启有性能开销 |
6.5 使用 DistributionSummary 记录分布统计
| 方法 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 创建 Summary | DistributionSummary.builder(name).register(registry) | 构建分布摘要 | java\nDistributionSummary summary = DistributionSummary.builder("request.size")\n .baseUnit("bytes")\n .register(registry); | 适用于记录非时间类数值分布 |
| 记录值 | summary.record(double value) | 记录一个数值 | summary.record(1024); // 1KB 请求体 | 可记录任意浮点数值 |
| 统计功能 | 自动计算 | 提供计数、总量、平均值、百分位等 | 无需额外代码 | 类似 Timer,但维度是数值而非时间 |
| 适用场景 | 数据大小分布 | 请求/响应大小、消息长度、文件尺寸等 | 不适用于执行时间 | 执行时间应使用 Timer |
| 百分位配置 | management.metrics.distribution.percentiles | 配置需要计算的百分位 | management.metrics.distribution.percentiles.all=0.9,0.95,0.99 | all 表示全局配置 |
| 性能权衡 | 滑动窗口 | 使用滑动窗口计算百分位 | 内部实现 | 高频记录时需评估性能影响 |
6.6 将指标导出到 Prometheus
| 配置/方法 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 添加依赖 | micrometer-registry-prometheus | 启用 Prometheus 导出 | xml\n<dependency>\n <groupId>io.micrometer</groupId>\n <artifactId>micrometer-registry-prometheus</artifactId>\n</dependency> | 必须添加,否则 /prometheus 端点 404 |
| 暴露端点 | management.endpoints.web.exposure.include | 通过 HTTP 暴露 | yaml\nmanagement:\n endpoints:\n web:\n exposure:\n include: prometheus | 确保 prometheus 在 include 列表中 |
| 访问指标 | GET /actuator/prometheus | 获取文本格式指标 | curl http://localhost:8080/actuator/prometheus | 响应 Content-Type 为 text/plain; version=0.0.4 |
| 全局标签 | management.metrics.tags | 添加全局标签 | yaml\nmanagement:\n metrics:\n tags:\n application: ${spring.application.name}\n region: us-east-1 | 所有指标自动附加这些标签 |
| 指标前缀 | management.metrics.export.prometheus.desired-metric-names | 过滤导出的指标 | 一般无需配置 | 用于性能优化或数据隔离 |
| Prometheus 配置 | scrape_configs | 在 Prometheus 中配置抓取 | yaml\n- job_name: 'spring-boot-app'\n metrics_path: '/actuator/prometheus'\n static_configs:\n - targets: ['localhost:8080'] | 确保网络可达 |
| 安全访问 | Spring Security | 保护 /actuator/prometheus | 配置 HTTP Basic 或 OAuth2 | 建议限制访问 IP 或使用认证 |
第7章:高级特性与扩展
7.1 远程调试与 @Endpoint 的 JMX 暴露
| 配置/方法 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 启用 JMX 支持 | spring.jmx.enabled=true | 启用 Spring 的 JMX 支持 | yaml\nspring:\n jmx:\n enabled: true | 默认为 true,通常无需配置 |
| 自定义 JMX 域名 | management.endpoint.jmx.domain | 设置 Actuator 端点的 JMX 域 | yaml\nmanagement:\n endpoint:\n jmx:\n domain: com.example.actuator | 避免命名冲突,便于管理 |
| 暴露端点到 JMX | management.endpoints.jmx.exposure.include | 指定暴露到 JMX 的端点 | yaml\nmanagement:\n endpoints:\n jmx:\n exposure:\n include: "*" | 默认暴露所有启用的端点 |
| 查看 MBean | JConsole 或 VisualVM | 连接 JVM 查看 MBean | 启动 JConsole → 选择本地进程 | 可查看 org.springframework.boot 域下的端点 |
| 自定义端点 JMX 支持 | @Endpoint + JMX | 自动注册为 MBean | java\n@Endpoint(id = "custom")\npublic class CustomEndpoint { ... } | 无需额外注解,框架自动处理 |
| 远程 JMX 连接 | 配置 JVM 参数 | 允许远程连接 JMX | \n-Dcom.sun.management.jmxremote\n-Dcom.sun.management.jmxremote.port=9999\n-Dcom.sun.management.jmxremote.authenticate=false | 生产环境必须启用认证和加密 |
7.2 使用 HealthIndicator 自定义健康检查
| 方法/配置 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
实现 HealthIndicator 接口 | 继承接口并重写 health() 方法 | 创建自定义健康检查逻辑 | java\n@Component\npublic class DatabaseHealthIndicator implements HealthIndicator {\n @Override\n public Health health() {\n if (isDatabaseUp()) {\n return Health.up().withDetail("version", "12.4").build();\n } else {\n return Health.down().withDetail("error", "Connection failed").build();\n }\n }\n} | Bean 名称应以 HealthIndicator 结尾 |
| 返回 UP 状态 | Health.up() | 表示组件健康 | return Health.up().build(); | 可附加详细信息 |
| 返回 DOWN 状态 | Health.down() | 表示组件故障 | return Health.down().withException(e).build(); | 有助于快速定位问题 |
| 添加详细信息 | withDetail(key, value) | 提供健康检查的上下文 | .withDetail("latency", 200) | 支持任意对象作为值 |
| 抛出异常 | withException(e) | 记录导致故障的异常 | .withException(new RuntimeException("Timeout")) | 异常信息会被掩码处理 |
| 异步健康检查 | CompletableFuture | 避免阻塞 | return CompletableFuture.supplyAsync(this::checkAsync); | 适用于耗时检查(如远程服务调用) |
7.3 使用 InfoContributor 扩展 info 信息
| 方法/配置 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
实现 InfoContributor 接口 | 重写 contribute() 方法 | 动态添加 /info 端点信息 | java\n@Component\npublic class BuildInfoContributor implements InfoContributor {\n @Override\n public void contribute(Info.Builder builder) {\n builder.withDetail("build", Map.of(\n "time", Instant.now(),\n "version", "1.0.0"\n ));\n }\n} | 框架自动发现并调用 |
| 添加静态信息 | builder.withDetail(key, value) | 添加键值对信息 | builder.withDetail("app.name", "MyApp"); | value 可为任意对象,自动序列化 |
| 添加嵌套结构 | Map 或 POJO | 构建层次化信息 | builder.withDetail("git", gitInfo); | 生成 JSON 嵌套对象 |
| 覆盖默认信息 | 同名 key | 后注册的 Contributor 可覆盖前者的值 | 无 | 注意加载顺序 |
| 运行时信息 | 获取系统状态 | 添加动态数据(如磁盘使用率) | builder.withDetail("disk.free", FileStore.getUsableSpace()); | 信息在每次请求时重新计算 |
| 多 Contributor 协作 | 多个 Bean | 多个组件共同构建 info 响应 | 无需特殊配置 | 所有 InfoContributor 都会被调用 |
7.4 端点响应的数据结构与序列化控制
| 特性/配置 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 默认序列化 | Jackson | 使用 ObjectMapper 序列化响应 | 无 | 自动处理 POJO、Map、集合等 |
| 自定义 ObjectMapper | @Bean ObjectMapper | 覆盖默认序列化行为 | java\n@Bean\npublic ObjectMapper objectMapper() {\n ObjectMapper mapper = new ObjectMapper();\n mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);\n return mapper;\n} | 影响整个应用的 JSON 序列化 |
| HAL 格式导航 | management.endpoint.jackson.serialization-inclusion=always | 启用 HAL 风格链接 | yaml\nmanagement:\n endpoint:\n jackson:\n serialization-inclusion: always | /actuator 响应包含 _links 字段 |
| 日期格式控制 | Jackson 配置 | 统一日期输出格式 | java\nmapper.findAndRegisterModules();\nmapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); | 推荐使用 ISO 8601 格式 |
| 敏感字段掩码 | 自动机制 | 掩码包含 password、secret 的字段 | info.password=secret → "******" | 基于字段名关键字匹配 |
| 自定义序列化器 | JsonSerializer | 为特定类型定制序列化逻辑 | public class CustomSerializer extends JsonSerializer<T> { ... } | 需注册到 ObjectMapper |
| 响应包装 | 自定义响应结构 | 统一错误或成功格式 | public class ApiResponse<T> { ... } | 不推荐修改 Actuator 内部结构 |
7.5 监控数据可视化(集成 Grafana)
| 集成方式 | 配置/工具 | 用途 | 示例配置/说明 | 注意事项 |
|---|
| Prometheus + Grafana | 标准组合 | 指标收集与可视化 | Prometheus 抓取 /actuator/prometheus → Grafana 展示 | 最主流的 Java 应用监控方案 |
| 导入 Grafana 仪表板 | Dashboard ID | 快速部署可视化面板 | Grafana 官方提供 Spring Boot 仪表板(ID: 12345) | 可自定义或导入现有模板 |
| 配置数据源 | Grafana Web UI | 添加 Prometheus 为数据源 | URL: http://prometheus-server:9090 | 确保网络可达 |
| 常用指标展示 | Grafana Panel | 展示关键性能指标 | - JVM 内存使用率 - HTTP 请求延迟 P95 - 线程数 - Tomcat 请求吞吐量 | 设置合理告警阈值 |
| 多实例监控 | job + instance 标签 | 区分不同服务实例 | 在 Prometheus 中通过 job 和 instance 标签筛选 | 适用于微服务集群 |
| 告警规则 | Prometheus Alerting | 设置指标告警 | 当 up{job="spring-app"} == 0 时触发 | 告警可集成到 Slack、钉钉等 |
第8章:生产实践与故障排查
8.1 常见端点响应分析(健康检查失败、线程阻塞等)
| 问题现象 | 可能原因 | 排查方法 | 解决方案 | 注意事项 |
|---|
/health 返回 DOWN | 数据库连接失败、Redis 不可用、磁盘满 | 查看 details 中具体组件状态 | 检查数据库服务、网络、凭证 | 配置 show-details: when-authorized 避免信息泄露 |
| 线程状态 BLOCKED | 锁竞争、死锁、同步方法阻塞 | GET /actuator/threads → 查看 blockedCount 和栈轨迹 | 优化同步代码、减少锁粒度 | 使用线程池避免阻塞主线程 |
| 堆内存持续增长 | 内存泄漏、缓存未清理、大对象未释放 | GET /actuator/metrics/jvm.memory.used → 观察趋势 | 生成 heapdump 分析 | 结合 /heapdump 下载文件用 MAT 分析 |
| HTTP 5xx 错误增多 | 业务异常、外部服务超时、资源不足 | GET /actuator/metrics/http.server.requests → 按 status 过滤 | 增加日志、优化异常处理 | 检查下游服务依赖 |
| 应用无响应 | 死锁、Full GC 频繁、CPU 100% | 结合 /threads、/metrics、系统监控 | 重启 + 事后分析 heapdump | 设置合理的 JVM 参数 |
| 端点 404 | 端点未暴露、路径配置错误 | 检查 management.endpoints.web.exposure.include | 正确配置暴露列表 | 确认依赖已添加(如 prometheus) |
8.2 利用 metrics 进行性能瓶颈定位
| 指标类别 | 关键指标 | 用途 | 分析方法 | 优化建议 |
|---|
| JVM 内存 | jvm.memory.used{area="heap"} | 监控堆内存使用 | 观察是否接近 max,Full GC 频率 | 调整 -Xmx,优化对象生命周期 |
| GC 时间 | jvm.gc.pause | GC 停顿时间 | 统计 P99 暂停时间是否过高 | 选择合适 GC 算法(如 G1) |
| HTTP 延迟 | http.server.requests{uri="/api/xxx"} | 接口响应时间 | 查看 P95/P99 延迟分布 | 优化 SQL、添加缓存、异步处理 |
| 线程池 | tomcat.threads.busy, tomcat.threads.current | Tomcat 线程使用率 | busy 接近 current 时可能成为瓶颈 | 增加线程数或优化请求处理速度 |
| 数据库 | hikaricp.connections.active | 数据库连接占用 | active 接近 maxPoolSize 时需关注 | 优化慢查询,调整连接池大小 |
| 缓存命中率 | cache.gets.hit, cache.gets.miss | 缓存效率 | 计算命中率 = hit / (hit + miss) | 提高缓存策略合理性,预热数据 |
8.3 日志与监控联动排查问题
| 场景 | 监控线索 | 日志配合 | 联动方法 | 示例 |
|---|
| 接口超时 | http.server.requests 延迟突增 | 查找对应时间点的 DEBUG/ERROR 日志 | 关联 traceId 或请求路径 | 发现某 SQL 执行耗时 5s |
| 内存溢出 | jvm.memory.used 持续上升 | 查看 OOM 前的日志输出 | 分析 GC 日志和异常堆栈 | 发现大文件上传未流式处理 |
| 服务不可用 | /health DOWN | 查看启动日志和依赖服务日志 | 检查数据库、Redis 连接日志 | 凭证错误导致数据库连接失败 |
| 高 CPU 使用 | 系统监控 CPU 100% | 结合 /threads 查看栈轨迹 | 定位热点方法 | 发现无限循环或正则回溯 |
| 频繁重启 | 容器平台事件 + /metrics 重置 | 查看 shutdown 原因日志 | 分析退出码和信号 | 发现内存超限被 K8s kill |
| 功能异常 | 自定义指标异常 | 根据业务日志定位逻辑分支 | 使用 MDC 记录 requestId | 发现特定用户数据格式错误 |
8.4 Actuator 在微服务架构中的集中监控方案
| 方案组件 | 作用 | 配置要点 | 优势 | 注意事项 |
|---|
| Prometheus | 指标收集中心 | 配置 scrape_configs 抓取所有实例的 /actuator/prometheus | 强大的查询语言 PromQL,原生支持 | 需维护 Prometheus 高可用 |
| Grafana | 可视化平台 | 添加 Prometheus 为数据源,创建多实例仪表板 | 统一视图,支持告警 | 可设置按服务、环境分组 |
| Service Discovery | 自动发现服务实例 | 集成 Consul、Eureka 或 Kubernetes SD | 无需手动维护目标列表 | 确保服务注册健康 |
| Pushgateway | 桥接短生命周期任务 | 用于批处理、Job 类应用推送指标 | 补充 scrape 模型的不足 | 避免用于常规应用 |
| Spring Boot Admin | 专用管理平台 | Server 端聚合 Client 端(集成 Actuator) | 提供 UI,支持通知 | 需额外部署 Admin 服务 |
| ELK/EFK | 日志集中分析 | Filebeat 收集日志 → Logstash → Elasticsearch → Kibana | 统一日志查询,关联分析 | 配置 MDC 输出 traceId |
| 告警中心 | 统一告警 | Prometheus Alertmanager 或集成钉钉/企业微信 | 避免告警风暴,分级通知 | 设置合理的告警规则和静默期 |