Skip to content
清晨的一缕阳光
返回

Spring Boot Actuator 监控端点

前言

Spring Boot Actuator 提供了生产级的监控和管理功能。通过内置的端点,可以轻松实现健康检查、指标采集、应用管理等功能。

快速开始

1. 添加依赖

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

2. 基础配置

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
      base-path: /actuator
  endpoint:
    health:
      show-details: always
      show-components: always
  info:
    env:
      enabled: true

3. 应用信息

info:
  app:
    name: ${spring.application.name}
    description: 'Spring Boot 4 Demo Application'
    version: '@project.version@'
  java:
    version: ${java.version}
  os:
    name: ${os.name}
@Component
public class CustomInfoContributor implements InfoContributor {
    
    @Override
    public void contribute(Info.Builder builder) {
        builder.withDetail("build-time", getBuildTime());
        builder.withDetail("git-commit", getGitCommit());
    }
    
    private String getBuildTime() {
        // 从文件读取构建时间
        return "2024-01-01 12:00:00";
    }
    
    private String getGitCommit() {
        // 从 Git 获取提交信息
        return "abc123";
    }
}

内置端点

1. 健康检查端点

management:
  endpoint:
    health:
      show-details: always
      show-components: always
      probes:
        enabled: true
  health:
    db:
      enabled: true
    redis:
      enabled: true
    mail:
      enabled: false
# 访问健康检查
curl http://localhost:8080/actuator/health

# 响应
{
  "status": "UP",
  "components": {
    "db": {
      "status": "UP",
      "details": {
        "database": "MySQL",
        "validationQuery": "SELECT 1"
      }
    },
    "redis": {
      "status": "UP",
      "details": {
        "version": "7.0.0"
      }
    },
    "diskSpace": {
      "status": "UP",
      "details": {
        "total": 500000000000,
        "free": 100000000000,
        "threshold": 10485760
      }
    }
  }
}

2. 自定义健康检查

@Component
public class CustomHealthIndicator implements HealthIndicator {
    
    @Override
    public Health health() {
        // 检查外部服务
        boolean serviceAvailable = checkExternalService();
        
        if (serviceAvailable) {
            return Health.up()
                .withDetail("service", "external-api")
                .withDetail("response-time", "100ms")
                .build();
        } else {
            return Health.down()
                .withDetail("service", "external-api")
                .withDetail("error", "Connection timeout")
                .build();
        }
    }
    
    private boolean checkExternalService() {
        // 实现检查逻辑
        return true;
    }
}

3. 组合健康检查

@Component
public class DatabaseHealthIndicator implements HealthIndicator {
    
    @Autowired
    private DataSource dataSource;
    
    @Override
    public Health health() {
        try {
            Connection connection = dataSource.getConnection();
            connection.close();
            return Health.up()
                .withDetail("database", "connection-ok")
                .build();
        } catch (SQLException e) {
            return Health.down(e)
                .withDetail("database", "connection-failed")
                .build();
        }
    }
}

4. 指标端点

# 获取所有指标
curl http://localhost:8080/actuator/metrics

# 获取 JVM 内存指标
curl http://localhost:8080/actuator/metrics/jvm.memory.used

# 获取 HTTP 请求指标
curl http://localhost:8080/actuator/metrics/http.server.requests

# 带标签查询
curl http://localhost:8080/actuator/metrics/http.server.requests?tag=uri:/api/users

5. 信息端点

# 获取应用信息
curl http://localhost:8080/actuator/info

# 响应
{
  "app": {
    "name": "demo",
    "description": "Spring Boot 4 Demo Application",
    "version": "1.0.0"
  },
  "java": {
    "version": "21.0.1"
  },
  "os": {
    "name": "Linux"
  }
}

6. 环境端点

# 获取所有环境属性
curl http://localhost:8080/actuator/env

# 获取特定属性
curl http://localhost:8080/actuator/env/spring.datasource.url

7. 线程端点

# 获取线程信息
curl http://localhost:8080/actuator/threaddump

8. 日志端点

# 获取日志配置
curl http://localhost:8080/actuator/loggers

# 修改日志级别
curl -X POST http://localhost:8080/actuator/loggers/com.example.demo \
  -H 'Content-Type: application/json' \
  -d '{"configuredLevel":"DEBUG"}'

自定义端点

1. 创建端点

@Component
@Endpoint(id = "cache")
public class CacheEndpoint {
    
    private final CacheManager cacheManager;
    
    public CacheEndpoint(CacheManager cacheManager) {
        this.cacheManager = cacheManager;
    }
    
    @ReadOperation
    public Map<String, Object> caches() {
        Map<String, Object> result = new HashMap<>();
        cacheManager.getCacheNames().forEach(name -> {
            Cache cache = cacheManager.getCache(name);
            result.put(name, cache.getNativeCache());
        });
        return result;
    }
    
    @ReadOperation
    public Object cache(@Selector String name) {
        Cache cache = cacheManager.getCache(name);
        return cache != null ? cache.getNativeCache() : null;
    }
    
    @WriteOperation
    public void evict(@Selector String name) {
        Cache cache = cacheManager.getCache(name);
        if (cache != null) {
            cache.clear();
        }
    }
    
    @DeleteOperation
    public void evictKey(@Selector String name, @Selector String key) {
        Cache cache = cacheManager.getCache(name);
        if (cache != null) {
            cache.evict(key);
        }
    }
}

2. Web 端点扩展

@Component
@WebEndpoint(id = "config")
public class ConfigEndpoint {
    
    @Autowired
    private Environment environment;
    
    @ReadOperation
    public Map<String, Object> config() {
        Map<String, Object> result = new HashMap<>();
        result.put("activeProfiles", environment.getActiveProfiles());
        result.put("properties", getPropertySources());
        return result;
    }
    
    @WriteOperation
    public ResponseEntity<String> updateProperty(
        @Selector String key, 
        @RequestBody String value
    ) {
        // 动态更新配置
        System.setProperty(key, value);
        return ResponseEntity.ok("Property updated");
    }
}

3. 端点安全

@Component
@Endpoint(id = "sensitive")
public class SensitiveEndpoint {
    
    @ReadOperation
    @Secured("ROLE_ADMIN")
    public Map<String, Object> sensitiveData() {
        // 只有管理员可以访问
        Map<String, Object> data = new HashMap<>();
        data.put("secret", "sensitive-information");
        return data;
    }
}

Prometheus 集成

1. 添加依赖

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

2. 配置

management:
  endpoints:
    web:
      exposure:
        include: prometheus
  metrics:
    export:
      prometheus:
        enabled: true
    tags:
      application: ${spring.application.name}

3. 访问指标

curl http://localhost:8080/actuator/prometheus

# 响应
# HELP jvm_memory_used_bytes The amount of used memory
# TYPE jvm_memory_used_bytes gauge
jvm_memory_used_bytes{area="heap",id="G1 Survivor Space",} 1048576.0
jvm_memory_used_bytes{area="heap",id="G1 Eden Space",} 52428800.0

4. 自定义指标

@Component
public class CustomMetrics {
    
    private final MeterRegistry meterRegistry;
    
    public CustomMetrics(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
        
        // 注册计数器
        Counter.builder("custom_counter")
            .description("Custom counter description")
            .tag("type", "business")
            .register(meterRegistry);
        
        // 注册计时器
        Timer.builder("custom_timer")
            .description("Custom timer description")
            .register(meterRegistry);
        
        // 注册分布摘要
        DistributionSummary.builder("custom_summary")
            .description("Custom summary description")
            .baseUnit("bytes")
            .register(meterRegistry);
    }
    
    public void incrementCounter() {
        meterRegistry.counter("custom_counter").increment();
    }
    
    public <T> T time(Supplier<T> supplier) {
        Timer timer = meterRegistry.timer("custom_timer");
        return timer.record(supplier);
    }
}

5. 业务指标

@Service
@RequiredArgsConstructor
public class OrderService {
    
    private final MeterRegistry meterRegistry;
    
    public Order createOrder(OrderCreateDTO dto) {
        Timer.Sample sample = Timer.start(meterRegistry);
        
        try {
            Order order = orderRepository.save(convert(dto));
            
            // 记录成功指标
            meterRegistry.counter("order.created", 
                "status", "success",
                "type", dto.getType()
            ).increment();
            
            return order;
        } catch (Exception e) {
            // 记录失败指标
            meterRegistry.counter("order.created", 
                "status", "failed",
                "type", dto.getType(),
                "error", e.getClass().getSimpleName()
            ).increment();
            
            throw e;
        } finally {
            sample.stop(Timer.builder("order.create.time")
                .register(meterRegistry));
        }
    }
}

安全配置

1. 端点安全

@Configuration
@EnableWebSecurity
public class ActuatorSecurityConfig {
    
    @Bean
    public SecurityFilterChain actuatorSecurityFilterChain(
        HttpSecurity http
    ) throws Exception {
        http
            .securityMatcher(EndpointRequest.toAnyEndpoint())
            .authorizeHttpRequests(authorize -> authorize
                .requestMatchers(EndpointRequest.to("health", "info")).permitAll()
                .requestMatchers(EndpointRequest.to("prometheus")).hasRole("MONITOR")
                .anyRequest().hasRole("ADMIN")
            )
            .httpBasic(Customizer.withDefaults());
        
        return http.build();
    }
}

2. 管理端口

management:
  server:
    port: 9090  # 独立的管理端口
    address: 127.0.0.1  # 只允许本地访问

3. 路径匹配

management:
  endpoints:
    web:
      base-path: /manage
      path-mapping:
        health: healthz
        ready: readyz

最佳实践

1. 生产环境配置

management:
  endpoints:
    web:
      exposure:
        include: health,info,prometheus
      base-path: /actuator
  endpoint:
    health:
      show-details: never
      show-components: when-authorized
  server:
    port: 9090
    address: 127.0.0.1

2. Kubernetes 探针

management:
  health:
    livenessState:
      enabled: true
    readinessState:
      enabled: true
  endpoint:
    health:
      probes:
        enabled: true
# Kubernetes 配置
livenessProbe:
  httpGet:
    path: /actuator/health/liveness
    port: 8080
  initialDelaySeconds: 30
  periodSeconds: 10

readinessProbe:
  httpGet:
    path: /actuator/health/readiness
    port: 8080
  initialDelaySeconds: 10
  periodSeconds: 5

3. 告警配置

# Prometheus Alertmanager 配置
groups:
  - name: spring-boot
    rules:
      - alert: ServiceDown
        expr: up{job="demo"} == 0
        for: 1m
        annotations:
          summary: "Service {{ $labels.instance }} is down"
      
      - alert: HighMemoryUsage
        expr: jvm_memory_used_bytes / jvm_memory_max_bytes > 0.9
        for: 5m
        annotations:
          summary: "High memory usage on {{ $labels.instance }}"

总结

Actuator 监控要点:

Actuator 是 Spring Boot 生产监控的基础设施。


分享这篇文章到:

上一篇文章
MySQL JOIN 优化实战
下一篇文章
Docker Compose 部署