添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

1.1 概述

Spring Boot Admin is a community project to manage and monitor your Spring Boot ® applications. The applications register with our Spring Boot Admin Client (via HTTP) or are discovered using Spring Cloud ® (e.g. Eureka , Consul). The UI is just a Vue.js application on top of the Spring Boot Actuator endpoints.

Spring Boot Admin是一个社区项目,用于管理和监视Spring Boot® 应用程序。这些应用程序在我们的Spring Boot Admin Client中注册(通过HTTP),或者使用Spring Cloud®(例如,Eureka, Consul )发现。 UI只是Spring Boot Actuator端点之上的 Vue.js 应用程序。

1.2 特点

  • Show health status:显示健康状况

  • Show details, like:显示详细信息,例如

    • JVM & memory metrics:JVM 和 内存指标

    • micrometer.io metrics:micrometer io指标

    • Datasource metrics:数据源指标

    • Cache metrics:缓存指标

  • Show build-info number:显示构建信息编号

  • Follow and download logfile:追踪并下载日志文件

  • View jvm system- & environment-properties:查看 jvm 系统属性和环境属性

  • View Spring Boot Configuration Properties:查看 Spring Boot 配置属性

  • Support for Spring Cloud’s postable /env- &/refresh-endpoint:支持Spring Cloud的可发布/ env-和// refresh-endpoint

  • Easy loglevel management:轻松的日志级别管理

  • Interact with JMX-beans:与JMX-beans交互

  • View thread dump:查看线程转储

  • View http-traces:查看http跟踪

  • View auditevents:查看审计事件

  • View http-endpoints:查看http端点

  • View scheduled tasks:查看定时任务

  • View and delete active sessions (using spring-session):查看和删除活动会话(使用spring-session)

  • View Flyway / Liquibase database migrations:查看Flyway / Liquibase数据库迁移

  • Download heapdump:下载 heapdump

  • Notification on status change (via e-mail, Slack, Hipchat, …):状态更改通知(通过电子邮件,Slack,Hipchat等)

  • Event journal of status changes (non persistent):状态更改的事件日志(非持久性)

2.演示环境

  1. JDK 1.8.0_201

  2. Spring Boot 2.2.0.RELEASE

  3. 构建工具(apache maven 3.6.3)

  4. 开发工具(IntelliJ IDEA )

3.演示代码

3.1 代码说明

使用 spring boot admin 需要两个项目:一个是 admin 项目,一个是 client 项目。admin 项目开启 SpringBoot Admin 功能,client 项目注册到 admin 项目上。

3.2 代码结构

3.3 maven 依赖

spring-boot-admin --> pom.xml

<modules>
    <module>spring-boot-admin-server</module>
    <module>spring-boot-admin-client</module>
</modules>

spring-boot-admin-server --> pom.xml

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>de.codecentric</groupId>
        <artifactId>spring-boot-admin-starter-server</artifactId>
    </dependency>
</dependencies>
12345678910

spring-boot-admin-client --> pom.xml

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>de.codecentric</groupId>
        <artifactId>spring-boot-admin-starter-client</artifactId>
    </dependency>
</dependencies>
12345678910

3.4 配置文件

spring-boot-admin-server --> application.properties

spring.application.name=spring-boot-admin-server
server.port=8080

spring-boot-admin-client --> application.properties

spring.application.name=spring-boot-admin-client
server.port=9090
# 指定admin-server地址
spring.boot.admin.client.url=http://localhost:8080
# 监控所有的endpoint
management.endpoints.web.exposure.include=*
1234567

3.5 java代码

SpringBootAdminServerApplication.java

@EnableAdminServer
@SpringBootApplication
public class SpringBootAdminServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootAdminServerApplication.class, args);
12345678

SpringBootAdminClientApplication.java

@SpringBootApplication
public class SpringBootAdminClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootAdminClientApplication.class, args);
1234567

3.6 git 地址

spring-boot/spring-boot-05-basis/spring-boot-admin

4.效果展示

先启动 SpringBootAdminServerApplication.main 方法,再启动 SpringBootAdminClientApplication.main 方法。

访问 http://localhost:8080/,会自动跳转到 Spring Boot Admin 界面,可以看到 spring-boot-admin-client 已经注册上来了

点击 spring-boot-admin-client,可以查看各项监控指标

5.源码分析

5.1 admin server 的请求原理

Spring Boot Admin 组件中,通过 @EnableAdminServer 标识一个 admin server 组件,并启动。EnableAdminServer 的内容如下.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AdminServerMarkerConfiguration.class)
public @interface EnableAdminServer {
1234567

EnableAdminServer 通过 @Import 导入一个 AdminServerMarkerConfiguration 配置类。

@Configuration(proxyBeanMethods = false)
public class AdminServerMarkerConfiguration {
   @Bean
   public Marker adminServerMarker() {
      return new Marker();
   public static class Marker {
123456789101112

AdminServerMarkerConfiguration 中定义了一个静态内部类 Marker,并将它声明为 Bean。那么这个 admin server 又是如何生效的呢?实际上,admin server 有一个自动装配类 AdminServerAutoConfiguration,这个类的内容如下。

@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(AdminServerMarkerConfiguration.Marker.class)
@EnableConfigurationProperties(AdminServerProperties.class)
@ImportAutoConfiguration({ AdminServerInstanceWebClientConfiguration.class, AdminServerWebConfiguration.class })
@AutoConfigureAfter({ WebClientAutoConfiguration.class })
public class AdminServerAutoConfiguration {
   private final AdminServerProperties adminServerProperties;
   public AdminServerAutoConfiguration(AdminServerProperties adminServerProperties) {
      this.adminServerProperties = adminServerProperties;
   @Bean
   @ConditionalOnMissingBean
   public InstanceRegistry instanceRegistry(InstanceRepository instanceRepository,
         InstanceIdGenerator instanceIdGenerator) {
      return new InstanceRegistry(instanceRepository, instanceIdGenerator);
   @Bean
   @ConditionalOnMissingBean
   public ApplicationRegistry applicationRegistry(InstanceRegistry instanceRegistry,
         InstanceEventPublisher instanceEventPublisher) {
      return new ApplicationRegistry(instanceRegistry, instanceEventPublisher);
   @Bean
   @ConditionalOnMissingBean
   public InstanceIdGenerator instanceIdGenerator() {
      return new HashingInstanceUrlIdGenerator();
   @Bean
   @ConditionalOnMissingBean
   public StatusUpdater statusUpdater(InstanceRepository instanceRepository,
         InstanceWebClient.Builder instanceWebClientBulder) {
      return new StatusUpdater(instanceRepository, instanceWebClientBulder.build());
   @Bean(initMethod = "start", destroyMethod = "stop")
   @ConditionalOnMissingBean
   public StatusUpdateTrigger statusUpdateTrigger(StatusUpdater statusUpdater, Publisher<InstanceEvent> events) {
      StatusUpdateTrigger trigger = new StatusUpdateTrigger(statusUpdater, events);
      trigger.setInterval(this.adminServerProperties.getMonitor().getStatusInterval());
      trigger.setLifetime(this.adminServerProperties.getMonitor().getStatusLifetime());
      return trigger;
   @Bean
   @ConditionalOnMissingBean
   public EndpointDetector endpointDetector(InstanceRepository instanceRepository,
         InstanceWebClient.Builder instanceWebClientBuilder) {
      InstanceWebClient instanceWebClient = instanceWebClientBuilder.build();
      ChainingStrategy strategy = new ChainingStrategy(new QueryIndexEndpointStrategy(instanceWebClient),
            new ProbeEndpointsStrategy(instanceWebClient, this.adminServerProperties.getProbedEndpoints()));
      return new EndpointDetector(instanceRepository, strategy);
   @Bean(initMethod = "start", destroyMethod = "stop")
   @ConditionalOnMissingBean
   public EndpointDetectionTrigger endpointDetectionTrigger(EndpointDetector endpointDetector,
         Publisher<InstanceEvent> events) {
      return new EndpointDetectionTrigger(endpointDetector, events);
   @Bean
   @ConditionalOnMissingBean
   public InfoUpdater infoUpdater(InstanceRepository instanceRepository,
         InstanceWebClient.Builder instanceWebClientBuilder) {
      return new InfoUpdater(instanceRepository, instanceWebClientBuilder.build());
   @Bean(initMethod = "start", destroyMethod = "stop")
   @ConditionalOnMissingBean
   public InfoUpdateTrigger infoUpdateTrigger(InfoUpdater infoUpdater, Publisher<InstanceEvent> events) {
      InfoUpdateTrigger trigger = new InfoUpdateTrigger(infoUpdater, events);
      trigger.setInterval(this.adminServerProperties.getMonitor().getInfoInterval());
      trigger.setLifetime(this.adminServerProperties.getMonitor().getInfoLifetime());
      return trigger;
   @Bean
   @ConditionalOnMissingBean(InstanceEventStore.class)
   public InMemoryEventStore eventStore() {
      return new InMemoryEventStore();
   @Bean(initMethod = "start", destroyMethod = "stop")
   @ConditionalOnMissingBean(InstanceRepository.class)
   public SnapshottingInstanceRepository instanceRepository(InstanceEventStore eventStore) {
      return new SnapshottingInstanceRepository(eventStore);
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394

AdminServerAutoConfiguration 通过 @ImportAutoConfiguration 导入了 AdminServerWebConfiguration 和

AdminServerInstanceWebClientConfiguration。查看 AdminServerWebConfiguration 内容

@Configuration(proxyBeanMethods = false)
public class AdminServerWebConfiguration {
    private final AdminServerProperties adminServerProperties;
    public AdminServerWebConfiguration(AdminServerProperties adminServerProperties) {
        this.adminServerProperties = adminServerProperties;
    @Bean
    public SimpleModule adminJacksonModule() {
        SimpleModule module = new SimpleModule();
        module.addDeserializer(Registration.class, new RegistrationDeserializer());
        module.setSerializerModifier(new RegistrationBeanSerializerModifier(
            new SanitizingMapSerializer(this.adminServerProperties.getMetadataKeysToSanitize())));
        return module;
    @Bean
    @ConditionalOnMissingBean
    public InstancesController instancesController(InstanceRegistry instanceRegistry, InstanceEventStore eventStore) {
        return new InstancesController(instanceRegistry, eventStore);
    @Bean
    @ConditionalOnMissingBean
    public ApplicationsController applicationsController(ApplicationRegistry applicationRegistry) {
        return new ApplicationsController(applicationRegistry);
    // reactive web configuration ...
    @Configuration(proxyBeanMethods = false)
    @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
    @AutoConfigureAfter(WebMvcAutoConfiguration.class)
    public static class ServletRestApiConfirguation {
        private final AdminServerProperties adminServerProperties;
        public ServletRestApiConfirguation(AdminServerProperties adminServerProperties) {
            this.adminServerProperties = adminServerProperties;
        @Bean
        @ConditionalOnMissingBean
        public de.codecentric.boot.admin.server.web.servlet.InstancesProxyController instancesProxyController(
            InstanceRegistry instanceRegistry, InstanceWebClient.Builder instanceWebClientBuilder) {
            return new de.codecentric.boot.admin.server.web.servlet.InstancesProxyController(
                this.adminServerProperties.getContextPath(),
                this.adminServerProperties.getInstanceProxy().getIgnoredHeaders(), instanceRegistry,
                instanceWebClientBuilder.build());
        @Bean
        public org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping adminHandlerMapping(
            ContentNegotiationManager contentNegotiationManager) {
            org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping mapping = new de.codecentric.boot.admin.server.web.servlet.AdminControllerHandlerMapping(
                this.adminServerProperties.getContextPath());
            mapping.setOrder(0);
            mapping.setContentNegotiationManager(contentNegotiationManager);
            return mapping;
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364

默认 servlet 情况下,会使用 ServletRestApiConfirguation 配置,生成 web mvc 的服务。在 ServletRestApiConfirguation 声明了 AdminControllerHandlerMapping 的 RequestMappingHandlerMapping 实例对象。

这个 AdminControllerHandlerMapping 用来处理被 @AdminController 修饰的类

@Override
protected boolean isHandler(Class<?> beanType) {
    return AnnotatedElementUtils.hasAnnotation(beanType, AdminController.class);

spring-boot-admin-server.jar 中提供了一些被 @AdminController 修饰的类,比如:ApplicationsController、NotificationFilterController、InstancesController、InstancesProxyController 等。ApplicationsController 内容如下。

@AdminController
@ResponseBody
public class ApplicationsController {
    private static final Logger log = LoggerFactory.getLogger(ApplicationsController.class);
    private static final ServerSentEvent<?> PING = ServerSentEvent.builder().comment("ping").build();
    private static final Flux<ServerSentEvent<?>> PING_FLUX = Flux.interval(Duration.ZERO, Duration.ofSeconds(10L))
        .map((tick) -> PING);
    private final ApplicationRegistry registry;
    public ApplicationsController(ApplicationRegistry registry) {
        this.registry = registry;
    @GetMapping(path = "/applications", produces = MediaType.APPLICATION_JSON_VALUE)
    public Flux<Application> applications() {
        return registry.getApplications();
    @GetMapping(path = "/applications/{name}", produces = MediaType.APPLICATION_JSON_VALUE)
    public Mono<ResponseEntity<Application>> application(@PathVariable("name") String name) {
        return registry.getApplication(name).map(ResponseEntity::ok).defaultIfEmpty(ResponseEntity.notFound().build());
    @GetMapping(path = "/applications", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ServerSentEvent<Application>> applicationsStream() {
        return registry.getApplicationStream().map((application) -> ServerSentEvent.builder(application).build())
            .mergeWith(ping());
    @DeleteMapping(path = "/applications/{name}")
    public Mono<ResponseEntity<Void>> unregister(@PathVariable("name") String name) {
        log.debug("Unregister application with name '{}'", name);
        return registry.deregister(name).collectList().map((deregistered) -> !deregistered.isEmpty()
                                                           ? ResponseEntity.noContent().build() : ResponseEntity.notFound().build());
    @SuppressWarnings("unchecked")
    private static <T> Flux<ServerSentEvent<T>> ping() {
        return (Flux<ServerSentEvent<T>>) (Flux) PING_FLUX;
123456789101112131415161718192021222324252627282930313233343536373839404142434445

其中 applications() 方法刚好处理 http://localhost:8080/ 跳转后的 http://localhost:8080/applications 请求。

5.2 server 和 client 之间通信

在 spring-boot-admin-server 中有自动装配类 AdminServerAutoConfiguration,相应地,在 spring-boot-admin-client 也有一个自动装配类。它是 SpringBootAdminClientAutoConfiguration。

这个 SpringBootAdminClientAutoConfiguration 声明了如下主要类型

@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication
@Conditional(SpringBootAdminClientEnabledCondition.class)
@AutoConfigureAfter({ WebEndpointAutoConfiguration.class, RestTemplateAutoConfiguration.class, WebClientAutoConfiguration.class })
@EnableConfigurationProperties({ ClientProperties.class, InstanceProperties.class, ServerProperties.class, ManagementServerProperties.class })
public class SpringBootAdminClientAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public ApplicationRegistrator registrator(RegistrationClient registrationClient, ClientProperties client, ApplicationFactory applicationFactory) {
        return new ApplicationRegistrator(applicationFactory, registrationClient, client.getAdminUrl(), client.isRegisterOnce());
    @Bean
    @ConditionalOnMissingBean
    public RegistrationApplicationListener registrationListener(ClientProperties client,
                                                                ApplicationRegistrator registrator, Environment environment) {
        RegistrationApplicationListener listener = new RegistrationApplicationListener(registrator);
        listener.setAutoRegister(client.isAutoRegistration());
        listener.setAutoDeregister(client.isAutoDeregistration(environment));
        listener.setRegisterPeriod(client.getPeriod());
        return listener;
    @Bean
    @ConditionalOnMissingBean
    public StartupDateMetadataContributor startupDateMetadataContributor() {
        return new StartupDateMetadataContributor();
    @Configuration(proxyBeanMethods = false)
    @ConditionalOnWebApplication(type = Type.SERVLET)
    @AutoConfigureAfter(DispatcherServletAutoConfiguration.class)
    public static class ServletConfiguration {
        @Bean
        @ConditionalOnMissingBean
        public ApplicationFactory applicationFactory(InstanceProperties instance, ManagementServerProperties management, ServerProperties server, ServletContext servletContext, PathMappedEndpoints pathMappedEndpoints, WebEndpointProperties webEndpoint, ObjectProvider<List<MetadataContributor>> metadataContributors, DispatcherServletPath dispatcherServletPath) {
            return new ServletApplicationFactory(instance, management, server, servletContext, pathMappedEndpoints, webEndpoint, new CompositeMetadataContributor(
                metadataContributors.getIfAvailable(Collections::emptyList)), dispatcherServletPath);
    @Configuration(proxyBeanMethods = false)
    @ConditionalOnBean(RestTemplateBuilder.class)
    public static class BlockingRegistrationClientConfig {
        @Bean
        @ConditionalOnMissingBean
        public BlockingRegistrationClient registrationClient(ClientProperties client) {
            RestTemplateBuilder builder = new RestTemplateBuilder().setConnectTimeout(client.getConnectTimeout())
                .setReadTimeout(client.getReadTimeout());
            if (client.getUsername() != null && client.getPassword() != null) {
                builder = builder.basicAuthentication(client.getUsername(), client.getPassword());
            return new BlockingRegistrationClient(builder.build());
    // ...
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263

ApplicationRegistrator 用来注册到 admin-server,其中定义了 register 和 deregister 方法

* Registers the client application at spring-boot-admin-server public class ApplicationRegistrator { private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationRegistrator.class); private final ConcurrentHashMap<String, LongAdder> attempts = new ConcurrentHashMap<>(); private final AtomicReference<String> registeredId = new AtomicReference<>(); private final ApplicationFactory applicationFactory; private final String[] adminUrls; private final boolean registerOnce; private final RegistrationClient registrationClient; public ApplicationRegistrator(ApplicationFactory applicationFactory, RegistrationClient registrationClient, String[] adminUrls, boolean registerOnce) { this.applicationFactory = applicationFactory; this.adminUrls = adminUrls; this.registerOnce = registerOnce; this.registrationClient = registrationClient; * Registers the client application at spring-boot-admin-server. * @return true if successful registration on at least one admin server public boolean register() { Application application = this.applicationFactory.createApplication(); boolean isRegistrationSuccessful = false; for (String adminUrl : this.adminUrls) { LongAdder attempt = this.attempts.computeIfAbsent(adminUrl, (k) -> new LongAdder()); boolean successful = register(application, adminUrl, attempt.intValue() == 0); if (!successful) { attempt.increment(); else { attempt.reset(); isRegistrationSuccessful = true; if (this.registerOnce) { break; return isRegistrationSuccessful; protected boolean register(Application application, String adminUrl, boolean firstAttempt) { try { String id = this.registrationClient.register(adminUrl, application); if (this.registeredId.compareAndSet(null, id)) { LOGGER.info("Application registered itself as {}", id); else { LOGGER.debug("Application refreshed itself as {}", id); return true; catch (Exception ex) { if (firstAttempt) { LOGGER.warn( "Failed to register application as {} at spring-boot-admin ({}): {}. Further attempts are logged on DEBUG level", application, this.adminUrls, ex.getMessage()); else { LOGGER.debug("Failed to register application as {} at spring-boot-admin ({}): {}", application, this.adminUrls, ex.getMessage()); return false; public void deregister() { String id = this.registeredId.get(); if (id == null) { return; for (String adminUrl : this.adminUrls) { try { this.registrationClient.deregister(adminUrl, id); this.registeredId.compareAndSet(id, null); if (this.registerOnce) { break; catch (Exception ex) { LOGGER.warn("Failed to deregister application (id={}) at spring-boot-admin ({}): {}", id, adminUrl, ex.getMessage()); * @return the id of this client as given by the admin server. Returns null if the * client has not registered against the admin server yet. public String getRegisteredId() { return this.registeredId.get(); 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108

RegistrationApplicationListener 则是用来触发开始注册和停止注册任务,它实现了 InitializingBean 和 DisposableBean 接口,分别定定义了初始化完成后和销毁前的处理方式。

private final ThreadPoolTaskScheduler taskScheduler;
public RegistrationApplicationListener(ApplicationRegistrator registrator) {
    this(registrator, registrationTaskScheduler());
// 声明线程池
private static ThreadPoolTaskScheduler registrationTaskScheduler() {
    ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
    taskScheduler.setPoolSize(1);
    taskScheduler.setRemoveOnCancelPolicy(true);
    taskScheduler.setThreadNamePrefix("registrationTask");
    return taskScheduler;
RegistrationApplicationListener(ApplicationRegistrator registrator, ThreadPoolTaskScheduler taskScheduler) {
    this.registrator = registrator;
    this.taskScheduler = taskScheduler;
// 实现 InitializingBean 中 afterPropertiesSet 方法
@Override
public void afterPropertiesSet() {
    taskScheduler.afterPropertiesSet();
// 实现 DisposableBean 中 destroy 方法
@Override
public void destroy() {
    taskScheduler.destroy();
12345678910111213141516171819202122232425262728293031

同时,它还接收 ApplicationReadyEvent 事件和 ContextClosedEvent 事件

// 接收 ApplicationReadyEvent 事件
@EventListener
@Order(Ordered.LOWEST_PRECEDENCE)
public void onApplicationReady(ApplicationReadyEvent event) {
    if (autoRegister) {
        // 启动开始注册任务
        startRegisterTask();
// 接收 ContextClosedEvent 事件
@EventListener
@Order(Ordered.LOWEST_PRECEDENCE)
public void onClosedContext(ContextClosedEvent event) {
    if (event.getApplicationContext().getParent() == null
        || "bootstrap".equals(event.getApplicationContext().getParent().getId())) {
        // 停止注册任务
        stopRegisterTask();
        if (autoDeregister) {
            // 删除注册内容
            registrator.deregister();
// 启动注册任务
public void startRegisterTask() {
    if (scheduledTask != null && !scheduledTask.isDone()) {
        return;
    // 开启定时任务,默认执行周期 10s,定时任务调用 registrator::register 方法
    scheduledTask = taskScheduler.scheduleAtFixedRate(registrator::register, registerPeriod);
    LOGGER.debug("Scheduled registration task for every {}ms", registerPeriod);
// 停止注册任务
public void stopRegisterTask() {
    if (scheduledTask != null && !scheduledTask.isDone()) {
        // 取消任务
        scheduledTask.cancel(true);
        LOGGER.debug("Canceled registration task");
123456789101112131415161718192021222324252627282930313233343536373839404142434445

其中 registrator.register 实现如下

public boolean register() {
    Application application = this.applicationFactory.createApplication();
    boolean isRegistrationSuccessful = false;
    for (String adminUrl : this.adminUrls) {
        LongAdder attempt = this.attempts.computeIfAbsent(adminUrl, (k) -> new LongAdder());
        // 注册
        boolean successful = register(application, adminUrl, attempt.intValue() == 0);
        if (!successful) {
            attempt.increment();
        else {
            attempt.reset();
            isRegistrationSuccessful = true;
            if (this.registerOnce) {
                break;
    return isRegistrationSuccessful;
protected boolean register(Application application, String adminUrl, boolean firstAttempt) {
    try {
        // 调用 registrationClient 的 register 方法
        String id = this.registrationClient.register(adminUrl, application);
        if (this.registeredId.compareAndSet(null, id)) {
            LOGGER.info("Application registered itself as {}", id);
        else {
            LOGGER.debug("Application refreshed itself as {}", id);
        return true;
    catch (Exception ex) {
        if (firstAttempt) {
            LOGGER.warn(
                "Failed to register application as {} at spring-boot-admin ({}): {}. Further attempts are logged on DEBUG level",
                application, this.adminUrls, ex.getMessage());
        else {
            LOGGER.debug("Failed to register application as {} at spring-boot-admin ({}): {}", application,
                         this.adminUrls, ex.getMessage());
        return false;
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849

最终调用 registrationClient.register 方法,它的实现如下

public class BlockingRegistrationClient implements RegistrationClient {
    private static final ParameterizedTypeReference<Map<String, Object>> RESPONSE_TYPE = new ParameterizedTypeReference<Map<String, Object>>() {
    private final RestTemplate restTemplate;
    public BlockingRegistrationClient(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    // 向指定的 adminUrl 方式 Post 请求
    @Override
    public String register(String adminUrl, Application application) {
        ResponseEntity<Map<String, Object>> response = this.restTemplate.exchange(adminUrl, HttpMethod.POST, new HttpEntity<>(application, this.createRequestHeaders()), RESPONSE_TYPE);
        return response.getBody().get("id").toString();
    protected HttpHeaders createRequestHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
        return HttpHeaders.readOnlyHttpHeaders(headers);
12345678910111213141516171819202122232425

registrator.deregister

public void deregister() {
    String id = this.registeredId.get();
    if (id == null) {
        return;
    for (String adminUrl : this.adminUrls) {
        try {
            // 调用 registrationClient 的 deregister 方法
            this.registrationClient.deregister(adminUrl, id);
            this.registeredId.compareAndSet(id, null);
            if (this.registerOnce) {
                break;
        catch (Exception ex) {
            LOGGER.warn("Failed to deregister application (id={}) at spring-boot-admin ({}): {}", id, adminUrl, ex.getMessage());
1234567891011121314151617181920

最终调用 registrationClient.deregister 方法,它的实现如下

@Override
public void deregister(String adminUrl, String id) {
    // 调用 Delete 方法
    this.restTemplate.delete(adminUrl + '/' + id);
12345
  1. Spring Boot Admin

https://blog.csdn.net/u010139373/article/details/1076007581.简介1.1 概述Spring Boot Admin is a community project to manage and monitor your Spring Boot ® applications. The applications register with our Spring Boot Admin Client (via HTTP) or are disco
使用到了springbootAdmin这个工具,但是有关它们的配置不太理解。下面是我对照着官网的说明以及自己的理解总结的,如果有不正确的地方欢迎大家指正。(我这里只是在springboot使用了SBA,还没有涉及到其它更加高级的spring cloud等。这里的属性也只是最简单的一些配置属性) springbootAdmin—client端配置属性详解: spring.boot.admin....
来自Codecentric的Spring Boot Admin 是一个管理和监控SpringBoot应用的工具。Spring Boot应用程序可以使用Spring Boot Admin Client通过进行主动HTTP注册,或在服务端使用Spring Cloud(如Eureka,Consul)工具进行服务发现。 SpringBoot Admin前端使用AngularJS应用程序,可以监控...
主要的功能点有:可点击https://github.com/codecentric/spring-boot-admin更多了解 Spring-boot-admin。搭建服务流程说明**版本说明:**版本建议:SpringBoot2.x=SpringBootAdmin2.x(比如SpringBoot2.3.x可以用SpringBootAdmin2.3.x)创建一个 Spring Boot 项目,用于展示各个服务中的监控信息,加上 Spring Boot Admin 的依赖,具体代码如下所示 添加 @E
Spring Boot Admin(SBA)是一个开源的社区项目,用于管理和监控 Spring Boot 应用程序。应用程序可以通过 http 的方式,或 Spring Cloud 服务发现机制注册到 SBA 中,然后就可以实现对 Spring Boot 项目的可视化管理和查看了。 Spring Boot Admin 可以监控 Spring Boot 单机或集群项目,它提供详细的健康 (Health)信息、内存信息、JVM 系统和环境属性、垃圾回收信息、日志设置和查看、定时任务查看、Spring Bo..
Spring Boot Admin可以将 Actuator 中的信息进行界面化的展示,用于监控所有 Spring Boot 应用的健康状况,提供实时警报功能。 使用步骤 1.服务器 1.Maven导入依赖 必须是web应用 所以导入spring-boot-starter-web admin版本必须和springboot一致 <dependency> <groupId>org.springframework.boot</groupId&gt
文章目录前言1. 监控组成2. 如何配置使用第一部分 配置服务端第二部分 配置客户端第三部分 认识Spring Boot Admin的监控信息遇到的错误问题1:启动失败问题2:Spring Boot Admin 服务端没看到客户端注册进来 Spring Boot Admin 是开源的图形化监控项目,用于管理监控SpringBoot应用。 1. 监控组成 Spring Boot Admin 分为一下两种角色: 客户端 : 被监控的项目。admin-server 服务段: 监控台。admin-c
SpringBootAdmin可以监控SpringBoot单击或集群项目,提供详细的健康信息、内存信息、JVM系统和环境属性、垃圾回收信息、日志设置和查看、定时任务查看、SpringBoot缓存查看和管理功能。 第一步:监控服务端搭建 创建一个SpringBoot项目,添加下面依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spr...
Admin Server一、Admin Server1.parent pom2.pom3.AdminServerApplication4.application.yml4. 启动界面二、Admin Client1.pom2.AdminClientApplication3.applicaiton.yml 一、Admin Server 1.parent pom <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven
你可以通过更改pom.xml文件中的spring-boot-starter-parent的版本号来更改spring boot版本。具体来说,你需要在pom.xml文件中找到以下行: <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.2</version> <relativePath/> <!-- lookup parent from repository --> </parent> 将version标签中的版本号更改为你想要使用的版本号即可。然后重新构建项目即可使用新的spring boot版本。