SpringBootAdmin轻松实现服务监控

322 阅读4分钟

Spring Boot Admin 和 Nacos 都是用于监控和管理微服务的工具,但它们有不同的焦点和作用。

Spring Boot Admin:

  1. 监控 Spring Boot 应用程序: Spring Boot Admin 是专门为监控 Spring Boot 应用程序而设计的。它通过与 Spring Boot Actuator 集成,可以轻松地获取应用程序的健康状态、度量指标、环境属性等信息。
  2. 用户界面: 提供了一个用户友好的 Web 界面,用于查看和管理注册的 Spring Boot 应用程序。你可以在界面上看到应用程序的运行状态、详细信息以及执行一些管理操作。
  3. 事件监听: 支持事件监听器,可以在应用程序状态变化时触发自定义操作。
  4. 自定义监控和扩展: 支持自定义监控端点、指标和事件监听器,可以根据具体需求进行扩展。

Nacos:

  1. 服务注册与发现: Nacos 是一个用于服务注册和发现的平台,支持多种服务发现和动态配置管理的功能。它可以用于管理微服务的注册、注销和发现。
  2. 动态配置: Nacos 提供了动态配置管理功能,允许你在运行时修改应用程序的配置,而不需要重启应用。
  3. 服务健康检查: Nacos 支持对注册的服务进行健康检查,以确保服务的可用性。
  4. 集群和分布式: Nacos 支持集群部署,适用于大规模和分布式的微服务架构。

区别总结:

  • 监控范围: Spring Boot Admin 主要关注于监控和管理 Spring Boot 应用程序,提供了特定于 Spring Boot 的监控和管理功能。Nacos 则更侧重于服务注册与发现、动态配置和服务健康检查等方面,是一个更广泛用途的微服务基础设施平台。
  • 功能特点: Spring Boot Admin 提供了丰富的 Spring Boot 应用程序监控功能,包括端点监控、指标监控、事件监听等。Nacos 提供了服务注册与发现、动态配置、服务健康检查等核心功能。
  • 应用场景: 如果你的主要关注点是监控和管理 Spring Boot 应用程序,并且希望使用特定于 Spring Boot 的监控功能,那么 Spring Boot Admin 是一个很好的选择。如果你更关心微服务的注册与发现、动态配置以及服务健康检查等方面,那么 Nacos 是一个更全面的微服务基础设施平台。

效果:

1697771200536.jpg 接下来简单使用SpringBootAdmin入门实现,springbootadmin的ip和端口即可访问

以下是springbootadmin服务端


package com.xxx.xxx.admin;

import de.codecentric.boot.admin.server.config.AdminServerProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;

@Configuration
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {

    private final String adminContextPath;

    public SecuritySecureConfig(AdminServerProperties adminServer) {
        this.adminContextPath = adminServer.getContextPath();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
        successHandler.setTargetUrlParameter("redirectTo");
        successHandler.setDefaultTargetUrl(adminContextPath + "/");

        http.authorizeRequests()
                .antMatchers(adminContextPath + "/login",
                        adminContextPath + "/assets/**",
                        adminContextPath + "/manage/**",
                        adminContextPath + "/actuator/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler)
                .and()
                .logout().logoutUrl(adminContextPath + "/logout")
                .and()
                .httpBasic()
                .and()
                .csrf().ignoringAntMatchers("/instances", "/actuator/**")
                .and()
                .csrf().disable();
    }

}


package com.xxx.xxx.admin;

import de.codecentric.boot.admin.server.config.EnableAdminServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@Slf4j
@EnableAdminServer //开启admin服务端
@SpringBootApplication
public class ServiceAdminApplication {

    public static void main(String[] args) {
        log.info("DtbServiceAdminApplication starting ...");
        SpringApplication.run(ServiceAdminApplication.class, args);
        log.info("DtbServiceAdminApplication started");
    }

}
spring:
  boot:
    admin:
      ui:
        title: Service Monitoring - TEST
        brand: <img src="assets/img/icon-spring-boot-admin.svg"><span>&#26381;&#21153;&#30417;&#25511; - TEST</span>
spring:
  cloud:
    nacos:
      server-addr: test-nbdp.gacicv.com:8858
      discovery:
        register-enabled: true
      config:
        group: DEFAULT_GROUP
        namespace:
        file-extension: yaml
        extension-configs[0]:
          data-id: common-hxh
          group: DEFAULT_GROUP
          refresh: true
  security:
    user:
      name: admin
      password: 1qaz@WSX

  application:
    name: dtb-service-admin
  message:
    encoding: UTF-8
server:
  port: 8081
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 禁用logback启动时的日志 -->
    <statusListener class="ch.qos.logback.core.status.NopStatusListener"/>

    <!-- 定义日志文件的存储地址 勿在 logback的配置中使用相对路径 -->
    <property name="LOG_HOME" value="logs"/>
    <property name="APP_NAME" value="spring"/>

    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %msg [%thread](%c:%L)%n</pattern>
        </encoder>
    </appender>

    <!-- 按照每天生成日志文件 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/${APP_NAME}.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- rollover daily -->
            <fileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}-${APP_NAME}.%i.zip</fileNamePattern>
            <!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
            <maxFileSize>100MB</maxFileSize>
            <maxHistory>5</maxHistory>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!-- 格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %msg [%thread](%c:%L)%n</pattern>
        </encoder>
    </appender>

    <!-- 按照每天生成日志文件 -->
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/${APP_NAME}-err.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- rollover daily -->
            <fileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}-${APP_NAME}-err.%i.zip</fileNamePattern>
            <!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
            <maxFileSize>100MB</maxFileSize>
            <maxHistory>5</maxHistory>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!-- 格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %msg [%thread](%c:%L)%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印错误日志 -->
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- 日志输出级别 -->
    <root level="INFO">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="FILE"/>
        <appender-ref ref="ERROR"/>
    </root>

    <!-- 定义各个包的详细路径,继承root宝的值 -->
    <logger name="com.dtb.activiti.dao" level="ERROR"/>
    <logger name="com.zaxxer" level="ERROR"/>
    <logger name="com.alibaba" level="ERROR"/>
    <logger name="springfox" level="ERROR"/>
    <logger name="org" level="ERROR"/>
    <logger name="org.apache.ibatis" level="ERROR"/>
    <logger name="_org" level="ERROR"/>
    <logger name="ch" level="ERROR"/>
    <logger name="io" level="ERROR"/>

    <!-- 此值由 application.properties的spring.profiles.active=dev指定 -->
    <springProfile name="dev">
        <!-- 定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径 -->
        <property name="LOG_HOME" value="logs"/>
        <logger name="org.springboot.sample" level="ERROR"/>
    </springProfile>

    <springProfile name="pro">
        <!-- 定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径 -->
        <property name="LOG_HOME" value="logs"/>
        <logger name="org.springboot.sample2" level="INFO"/>
    </springProfile>

</configuration>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.12.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>com.xxx</groupId>
    <artifactId>service-admin</artifactId>
    <version>1.0</version>
    <name>service-admin</name>
    <description>service-admin</description>
    <properties>
        <java.version>1.8</java.version>
        <spring.cloud.alibaba.version>2.2.6.RELEASE</spring.cloud.alibaba.version>
        <maven.test.skip>true</maven.test.skip>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>${spring.cloud.alibaba.version}</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            <version>${spring.cloud.alibaba.version}</version>
        </dependency>
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-server</artifactId>
            <version>2.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <includeSystemScope>true</includeSystemScope>
                    <includes>
                        <include>
                            <groupId>nothing</groupId>
                            <artifactId>nothing</artifactId>
                        </include>
                    </includes>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <addMavenDescriptor>false</addMavenDescriptor>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>com.dtb.service.admin.ServiceAdminApplication</mainClass>
                        </manifest>
                        <manifestEntries>
                            <Class-Path>config/</Class-Path>
                        </manifestEntries>
                    </archive>
                    <excludes>
                        <classesDirectory>${project.basedir}/src/main/resources/</classesDirectory>
                        <exclude>*.properties</exclude>
                        <exclude>*.xml</exclude>
                        <exclude>*.yml</exclude>
                        <exclude>*.yaml</exclude>
                        <exclude>*.conf</exclude>
                        <exclude>**/mybatis/**</exclude>
                    </excludes>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-resources</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${project.build.directory}/maven-archiver/resources</outputDirectory>
                            <resources>
                                <resource>
                                    <directory>${basedir}/src/main/resources</directory>
                                    <include>*.properties</include>
                                    <filtering>true</filtering>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptors>
                        <descriptor>${project.basedir}/package.xml</descriptor>
                    </descriptors>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
                <version>1.8</version>
                <executions>
                    <execution>
                        <id>deploy</id>
                        <phase>package</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <target>
                                <untar src="${project.build.directory}/${project.name}-bin.tar.gz"
                                       dest="${project.build.directory}" overwrite="true" compression="gzip"/>
                            </target>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

被监控的服务

开启所有 Actuator 端点

management.endpoints.web.exposure.include=*

或者只开启特定的端点

management.endpoints.web.exposure.include=health,info,metrics,env

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-client</artifactId>
    <version>2.3.1</version>
</dependency>

配置以上即可,也可以通过配置文件中配置实现被监控

spring:
  boot:
    admin:
      client:
        url: http://localhost:8081
        ```