Spring Boot Actuator 监控端点

字节跳动P6面试间,面试官翻到简历上"有生产环境运维经验"这一行,问:

"你们生产环境的 Spring Boot 应用,怎么做监控的?"

候选人小钱说:"用 Prometheus 采集指标,Grafana 做可视化。"面试官追问:"Spring Boot 端点怎么暴露的?"小钱说:"引入 actuator 依赖,然后配置一下。"

面试官追问:"/actuator/health 和 /actuator/health/liveness 有什么区别?"小钱愣住了。面试官又问:"怎么防止 actuator 端点被未授权访问?"小钱答不上来。

【面试官心理】

这道题我用来测试候选人的生产运维意识。能说出常用端点名称的占 60%,能说出健康检查配置的占 30%,能讲清楚安全防护和外部集成的只有 10%。现在面试越来越注重生产经验,只会说"引入依赖配一下"的人很容易露馅。

一、Actuator 核心端点 🔴

1.1 必须掌握的端点

Spring Boot Actuator 提供了大量内置端点,以下是面试中最常被问到的:

端点路径作用面试重要性
health/actuator/health健康检查必考
info/actuator/info应用信息了解
beans/actuator/beans容器中所有 Bean高频
conditions/actuator/conditions自动配置条件报告高频
env/actuator/env环境变量高频
configprops/actuator/configprops配置属性了解
metrics/actuator/metrics指标数据高频
loggers/actuator/loggers日志级别管理高频
heapdump/actuator/heapdump堆内存 dump生产必知
threaddump/actuator/threaddump线程 dump生产必知
mappings/actuator/mappingsURL 路径映射了解
scheduledtasks/actuator/scheduledtasks定时任务了解

1.2 引入依赖

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

Actuator 默认只暴露 healthinfo 两个端点。其他端点需要显式配置暴露:

management:
  endpoints:
    web:
      exposure:
        include: health,info,beans,conditions,env,metrics,loggers
        exclude: heapdump,threaddump  # 排除敏感端点
      base-path: /actuator  # 端点前缀,默认是 /actuator

二、health 端点深度解析 🟡

2.1 health 端点的细节层级

Spring Boot 2.3+ 对 health 端点做了重大拆分:

# application.yml
management:
  endpoint:
    health:
      show-details: always  # always | when-authorized | never
      probes:
        enabled: true  # 启用存活探针和就绪探针

拆分后的健康检查

  • /actuator/health/liveness:存活探针(Kubernetes liveness probe)
    • 如果返回 DOWN,说明应用处于死锁状态,需要重启
  • /actuator/health/readiness:就绪探针(Kubernetes readiness probe)
    • 如果返回 DOWN,说明应用还没准备好接收流量(比如数据库连接失败)
  • /actuator/health:聚合健康状态
// GET /actuator/health
{
    "status": "UP",
    "components": {
        "db": {
            "status": "UP",
            "details": {
                "database": "MySQL",
                "validationQuery": "isValid()"
            }
        },
        "redis": {
            "status": "DOWN",
            "details": {
                "error": "redis.clients.jedis.exceptions.JedisConnectionException"
            }
        },
        "diskSpace": {
            "status": "UP"
        }
    }
}
⚠️

show-details 默认是 when-authorized,意味着只有认证用户才能看到详细信息。在开发/测试环境建议设为 always,生产环境保持 when-authorized 或者 never

2.2 自定义健康检查

@Component
public class CustomHealthIndicator implements HealthIndicator {
    @Override
    public Health health() {
        try {
            // 检查自定义业务逻辑
            boolean healthy = checkBusinessHealth();
            if (healthy) {
                return Health.up()
                    .withDetail("responseTime", 100)
                    .withDetail("activeConnections", 5)
                    .build();
            } else {
                return Health.down()
                    .withDetail("error", "Service unavailable")
                    .build();
            }
        } catch (Exception e) {
            return Health.down()
                .withDetail("error", e.getMessage())
                .build();
        }
    }
}

三、@Endpoint 注解体系 🟡

3.1 自定义端点

Spring Boot 允许自定义 Actuator 端点:

@Endpoint(id = "custom")
public class CustomEndpoint {

    @ReadOperation
    public Map<String, Object> getCustomInfo() {
        Map<String, Object> info = new HashMap<>();
        info.put("customData", "some value");
        info.put("timestamp", System.currentTimeMillis());
        return info;
    }

    @WriteOperation
    public String triggerAction(@Selector String action) {
        return "Triggered: " + action;
    }

    @DeleteOperation
    public String clearCache(@Selector String cacheName) {
        return "Cleared: " + cacheName;
    }
}
management:
  endpoints:
    web:
      exposure:
        include: custom
  endpoint:
    custom:
      enabled: true
注解HTTP 方法作用
@ReadOperationGET查询数据
@WriteOperationPOST执行操作
@DeleteOperationDELETE删除资源
💡

自定义端点时,默认情况下所有操作都不需要认证。如果你的端点涉及敏感操作,需要配合 Spring Security 进行权限控制。

四、安全防护 🟡

4.1 禁止未授权访问

Actuator 端点如果暴露到公网,可能造成严重的信息泄露。以下是必须做的安全配置:

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics
        exclude: env,beans,conditions,configprops,heapdump,threaddump
  endpoint:
    health:
      show-details: when-authorized  # 只给授权用户看详情

spring:
  security:
    endpoints:
      web:
        exposure:
          include: health
    authorization:
      endpoints:
        health:
          access:
            - hasRole('ADMIN')  # 只有 ADMIN 角色能访问健康详情
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                // actuator 端点需要认证
                .requestMatchers("/actuator/**").authenticated()
                .anyRequest().permitAll()
            )
            .httpBasic();  // 使用 HTTP Basic 认证
        return http.build();
    }
}
⚠️

生产环境绝对不能把 heapdump、threaddump、env 这些端点直接暴露出去。heapdump 可以下载完整的堆内存快照,里面包含所有对象和字符串(可能包含密码、Token 等敏感信息),threaddump 可以看到方法调用栈(可能泄露业务逻辑)。

五、与 Prometheus/Grafana 集成 🟢

5.1 暴露 Prometheus 端点

<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
management:
  endpoints:
    web:
      exposure:
        include: health,prometheus,metrics
  metrics:
    tags:
      application: ${spring.application.name}
# GET /actuator/prometheus
# TYPE jvm_memory_used_bytes gauge
jvm_memory_used_bytes{area="heap",id="Eden Space",application="my-app"} 1.23E8

5.2 Grafana Dashboard 配置

{
  "dashboard": {
    "panels": [
      {
        "title": "JVM Memory",
        "type": "graph",
        "targets": [
          {
            "expr": "jvm_memory_used_bytes{application=\"my-app\", area=\"heap\"}",
            "legendFormat": "{{id}}"
          }
        ]
      },
      {
        "title": "HTTP Requests",
        "type": "graph",
        "targets": [
          {
            "expr": "http_server_requests_seconds_count{application=\"my-app\"}",
            "legendFormat": "{{uri}} - {{status}}"
          }
        ]
      }
    ]
  }
}

六、常用排查端点 🟢

6.1 beans 端点

# 查看所有 Bean,包括 Bean 的依赖关系
GET /actuator/beans
{
    "contexts": {
        "application": {
            "beans": {
                "dataSource": {
                    "aliases": [],
                    "scope": "singleton",
                    "type": "com.zaxxer.hikari.HikariDataSource",
                    "resource": "class path resource [application.yml]",
                    "dependencies": ["dataSourceInitializer"]
                }
            }
        }
    }
}

6.2 env 端点

# 查看所有配置属性,包括从环境变量注入的值
GET /actuator/env
GET /actuator/env/spring.datasource.password  # 查看特定属性
POST /actuator/env  # 修改运行时属性
{
    "name": "server.tomcat.connection-timeout",
    "value": 5000
}

6.3 loggers 端点

# 查看和修改日志级别(运行时生效)
GET /actuator/loggers
POST /actuator/loggers/com.example.service
{
    "configuredLevel": "DEBUG"
}

七、面试标准回答

7.1 P5 级别

"Spring Boot Actuator 提供了很多监控端点,比如 /actuator/health 做健康检查、/actuator/metrics 查看指标、/actuator/beans 查看 Bean 列表。使用时引入 spring-boot-starter-actuator 依赖,然后通过 management.endpoints.web.exposure.include 配置暴露哪些端点。"

7.2 P6 级别

"Actuator 默认只暴露 health 和 info,其他端点需要配置暴露。health 端点在 Spring Boot 2.3+ 拆分为 liveness 和 readiness 两个探针,分别用于 Kubernetes 的存活检测和就绪检测。

自定义端点使用 @Endpoint 注解,配合 @ReadOperation/@WriteOperation/@DeleteOperation 定义操作。安全方面,heapdump、threaddump、env 等敏感端点必须在生产环境禁止暴露或加上认证。show-details 默认是 when-authorized,只有认证用户才能看详情。"

7.3 P7 级别

"Actuator 是 Spring Boot 生产运维的核心。我之前在项目中把 Actuator 和 Prometheus 做了深度集成——通过 micrometer-registry-prometheus 暴露 /actuator/prometheus 端点,Grafana 配置了 JVM 监控、Datasource 连接池监控、自定义业务指标监控。

踩过一个坑:最开始我们把所有端点都暴露了,结果压测时被攻击者扫描到了 /actuator/heapdump 端点,直接 dump 了生产环境的堆内存快照。后来我们做了三层防护:1. 禁止暴露敏感端点;2. actuator 端点加 HTTP Basic 认证;3. 在网关层做了 IP 白名单。"

【面试官心理】

P7 的回答重点在于"生产踩坑"和"系统建设"。能说出安全防护细节和监控集成的候选人,说明他真正在生产环境用过这些工具,而不只是看过文档。