Skip to content

Spring Boot Actuator HTTP 监控管理详解 🚀

概述

Spring Boot Actuator 是 Spring Boot 提供的生产就绪功能模块,它能够帮助我们监控和管理应用程序。当你开发 Web 应用时,Actuator 会自动配置所有启用的端点通过 HTTP 暴露出来。

NOTE

Actuator 原生支持 Spring MVC、Spring WebFlux 和 Jersey。如果 Jersey 和 Spring MVC 都可用,Spring MVC 会被优先使用。

为什么需要 Actuator HTTP 监控? 🤔

想象一下,你的应用程序部署到生产环境后,运维团队需要:

  • 检查应用健康状态
  • 查看应用配置信息
  • 监控应用性能指标
  • 管理应用生命周期

如果没有 Actuator,你可能需要:

  • 手动编写健康检查接口
  • 自己实现配置信息暴露
  • 从头构建监控体系
  • 编写复杂的管理工具

Actuator 的设计哲学:提供开箱即用的生产级监控和管理功能,让开发者专注于业务逻辑。

默认 HTTP 端点访问方式

默认情况下,所有端点都使用 /actuator 作为前缀:

kotlin
@RestController
class HealthController {
    
    // 这是我们手动实现的方式(不推荐)
    @GetMapping("/custom-health") 
    fun customHealth(): Map<String, String> { 
        return mapOf("status" to "UP") 
    } 
    
    // Actuator 自动提供的端点(推荐)
    // 访问路径:/actuator/health
    // 无需手动编写代码
}
bash
# 健康检查
curl http://localhost:8080/actuator/health

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

# 环境信息
curl http://localhost:8080/actuator/env

IMPORTANT

Jackson 是获取正确 JSON 响应的必需依赖项。确保你的项目中包含了 Jackson 依赖。

自定义管理端点路径

更改基础路径前缀

有时候 /actuator 路径可能与你的业务路径冲突,你可以自定义前缀:

properties
# 将 /actuator 改为 /manage
management.endpoints.web.base-path=/manage
yaml
management:
  endpoints:
    web:
      base-path: "/manage"

效果对比

路径变化示例

  • 修改前: /actuator/health/actuator/info
  • 修改后: /manage/health/manage/info

自定义特定端点路径

你还可以为特定端点设置自定义路径:

properties
# 设置根路径为 /,并将 health 端点映射到 /healthcheck
management.endpoints.web.base-path=/
management.endpoints.web.path-mapping.health=healthcheck
yaml
management:
  endpoints:
    web:
      base-path: "/"
      path-mapping:
        health: "healthcheck"
kotlin
@Component
class CustomHealthIndicator : HealthIndicator {
    
    override fun health(): Health {
        // 自定义健康检查逻辑
        val isHealthy = checkDatabaseConnection() && checkExternalService()
        
        return if (isHealthy) {
            Health.up()
                .withDetail("database", "连接正常") 
                .withDetail("external-service", "服务可用") 
                .build()
        } else {
            Health.down()
                .withDetail("error", "系统异常") 
                .build()
        }
    }
    
    private fun checkDatabaseConnection(): Boolean {
        // 数据库连接检查逻辑
        return true
    }
    
    private fun checkExternalService(): Boolean {
        // 外部服务检查逻辑  
        return true
    }
}

访问路径变化

  • 原路径:/actuator/health
  • 新路径:/healthcheck

自定义管理服务器端口

为什么需要独立端口?

在生产环境中,你可能希望:

  • 安全隔离:管理端点与业务接口分离
  • 网络策略:管理端口仅对内网开放
  • 负载均衡:业务流量与监控流量分开处理

配置独立管理端口

properties
# 业务端口
server.port=8080
# 管理端口
management.server.port=8081
yaml
server:
  port: 8080
management:
  server:
    port: 8081
kotlin
@RestController
class BusinessController {
    
    @GetMapping("/api/users")
    fun getUsers(): List<User> {
        // 业务逻辑 - 运行在 8080 端口
        return userService.findAll() 
    }
}

// Actuator 端点自动运行在 8081 端口
// 访问: http://localhost:8081/actuator/health

WARNING

在 Cloud Foundry 上,应用默认只在 8080 端口接收 HTTP 和 TCP 路由请求。如果要使用自定义管理端口,需要显式设置应用路由。

配置管理专用 SSL

混合 SSL 配置场景

你可能需要这样的配置:

  • 主应用:使用 HTTPS(8443 端口)
  • 管理端点:使用 HTTP(8080 端口,仅内网访问)
properties
# 主服务器 HTTPS 配置
server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:store.jks
server.ssl.key-password=secret

# 管理服务器 HTTP 配置
management.server.port=8080
management.server.ssl.enabled=false
yaml
server:
  port: 8443
  ssl:
    enabled: true
    key-store: "classpath:store.jks"
    key-password: "secret"
management:
  server:
    port: 8080
    ssl:
      enabled: false

双 SSL 配置

如果两个端口都需要 SSL,但使用不同的证书:

properties
# 主服务器证书
server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:main.jks
server.ssl.key-password=secret

# 管理服务器证书
management.server.port=8080
management.server.ssl.enabled=true
management.server.ssl.key-store=classpath:management.jks
management.server.ssl.key-password=secret
yaml
server:
  port: 8443
  ssl:
    enabled: true
    key-store: "classpath:main.jks"
    key-password: "secret"
management:
  server:
    port: 8080
    ssl:
      enabled: true
      key-store: "classpath:management.jks"
      key-password: "secret"
kotlin
@Configuration
class SecurityConfig {
    
    @Bean
    fun managementSecurityFilterChain(http: HttpSecurity): SecurityFilterChain {
        return http
            .securityMatcher("/actuator/**")
            .authorizeHttpRequests { auth ->
                auth
                    .requestMatchers("/actuator/health").permitAll() 
                    .requestMatchers("/actuator/**").hasRole("ADMIN") 
            }
            .httpBasic(Customizer.withDefaults())
            .build()
    }
}

自定义管理服务器地址

限制访问来源

出于安全考虑,你可能只希望管理端点在特定网络接口上可用:

properties
management.server.port=8081
management.server.address=127.0.0.1
yaml
management:
  server:
    port: 8081
    address: "127.0.0.1"
kotlin
@Component
class NetworkSecurityConfig {
    
    @EventListener
    fun onApplicationReady(event: ApplicationReadyEvent) {
        val managementPort = environment.getProperty("management.server.port")
        val managementAddress = environment.getProperty("management.server.address")
        
        logger.info("管理端点仅在 $managementAddress:$managementPort 上可用") 
        logger.warn("确保防火墙规则正确配置") 
    }
    
    @Autowired
    private lateinit var environment: Environment
    
    companion object {
        private val logger = LoggerFactory.getLogger(NetworkSecurityConfig::class.java)
    }
}

NOTE

只有当管理端口与主服务器端口不同时,才能监听不同的地址。

禁用 HTTP 端点

完全禁用管理端口

如果你不想通过 HTTP 暴露任何管理端点:

properties
# 设置端口为 -1 完全禁用
management.server.port=-1
properties
# 排除所有 web 端点
management.endpoints.web.exposure.exclude=*
yaml
management:
  server:
    port: -1
yaml
management:
  endpoints:
    web:
      exposure:
        exclude: "*"

选择性暴露端点

kotlin
@Configuration
class ActuatorConfig {
    
    @Bean
    @ConditionalOnProperty(
        name = ["management.endpoints.enabled"],
        havingValue = "true",
        matchIfMissing = false
    )
    fun customEndpointConfiguration(): WebMvcEndpointHandlerMapping {
        // 仅在明确启用时才配置端点
        logger.info("Actuator 端点已启用") 
        return WebMvcEndpointHandlerMapping(
            EndpointMapping("/actuator"),
            emptyList(),
            EndpointMediaTypes.DEFAULT,
            CorsConfiguration(),
            EndpointLinksResolver(emptyList()),
            false
        )
    }
    
    companion object {
        private val logger = LoggerFactory.getLogger(ActuatorConfig::class.java)
    }
}

实际应用场景示例

生产环境最佳实践

生产环境完整配置示例
yaml
# application-prod.yml
server:
  port: 8080
  ssl:
    enabled: true
    key-store: "classpath:production.jks"
    key-password: "${SSL_KEY_PASSWORD}"

management:
  server:
    port: 8081
    address: "10.0.0.100"  # 内网地址
    ssl:
      enabled: true
      key-store: "classpath:management.jks"
      key-password: "${MANAGEMENT_SSL_PASSWORD}"
  endpoints:
    web:
      base-path: "/ops"
      exposure:
        include: "health,info,metrics,prometheus"
        exclude: "env,configprops"  # 排除敏感信息
  endpoint:
    health:
      show-details: "when-authorized"
      roles: "ADMIN"

# 安全配置
spring:
  security:
    user:
      name: "ops-admin"
      password: "${OPS_PASSWORD}"
      roles: "ADMIN"

logging:
  level:
    org.springframework.boot.actuate: INFO

开发环境便捷配置

yaml
# application-dev.yml
management:
  endpoints:
    web:
      exposure:
        include: "*"  # 开发环境暴露所有端点
  endpoint:
    health:
      show-details: "always"

总结 ✅

Spring Boot Actuator 的 HTTP 监控功能为我们提供了:

  1. 开箱即用:无需编写监控代码,自动暴露常用端点
  2. 灵活配置:支持自定义路径、端口、SSL 等
  3. 安全控制:可以限制访问地址、禁用敏感端点
  4. 生产就绪:支持复杂的生产环境部署需求

TIP

在生产环境中,建议:

  • 使用独立的管理端口
  • 限制管理端点的网络访问
  • 启用适当的安全认证
  • 仅暴露必要的端点信息

通过合理配置 Actuator HTTP 监控,你可以轻松构建一个可观测、易维护的 Spring Boot 应用程序! 🎉