Spring Boot Admin 监控自己导致 DOWN 状态:一个循环依赖的坑与完美解决方案

前言

最近在搭建微服务监控平台时,使用 Spring Boot Admin 作为监控中心。按照常规配置完成后,发现 Admin Server 自己在监控面板上显示为 DOWN 状态,而其他服务的健康检查却是正常的。通过 API 直接访问健康检查端点返回 200 OK,但 Admin UI 却始终显示红色 DOWN。更奇怪的是,如果禁用服务发现,Admin Server 自己消失了,但其他服务也都不见了。这个问题困扰了我整整一天,最终发现是循环依赖和配置冲突导致的。本文详细记录了从问题出现、排查思路、到最终解决的全过程,希望能帮助遇到类似问题的朋友快速定位并解决。

一、环境信息

组件版本备注
Spring Boot4.0.x微服务基础框架
Spring Boot Admin4.0.x监控服务端和客户端
Spring Cloud2025.1.x服务发现组件
Nacos3.2.x注册中心
Java17JDK 版本

架构说明

  • feng-bootadmin-server:Spring Boot Admin Server,作为监控中心
  • 其他业务服务(如 feng-user3-bizfeng-auth3):作为 Admin Client,被监控
  • 所有服务都注册到 Nacos 进行服务发现

二、问题现象

2.1 Admin UI 显示 DOWN

登录 Spring Boot Admin UI(http://localhost:12006),发现 feng-bootadmin-server 自己在监控列表中,状态为 DOWN

feng-bootadmin-server
健康: DOWN
error: Unauthorized
status: 401

2.2 健康检查接口实际正常

使用 curl 直接访问健康检查端点:

curl -v http://localhost:12006/actuator/health

返回:

< HTTP/1.1 401 Unauthorized
< WWW-Authenticate: Basic realm="Realm"

带认证信息访问:

curl -v -u admin:123456 http://localhost:12006/actuator/health

返回:

< HTTP/1.1 200 OK
{"status":"UP","components":{...}}

矛盾点:健康检查接口本身正常,但 Admin Server 认为自己 DOWN。

2.3 事件日志显示循环注册

查看 Admin Server 的事件日志:

// 23:08:18 - 注册成功
{
  "type": "REGISTERED",
  "instance": "a49f721a2bc7",
  "registration": {
    "healthUrl": "http://192.168.0.2:12006/actuator/health",
    "name": "feng-bootadmin-server"
  }
}

// 23:08:20 - 状态变为 DOWN
{
  "type": "STATUS_CHANGED",
  "statusInfo": {
    "status": "DOWN",
    "details": {
      "error": "Unauthorized",
      "status": 401
    }
  }
}

三、问题排查过程

3.1 初步怀疑:认证配置错误

尝试方案:在 application.yml 中明确配置 Admin Client 的认证信息。

spring:
  boot:
    admin:
      client:
        url: http://localhost:12006
        username: admin
        password: 123456

结果:仍然 401,问题依旧。

3.2 怀疑:Actuator 端点被 Security 保护

尝试方案:配置 Security 允许 Actuator 匿名访问。

@Configuration
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) {
        http.authorizeRequests()
            .requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
            .anyRequest().authenticated();
        return http.build();
    }
}

结果:直接访问 /actuator/health 不再需要认证,但 Admin UI 中的自己仍然是 DOWN。

3.3 发现关键:删除 client 配置后自己消失

尝试方案:完全删除 spring.boot.admin.client 配置。

spring:
  boot:
    admin:
      # 删除 client 配置块

结果:Admin UI 中 feng-bootadmin-server 完全消失了,其他服务也不见了!

3.4 根因分析

通过不断尝试和查阅文档,终于找到了根本原因:

问题本质:Spring Boot Admin Server 在启用服务发现(discovery.enabled: true)后,会从 Nacos 拉取所有注册的服务进行监控,包括自己。当监控自己时:

  1. Admin Server 作为 Client 向自己发送健康检查请求
  2. 由于 Security 配置,请求需要认证
  3. 虽然配置了 client.username/password,但在自己监控自己的场景下,认证信息没有正确传递
  4. 健康检查失败,状态变为 DOWN
  5. 如果禁用 Client(client.enabled: false),Admin Server 不会主动注册,但通过 Nacos 发现后依然会监控自己
  6. 如果禁用服务发现(discovery.enabled: false),所有服务都看不到了

循环依赖图示

Nacos 注册中心
    ↑
    │ 注册
    │
Admin Server ←──────┐
    │               │
    │ 发现并监控      │ 自己监控自己
    │               │
    ↓               │
其他服务        401 Unauthorized
                    ↓
                  DOWN 状态

四、解决方案

4.1 核心配置:启用发现但排除自己

最终的正确配置如下:

spring:
  application:
    name: feng-bootadmin-server
  security:
    user:
      name: admin
      password: 123456
      roles: ADMIN
  boot:
    admin:
      # 关键1:禁用 client 自注册
      client:
        enabled: false
      # 关键2:启用服务发现,但排除自己
      discovery:
        enabled: true
        ignored-services: feng-bootadmin-server   # 排除自己
      ui:
        extension-resource-locations: classpath:/static/
  cloud:
    nacos:
      discovery:
        server-addr: ${NACOS_SERVER:localhost:8848}
        register-enabled: true   # 注册自己,让其他服务能找到
        metadata:
          management:
            port: 12006
            context-path: /actuator

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

配置要点说明

配置项作用
client.enabledfalseAdmin Server 不主动注册到任何 Admin Server(避免自注册)
discovery.enabledtrue从 Nacos 发现服务进行监控
discovery.ignored-servicesfeng-bootadmin-server排除自己,不监控自己
nacos.discovery.register-enabledtrue注册到 Nacos,让其他服务能被发现

4.2 其他服务的标准配置

被监控的微服务配置:

spring:
  boot:
    admin:
      client:
        url: http://feng-bootadmin-server:12006
        username: admin
        password: 123456
        instance:
          metadata:
            user.name: ${spring.security.user.name}
            user.password: ${spring.security.user.password}
  cloud:
    nacos:
      discovery:
        server-addr: ${NACOS_SERVER:localhost:8848}

management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: always

4.3 验证结果

重启服务后,查看 Admin UI:

# 查看 API 返回的实例列表
curl -u admin:123456 http://localhost:12006/api/applications

返回结果只包含其他业务服务,不再包含 feng-bootadmin-server 自己:

[
  {"name": "feng-gateway3", "status": "UP"},
  {"name": "feng-user3-biz", "status": "UP"},
  {"name": "feng-auth3", "status": "UP"}
]

登录 Admin UI,所有服务正常显示为 UP,不再有红色的 DOWN 状态。
在这里插入图片描述

五、踩坑经验总结

踩坑1:client.enabled 和 discovery.enabled 的关系

错误理解:以为 client.enabled: true 才是主动注册,discovery.enabled: true 是发现其他服务,两者独立。

实际情况

  • client.enabled: true:主动向配置的 url 注册
  • discovery.enabled: true:从注册中心拉取服务,包括自己
  • 两者同时为 true 时,会重复注册

正确做法:Admin Server 上设置 client.enabled: false,其他服务设置 client.enabled: true

踩坑2:认为删除 client 配置就万事大吉

错误操作:删除 spring.boot.admin.client 配置块后,Admin Server 确实不显示自己了,但其他服务也消失了。

原因discovery.enabled 默认为 false,删除 client 配置不会自动启用发现。

正确做法:显式设置 discovery.enabled: true

踩坑3:试图通过 Security 配置解决 401

错误思路:既然健康检查返回 401,就开放所有 Actuator 端点。

问题:这会降低系统安全性,且不能解决根本问题(自己监控自己本身就是错误的)。

正确思路:不要让自己监控自己,而不是解决监控自己的认证问题。

踩坑4:使用 services: -feng-bootadmin-server 语法错误

错误写法

discovery:
  services: -feng-bootadmin-server

正确写法

discovery:
  ignored-services: feng-bootadmin-server

或者使用 YAML 列表格式:

discovery:
  ignored-services: 
    - feng-bootadmin-server
    - feng-xxx-server

六、进阶:使用独立管理端口

如果希望 Admin Server 也监控自己(不推荐),可以通过独立管理端口避免认证冲突:

management:
  server:
    port: 12007  # 独立的管理端口
  endpoints:
    web:
      base-path: /actuator
      exposure:
        include: "*"

spring:
  boot:
    admin:
      client:
        url: http://localhost:12007  # 监控自己的管理端口
        username: admin
        password: 123456

这样管理端口可以配置不同的安全策略,但会增加端口管理的复杂度。

七、最佳实践建议

7.1 架构设计原则

  1. 监控中心不应该监控自己

    • 避免循环依赖
    • 减少不必要的健康检查开销
    • 简化认证配置
  2. 使用注册中心服务发现

    • 让 Admin Server 从 Nacos/Eureka/Consul 拉取服务列表
    • 通过 ignored-services 排除不需要监控的服务
  3. 统一认证配置

    • 所有服务使用相同的 Admin Server 认证信息
    • 通过配置中心统一管理

7.2 生产环境配置模板

Admin Server 完整配置bootstrap.yml):

spring:
  application:
    name: monitor-admin-server
  cloud:
    nacos:
      config:
        server-addr: ${NACOS_SERVER:localhost:8848}
        file-extension: yaml
      discovery:
        server-addr: ${NACOS_SERVER:localhost:8848}
        register-enabled: true
        metadata:
          management:
            port: ${MANAGEMENT_PORT:12007}
            context-path: /actuator
  
---
spring:
  config:
    activate:
      on-profile: prod
  boot:
    admin:
      client:
        enabled: false
      discovery:
        enabled: true
        ignored-services:
          - monitor-admin-server
          - monitor-gateway
      monitor:
        period: 30000
        status-lifetime: 30000
        connect-timeout: 10000
        read-timeout: 10000

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics
      base-path: /actuator
  endpoint:
    health:
      show-details: when-authorized
      probes:
        enabled: true
  metrics:
    export:
      prometheus:
        enabled: true

7.3 快速排障命令

# 1. 测试健康检查是否需要认证
curl -v http://localhost:12006/actuator/health

# 2. 带认证测试
curl -u admin:123456 http://localhost:12006/actuator/health

# 3. 查看 Admin Server 注册了哪些服务
curl -u admin:123456 http://localhost:12006/api/applications | jq '.[].name'

# 4. 查看 Nacos 中的服务列表
curl -X GET "http://localhost:8848/nacos/v1/ns/service/list"

# 5. 查看具体服务的健康检查详情
curl -u admin:123456 http://localhost:12006/api/applications/{instance-id}

八、总结

踩坑汇总

问题现象根本原因解决方案
Admin Server 自己显示 DOWN自己监控自己,健康检查认证失败ignored-services 排除自己
删除 client 配置后所有服务消失未启用 discovery.enabled显式设置 discovery.enabled: true
401 UnauthorizedAdmin Server 监控自己时未传递认证信息不要让 Admin Server 监控自己
配置 services: -app 不生效语法错误,应使用 ignored-services使用正确的配置项名称

核心要点

  1. Admin Server 不监控自己:通过 ignored-services 排除自己
  2. 启用服务发现discovery.enabled: true 才能发现其他服务
  3. 禁用自注册client.enabled: false 避免重复注册
  4. 其他服务正常配置:通过 client.url 指向 Admin Server

经验教训

  • 不要想当然地认为默认配置就是最佳实践:Spring Boot Admin 的自动配置在某些场景下会产生意外行为
  • 健康检查 401 不一定是认证配置错误:可能是根本就不应该监控自己
  • 查阅官方文档时注意场景区分:Admin Server 和 Client 的配置完全不同
  • 使用注册中心时要考虑循环依赖:服务发现 + 自监控的组合容易产生环路

希望这篇文章能帮助大家避开这个看似简单却容易踩坑的问题。Spring Boot Admin 是一个强大的监控工具,正确的配置能让它发挥最大价值。如果大家在实践中遇到其他问题,欢迎交流讨论!

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐