Spring Boot Actuator 定制端点详解

🎯 Spring Boot Actuator 定制端点详解

除了使用内置的 Actuator 端点外,Spring Boot 还提供了强大的扩展机制,允许我们自定义监控信息,以满足业务需求。本文将详细介绍如何定制 /info、健康检查、度量指标,以及创建完全自定义的端点。


1. 定制 /actuator/info 端点

/info 端点用于展示应用的元信息,如版本、构建时间、作者等。你可以通过以下两种方式扩展它。

✅ 方式一:通过 application.ymlapplication.properties

# application.yml
info:
  app:
    name: MyApp
    version: 1.2.0
    description: A powerful Spring Boot application
    contact:
      email: admin@myapp.com
      phone: +86-123-4567-8901
  build:
    artifact: @project.artifactId@
    name: @project.name@
    version: @project.version@
    time: @build.time@

⚠️ 注意:@xxx@ 占位符需要启用资源过滤(Maven/Gradle)。

Maven 资源过滤配置:
<build>
  <resources>
    <resource>
      <directory>src/main/resources</directory>
      <filtering>true</filtering>
    </resource>
  </resources>
</build>

并在 pom.xml 中添加构建时间:

<properties>
  <build.time>${maven.build.timestamp}</build.time>
  <maven.build.timestamp.format>yyyy-MM-dd HH:mm:ss</maven.build.timestamp.format>
</properties>

✅ 方式二:实现 InfoContributor 接口(动态信息)

适用于需要运行时动态生成的信息,如 Git 提交、数据库版本、服务依赖状态等。

@Component
public class CustomInfoContributor implements InfoContributor {

    @Override
    public void contribute(Info.Builder builder) {
        builder
            .withDetail("runtime", System.currentTimeMillis())
            .withDetail("java.version", System.getProperty("java.version"))
            .withDetail("active.profile", 
                Arrays.toString(environment.getActiveProfiles()))
            .withDetail("git.commit", getGitCommit());
    }

    private String getGitCommit() {
        // 可集成 git-commit-id-plugin 获取 Git 信息
        return "abc1234";
    }

    @Autowired
    private Environment environment;
}

💡 提示:使用 git-commit-id-plugin 插件可自动注入 Git 信息。

访问 /actuator/info 将看到你添加的动态信息。


2. 自定义健康检查(Health Indicator)

当你的应用依赖第三方服务(如 Kafka、第三方 API、文件系统、内部微服务),你可以实现 HealthIndicator 来监控其状态。

✅ 实现 HealthIndicator 接口

@Component
public class ThirdPartyApiHealthIndicator implements HealthIndicator {

    private final RestTemplate restTemplate = new RestTemplate();

    @Value("${thirdparty.api.url}")
    private String apiUrl;

    @Override
    public Health health() {
        try {
            ResponseEntity<String> response = restTemplate.getForEntity(apiUrl, String.class);
            if (response.getStatusCode().is2xxSuccessful()) {
                return Health.up()
                    .withDetail("status", "OK")
                    .withDetail("responseTime", System.currentTimeMillis())
                    .build();
            } else {
                return Health.outOfService()
                    .withDetail("status", "DOWN")
                    .withDetail("statusCode", response.getStatusCodeValue())
                    .build();
            }
        } catch (Exception e) {
            return Health.down(e)
                .withDetail("error", e.getMessage())
                .build();
        }
    }
}

✅ 更高级:继承 AbstractHealthIndicator

@Component
public class DatabaseHealthIndicator extends AbstractHealthIndicator {

    @Autowired
    private DataSource dataSource;

    @Override
    protected void doHealthCheck(Builder builder) throws Exception {
        try (Connection conn = dataSource.getConnection()) {
            if (conn.isValid(2)) {
                builder.up().withDetail("database", "MySQL").withDetail("schema", conn.getSchema());
            } else {
                builder.outOfService().withDetail("database", "unreachable");
            }
        }
    }
}

✅ 效果:该健康检查会自动集成到 /actuator/healthcomponents 中。


3. 自定义度量指标(Metrics)

Spring Boot 使用 Micrometer 作为指标抽象层,支持多种监控系统(Prometheus、Graphite、Datadog 等)。

✅ 方式一:使用 MeterRegistry 手动记录指标

@Service
public class OrderService {

    private final Counter orderCounter;
    private final Timer orderProcessingTimer;
    private final Gauge activeUsersGauge;

    public OrderService(MeterRegistry registry) {
        this.orderCounter = Counter.builder("orders.processed")
            .description("Number of processed orders")
            .tag("status", "success")
            .register(registry);

        this.orderProcessingTimer = Timer.builder("order.process.time")
            .description("Time taken to process an order")
            .register(registry);

        // 动态指标:当前活跃用户数
        this.activeUsersGauge = Gauge.builder("active.users", this, OrderService::getActiveUserCount)
            .register(registry);
    }

    public void processOrder(Order order) {
        Timer.Sample sample = Timer.start(meterRegistry);
        try {
            // 处理订单逻辑
            orderCounter.increment();
        } finally {
            sample.stop(orderProcessingTimer);
        }
    }

    public int getActiveUserCount() {
        return userService.countActiveUsers();
    }
}

访问 /actuator/metrics/orders.processed 查看指标。

✅ 方式二:使用注解(推荐简单场景)

@Timed:记录方法执行时间
@Timed(value = "user.login.time", description = "Time taken to login")
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
    // 登录逻辑
}
@Counted:统计调用次数
@Counted(value = "api.call.count", description = "Count of API calls", extraTags = {"method", "login"})
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
    // ...
}

📌 注解需配合 @EnableAspectJAutoProxy 或启用 Micrometer 注解支持。


4. 创建完全自定义的端点

你可以创建一个全新的端点,暴露自定义的监控或管理功能。

✅ 方式一:使用 @Endpoint(支持 HTTP + JMX)

@Component
@Endpoint(id = "feature-toggle")
public class FeatureToggleEndpoint {

    private final Map<String, Boolean> features = new ConcurrentHashMap<>();

    public FeatureToggleEndpoint() {
        features.put("new-ui", false);
        features.put("beta-api", true);
    }

    @ReadOperation
    public Map<String, Boolean> getStatus() {
        return Collections.unmodifiableMap(features);
    }

    @WriteOperation
    public void setFeature(@Selector String feature, boolean enabled) {
        features.put(feature, enabled);
    }

    @DeleteOperation
    public void resetFeature(@Selector String feature) {
        features.remove(feature);
    }
}

🔗 访问:

  • GET /actuator/feature-toggle → 获取所有功能开关
  • POST /actuator/feature-toggle/new-ui?enabled=true → 开启功能
  • DELETE /actuator/feature-toggle/new-ui → 重置

✅ 方式二:使用 @WebEndpoint(仅 HTTP)

如果你只希望支持 HTTP,可以使用:

@Component
@WebEndpoint(id = "maintenance")
public class MaintenanceEndpoint {

    private boolean underMaintenance = false;

    @ReadOperation
    public Map<String, Boolean> status() {
        return Map.of("maintenance", underMaintenance);
    }

    @WriteOperation
    public void toggle(@Selector boolean enable) {
        this.underMaintenance = enable;
    }
}

✅ 方式三:@RestControllerEndpoint(更灵活的 REST 控制器)

@Component
@RestControllerEndpoint(id = "admin")
public class AdminEndpoint {

    @GetMapping("/clear-cache")
    public ResponseEntity<String> clearCache() {
        cacheService.clearAll();
        return ResponseEntity.ok("Cache cleared");
    }

    @PostMapping("/reload-config")
    public ResponseEntity<String> reloadConfig() {
        configService.reload();
        return ResponseEntity.ok("Config reloaded");
    }
}

⚠️ 注意:@RestControllerEndpoint 的路径是 /actuator/admin/clear-cache


✅ 各方式对比

方式支持协议灵活性推荐场景
@EndpointHTTP + JMX通用自定义端点
@WebEndpoint仅 HTTP简单 HTTP 端点
@RestControllerEndpoint仅 HTTP需要完整 REST 控制器逻辑
InfoContributor/info扩展 info 信息
HealthIndicator/health健康检查
MeterRegistry / 注解指标系统业务指标监控

🔐 安全建议

  • 自定义端点可能包含敏感操作(如清缓存、重启服务),建议:
    • 配合 Spring Security 进行权限控制
    • 使用 @PreAuthorize("hasRole('ADMIN')")
    • 生产环境限制 IP 访问
    • 敏感操作记录日志
@WriteOperation
@PreAuthorize("hasRole('ADMIN')")
public void setFeature(@Selector String feature, boolean enabled) {
    // ...
}

🚀 总结:定制化监控四步法

步骤方法工具
1. 展示应用信息info.* 配置 or InfoContributor/actuator/info
2. 监控外部依赖实现 HealthIndicator/actuator/health
3. 记录业务指标MeterRegistry or @Timed/actuator/metrics
4. 创建管理功能@Endpoint, @WebEndpoint/actuator/custom

通过定制 Actuator 端点,你可以将 Spring Boot 应用打造成一个高度可观测、易运维的生产级服务。
结合 Prometheus、Grafana、Spring Boot Admin,即可构建完整的监控告警体系!📊🛠️

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值