Spring Boot: Spring Boot Actuator

最后更新:2026-08-26

Actuator 是 Spring Boot 的仪表盘——健康状态、指标数据、配置信息,运维的"上帝视角"。

1. 你将学到


2. 一个运维工程师的真实故事

(1) 痛点:生产环境像黑盒

Bob 负责运维 OrderFlow 生产环境,但应用内部完全是个黑盒:数据库连接是否正常?内存用了多少?哪些接口响应慢?每次出问题都要找 Alice 加日志、重启应用才能排查,平均故障恢复时间(MTTR)超过 1 小时。Charlie 要求 MTTR 降到 10 分钟。

(2) Actuator 的解法

Actuator 开箱即用,提供丰富的运维端点:

YAML
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
BASH
curl http://localhost:8080/actuator/health
# {"status":"UP","components":{"db":{"status":"UP"},"diskSpace":{"status":"UP"}}}

(3) 收益

Bob 用 Actuator 后,/health 监控数据库连通性,/metrics 追踪接口响应时间,自定义 HealthIndicator 检测外部支付网关,MTTR 从 1 小时降到 5 分钟。


3. Actuator 端点概览

(1) 内置端点一览

端点 说明 默认暴露
/actuator/health 应用健康状态 ✅ 是
/actuator/info 应用信息 ✅ 是
/actuator/metrics 指标列表 ❌ 否
/actuator/metrics/{name} 具体指标值 ❌ 否
/actuator/env 环境配置 ❌ 否
/actuator/beans Bean 列表 ❌ 否
/actuator/loggers 日志级别 ❌ 否
/actuator/threaddump 线程转储 ❌ 否
/actuator/heapdump 堆转储 ❌ 否
/actuator/prometheus Prometheus 格式指标 ❌ 否

▶ 示例: 启用 Actuator 依赖

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

输出:

TEXT 📖 仅展示
// 执行成功

▶ 示例: 配置端点暴露

YAML
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,env,loggers
      base-path: /actuator
  endpoint:
    health:
      show-details: when-authorized
    metrics:
      enabled: true
  info:
    env:
      enabled: true

输出:

TEXT 📖 仅展示
配置文件已生效
暴露策略 配置值 说明
仅健康和信息 include: health,info 最安全,默认值
按需暴露 include: health,info,metrics 推荐
暴露所有 include: "*" 仅开发环境
排除特定 exclude: env,beans 从全部中排除

4. Health 端点详解

(1) 健康状态聚合规则

100%
graph TD
    A["Health Status<br/>Aggregator"] --> B["DiskSpace<br/>UP"]
    A --> C["DataSource<br/>UP"]
    A --> D["PaymentGateway<br/>DOWN"]
    A --> E["Redis<br/>UP"]
    D --> F["Overall: DOWN<br/>Any DOWN → DOWN"]
状态 含义 聚合规则
UP 正常
DOWN 异常 任意一个 DOWN → 整体 DOWN
DEGRADED 降级 非关键组件降级
OUT_OF_SERVICE 不提供服务 任意一个 → 整体 OUT_OF_SERVICE
UNKNOWN 未知 默认状态

▶ 示例: 自定义 HealthIndicator

JAVA
@Component
public class PaymentGatewayHealthIndicator implements HealthIndicator {

    private final RestTemplate restTemplate;

    public PaymentGatewayHealthIndicator(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @Override
    public Health health() {
        try {
            ResponseEntity<String> response = restTemplate.getForEntity(
                "https://api.payment-gateway.com/ping", String.class);
            if (response.getStatusCode().is2xxSuccessful()) {
                return Health.up()
                    .withDetail("gateway", "reachable")
                    .withDetail("responseTime", response.getHeaders().getDate())
                    .build();
            }
            return Health.down()
                .withDetail("gateway", "unhealthy")
                .withDetail("statusCode", response.getStatusCode())
                .build();
        } catch (Exception e) {
            return Health.down()
                .withDetail("gateway", "unreachable")
                .withDetail("error", e.getMessage())
                .build();
        }
    }
}

输出:

TEXT 📖 仅展示
// 执行成功
💻 输出:

JSON
{
  "status": "DOWN",
  "components": {
    "diskSpace": {"status": "UP", "details": {"total": 536870912000, "free": 268435456000}},
    "db": {"status": "UP", "details": {"database": "MySQL", "validationQuery": "SELECT 1"}},
    "paymentGateway": {"status": "DOWN", "details": {"gateway": "unreachable", "error": "Connection refused"}}
  }
}

5. Metrics 端点详解

▶ 示例: 查看 HTTP 请求指标

BASH
# List all available metrics
curl http://localhost:8080/actuator/metrics

# Get specific metric: HTTP server requests
curl http://localhost:8080/actuator/metrics/http.server.requests

# Get filtered metric
curl "http://localhost:8080/actuator/metrics/http.server.requests?tag=uri:/api/v1/orders&tag=status:200"

输出:

TEXT 📖 仅展示
{"status":"ok","data":{}}
常用指标 说明
http.server.requests HTTP 请求耗时分布
jvm.memory.used JVM 内存使用
jvm.threads.live 活跃线程数
process.cpu.usage 进程 CPU 使用率
disk.total / disk.free 磁盘空间
hikaricp.connections.active 数据库连接池

▶ 示例: 自定义业务指标

JAVA
@Service
public class OrderMetrics {

    private final Counter orderCreatedCounter;
    private final Timer orderCreationTimer;
    private final AtomicLong pendingOrders;

    public OrderMetrics(MeterRegistry registry) {
        this.orderCreatedCounter = Counter.builder("orderflow.orders.created")
            .description("Total orders created")
            .tag("service", "orderflow")
            .register(registry);

        this.orderCreationTimer = Timer.builder("orderflow.orders.creation.time")
            .description("Order creation time")
            .register(registry);

        this.pendingOrders = registry.gauge("orderflow.orders.pending",
            new AtomicLong(0));
    }

    public void recordOrderCreated() {
        orderCreatedCounter.increment();
        pendingOrders.incrementAndGet();
    }

    public void recordOrderCompleted() {
        pendingOrders.decrementAndGet();
    }

    public Timer getCreationTimer() {
        return orderCreationTimer;
    }
}

输出:

TEXT 📖 仅展示
// 执行成功

6. 自定义端点

▶ 示例: 自定义 OrderStats 端点

JAVA
@Endpoint(id = "orderstats")
@Component
public class OrderStatsEndpoint {

    private final OrderRepository orderRepository;

    public OrderStatsEndpoint(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }

    @ReadOperation
    public Map<String, Object> orderStats() {
        long total = orderRepository.count();
        long pending = orderRepository.countByStatus("PENDING");
        long completed = orderRepository.countByStatus("COMPLETED");
        long cancelled = orderRepository.countByStatus("CANCELLED");
        return Map.of(
            "totalOrders", total,
            "pendingOrders", pending,
            "completedOrders", completed,
            "cancelledOrders", cancelled,
            "completionRate", total > 0
                ? String.format("%.2f%%", (double) completed / total * 100)
                : "N/A"
        );
    }

    @ReadOperation
    public Map<String, Object> orderStatsByStatus(
            @Selector String status) {
        long count = orderRepository.countByStatus(status.toUpperCase());
        return Map.of("status", status, "count", count);
    }
}

输出:

TEXT 📖 仅展示
// 执行成功
YAML
management:
  endpoint:
    orderstats:
      enabled: true
  endpoints:
    web:
      exposure:
        include: health,info,orderstats
💻 输出:

BASH
curl http://localhost:8080/actuator/orderstats
# {"totalOrders":1523,"pendingOrders":45,"completedOrders":1420,"cancelledOrders":58,"completionRate":"93.30%"}

curl http://localhost:8080/actuator/orderstats/PENDING
# {"status":"PENDING","count":45}

7. 安全加固

(1) 端点安全策略

层级 策略 说明
网络层 独立管理端口 management.server.port=8081
网络层 绑定内网 IP management.server.address=127.0.0.1
应用层 Spring Security 控制 .requestMatchers("/actuator/**").hasRole("ADMIN")
端点层 禁用敏感端点 management.endpoint.env.enabled=false

▶ 示例: 生产级安全配置

YAML
# application-prod.yml
management:
  server:
    port: 8081                    # Separate management port
    address: 127.0.0.1            # Bind to localhost only
  endpoints:
    web:
      exposure:
        include: health,prometheus,orderstats
      base-path: /actuator
  endpoint:
    health:
      show-details: when-authorized
    env:
      enabled: false
    beans:
      enabled: false
    heapdump:
      enabled: false

输出:

TEXT 📖 仅展示
Monitoring config loaded
Prometheus targets: 3 active
Grafana dashboard: ready
环境 暴露策略 管理端口
开发 include: "*" 同端口 8080
测试 include: health,info,metrics,env 同端口 8080
生产 include: health,prometheus 独立端口 8081 + 内网

8. 综合示例:OrderFlow Actuator 完整配置

YAML
# application.yml
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus,orderstats
  endpoint:
    health:
      show-details: when-authorized
    orderstats:
      enabled: true
  metrics:
    tags:
      application: ${spring.application.name}
  info:
    env:
      enabled: true

info:
  app:
    name: OrderFlow Service
    version: @project.version@
    description: E-commerce order management microservice
JAVA
// PaymentGatewayHealthIndicator.java
@Component
public class PaymentGatewayHealthIndicator implements HealthIndicator {
    private final RestTemplate restTemplate;
    public PaymentGatewayHealthIndicator(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }
    @Override
    public Health health() {
        try {
            ResponseEntity<String> resp = restTemplate
                .getForEntity("https://api.payment.com/ping", String.class);
            return resp.getStatusCode().is2xxSuccessful()
                ? Health.up().withDetail("gateway", "reachable").build()
                : Health.down().withDetail("statusCode", resp.getStatusCode()).build();
        } catch (Exception e) {
            return Health.down().withDetail("error", e.getMessage()).build();
        }
    }
}

// OrderStatsEndpoint.java
@Endpoint(id = "orderstats")
@Component
public class OrderStatsEndpoint {
    private final OrderRepository orderRepository;
    public OrderStatsEndpoint(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }
    @ReadOperation
    public Map<String, Object> stats() {
        return Map.of(
            "total", orderRepository.count(),
            "pending", orderRepository.countByStatus("PENDING"),
            "completed", orderRepository.countByStatus("COMPLETED")
        );
    }
}

❓ 常见问题

Q Actuator 端点会影响性能吗?
A 读操作(health、metrics)开销极小。heapdump 和 threaddump 会暂停应用,生产环境默认禁用。Prometheus 端点的抓取间隔建议 15-30 秒。
Q 健康检查端点应该给谁用?
A /health 给负载均衡器和 K8s 探针用,不暴露敏感详情。/health with details 给运维用,需要 ADMIN 权限。生产环境用 show-details: when-authorized
Q 如何自定义健康状态聚合规则?
A 实现 HealthAggregator 或用 StatusAggregator Bean。默认规则是:任意 DOWN → 整体 DOWN。可以通过 statusOrder 自定义优先级。
Q /actuator/env 会暴露密码吗?
A 会显示配置值,但 Spring Boot 3.x 默认对包含 passwordsecretkeytoken 的键值进行脱敏(显示 ••••••)。仍建议生产环境禁用此端点。
Q 管理端口和应用端口分离有什么好处?
A 1)管理端点只绑定内网,不暴露公网;2)应用流量和管理流量隔离,互不影响;3)可以对管理端口设置不同的安全策略。
Q 如何把 Actuator 指标对接 Prometheus?
A 添加 micrometer-registry-prometheus 依赖,暴露 prometheus 端点,在 Prometheus 配置中添加抓取目标。后续课程(L23)会详细讲解。

📖 小节


📝 作业

  1. 基础题(难度⭐):为 OrderFlow 添加 Actuator,配置暴露 health、info、metrics 端点,验证 /actuator/health 返回 UP 状态。

  2. 进阶题(难度⭐⭐):实现自定义 PaymentGatewayHealthIndicator 和 OrderStatsEndpoint,配置生产环境独立管理端口。

  3. 挑战题(难度⭐⭐⭐):添加 micrometer-registry-prometheus 依赖,暴露 /actuator/prometheus 端点,编写自定义业务指标(订单创建计数、下单耗时),思考指标命名规范和标签设计。

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏