Spring Boot Admin 和 Nacos 都是用于监控和管理微服务的工具,但它们有不同的焦点和作用。
Spring Boot Admin:
- 监控 Spring Boot 应用程序: Spring Boot Admin 是专门为监控 Spring Boot 应用程序而设计的。它通过与 Spring Boot Actuator 集成,可以轻松地获取应用程序的健康状态、度量指标、环境属性等信息。
- 用户界面: 提供了一个用户友好的 Web 界面,用于查看和管理注册的 Spring Boot 应用程序。你可以在界面上看到应用程序的运行状态、详细信息以及执行一些管理操作。
- 事件监听: 支持事件监听器,可以在应用程序状态变化时触发自定义操作。
- 自定义监控和扩展: 支持自定义监控端点、指标和事件监听器,可以根据具体需求进行扩展。
Nacos:
- 服务注册与发现: Nacos 是一个用于服务注册和发现的平台,支持多种服务发现和动态配置管理的功能。它可以用于管理微服务的注册、注销和发现。
- 动态配置: Nacos 提供了动态配置管理功能,允许你在运行时修改应用程序的配置,而不需要重启应用。
- 服务健康检查: Nacos 支持对注册的服务进行健康检查,以确保服务的可用性。
- 集群和分布式: Nacos 支持集群部署,适用于大规模和分布式的微服务架构。
区别总结:
- 监控范围: Spring Boot Admin 主要关注于监控和管理 Spring Boot 应用程序,提供了特定于 Spring Boot 的监控和管理功能。Nacos 则更侧重于服务注册与发现、动态配置和服务健康检查等方面,是一个更广泛用途的微服务基础设施平台。
- 功能特点: Spring Boot Admin 提供了丰富的 Spring Boot 应用程序监控功能,包括端点监控、指标监控、事件监听等。Nacos 提供了服务注册与发现、动态配置、服务健康检查等核心功能。
- 应用场景: 如果你的主要关注点是监控和管理 Spring Boot 应用程序,并且希望使用特定于 Spring Boot 的监控功能,那么 Spring Boot Admin 是一个很好的选择。如果你更关心微服务的注册与发现、动态配置以及服务健康检查等方面,那么 Nacos 是一个更全面的微服务基础设施平台。
效果:
接下来简单使用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>服务监控 - 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
```