spring-boot-admin基础搭建教程

简介: spring-boot-admin为我们基于spring-boot的基础数据安全端口提供了基础的可视化监控功能。还可以通过spring-boot-admin的server程序对spring-boot程序提供简单的实时管理(例如修改日志输出级别)。

spring-boot-admin为我们基于spring-boot的基础数据安全端口提供了基础的可视化监控功能。还可以通过spring-boot-admin的server程序对spring-boot程序提供简单的实时管理(例如修改日志输出级别)。
通过官方的英文指导文档,可以很方便的学习spring-boot-admin的集成。根据个人的学习过程简单整理了一下,希望对想要学习的童鞋有所帮助。

注意,搭建demo的过程中采用了maven来构建,在父pom中统一配置spring-boot、spring-cloud以及spring-boot-admin相关组件的版本,所以在子模块中,引入依赖时不会显示指明版本。
以下是父pom中的的主要配置

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.8.RELEASE</version>
    <relativePath/>
</parent>
<properties>
    <java.version>1.8</java.version>
    <admin.version>1.5.4</admin.version>
</properties>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Dalston.SR4</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-client</artifactId>
            <version>${admin.version}</version>
        </dependency>
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-server</artifactId>
            <version>${admin.version}</version>
        </dependency>
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-server-ui</artifactId>
            <version>${admin.version}</version>
        </dependency>
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-server-ui-hystrix</artifactId>
            <version>${admin.version}</version>
        </dependency>
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-server-ui-turbine</artifactId>
            <version>${admin.version}</version>
        </dependency>
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-server-ui-login</artifactId>
            <version>${admin.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

一、spring-boot + spring-boot-admin 集成基础

1.1、利用spring-boot-starter-actuator创建安全端点

添加maven依赖

首先,我们创建一个admin-client作为spring-boot-admin的客户端程序。该程序依赖如下两个依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

application.properties文件配置

我们设置内嵌tomcat监听端口为8090

spring.application.name=admin-client
server.port=8090
#关闭安全控制
management.security.enabled=false

启动类配置

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

测试效果

直接启动main方法,可以看到日志中有如下几行记录,里面有spring-boot-starter-actuator为我们暴露的信息

2017-10-22 16:59:22.572  INFO 341860 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/loggers/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.get(java.lang.String)
2017-10-22 16:59:22.573  INFO 341860 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/loggers/{name:.*}],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v1+json || application/json],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.set(java.lang.String,java.util.Map<java.lang.String, java.lang.String>)
2017-10-22 16:59:22.573  INFO 341860 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/loggers || /loggers.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-10-22 16:59:22.579  INFO 341860 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/health || /health.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(javax.servlet.http.HttpServletRequest,java.security.Principal)
2017-10-22 16:59:22.581  INFO 341860 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/mappings || /mappings.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-10-22 16:59:22.583  INFO 341860 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/info || /info.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-10-22 16:59:22.584  INFO 341860 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/autoconfig || /autoconfig.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-10-22 16:59:22.586  INFO 341860 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/heapdump || /heapdump.json],methods=[GET],produces=[application/octet-stream]}" onto public void org.springframework.boot.actuate.endpoint.mvc.HeapdumpMvcEndpoint.invoke(boolean,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException,javax.servlet.ServletException
2017-10-22 16:59:22.587  INFO 341860 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/configprops || /configprops.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-10-22 16:59:22.591  INFO 341860 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/beans || /beans.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-10-22 16:59:22.598  INFO 341860 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/trace || /trace.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-10-22 16:59:22.600  INFO 341860 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/dump || /dump.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-10-22 16:59:22.601  INFO 341860 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/metrics/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String)
2017-10-22 16:59:22.602  INFO 341860 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/metrics || /metrics.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-10-22 16:59:22.605  INFO 341860 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/auditevents || /auditevents.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public org.springframework.http.ResponseEntity<?> org.springframework.boot.actuate.endpoint.mvc.AuditEventsMvcEndpoint.findByPrincipalAndAfterAndType(java.lang.String,java.util.Date,java.lang.String)
2017-10-22 16:59:22.606  INFO 341860 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/env/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint.value(java.lang.String)
2017-10-22 16:59:22.607  INFO 341860 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/env || /env.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()

我们简单访问health端点地址:http://127.0.0.1:8090/health,可以得到如下程序健康信息结果

{"status":"UP","diskSpace":{"status":"UP","total":104857595904,"free":55882469376,"threshold":10485760}}

由于端点众多且与其他框架例如spring-cloud集成时还会增加其他端点,非常不方便记忆核操作。同时直接访问的时候返回的数据都是JSON格式的字符串,查看不太直观。所以这就有了spring-boot-admin,它可以为我们提供这些端点比较直观的UI界面效果,方便我们的运营、运维、技术等人员使用。

1.2、创建spring-boot-admin服务端程序admin-server

我们创建admin-server作为spring-boot-admin的server端程序,为该程序添加jar包依赖,该依赖包括自动装配依赖和UI依赖

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-server</artifactId>
</dependency>
<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-server-ui</artifactId>
</dependency>

配置监听端口核程序名等

spring.application.name=admin-server
server.port=80

创建核配置启动类

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

@EnableAdminServer注解表示开启spring-boot-admin-server程序。直接启动main方法后,我们访问http://127.0.0.1,可以看到简单的界面效果,由于目前没有客户端程序所以列表中没有记录

image

接下来我们将之前的admin-client程序集成spring-boot-admin-starter-client,先修改maven依赖

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>

其次,我们在配置文件中新增如下配置

#设置admin-server的地址
spring.boot.admin.url=http://127.0.0.1

然后我们启动admin-client程序,我们可以看看admin-client程序已经可以在admin-server程序的UI界面中看到了

image

点击Details按钮,可以看到更多程序的信息,例如

image

从图中我们可以看到内存使用的情况,这些数据都是通过admin-client程序的端点获取到的信息并展示给我们。信息非常多,更多细节功能可以自己探索,这里不做赘述。

小结

从以上简单的例子中,我们可以发现一般的spring-boot程序使用spring-boot-admin作为管理工具需要经过如下两个步骤:

  • 1、需要创建一个spring-boot-admin的server程序。
  • 2、为应用程序集成spring-boot-admin-stater-client客户端。
  • 3、客户端配置关闭掉端口的安全控制以及配置上admin-server的URL地址。
  • 4、spring-boot-admin的管理程序必须与客户端程序必须网络可达。

1.3 为admin-server程序添加安全访问控制

admin-server程序是spring-boot的安全端点管理程序,自身的安全也是比不可少的,所以我们需要为admin-server程序添加安全访问控制。官方已经提供了对应的支持,具体步骤如下:

  • 添加maven依赖

admin-server的登录安全采用的是spring-security来实现的,官方为我们提供了UI界面。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-server-ui-login</artifactId>
</dependency>
  • 配置用户名核密码

在配置文件application.properties中添加登录访问密码

security.user.name=user
security.user.password=123456
  • 配置WebSecurity安全拦截

最后,我们还需要在admin-server中配置security的拦截配置,同样官方也为我们提供了代码,如下

@Configuration
public static class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // Page with login form is served as /login.html and does a POST on /login
        http.formLogin().loginPage("/login.html").loginProcessingUrl("/login").permitAll();
        // The UI does a POST on /logout on logout
        http.logout().logoutUrl("/logout");
        // The ui currently doesn't support csrf
        http.csrf().disable();

        // Requests for the login page and the static assets are allowed
        http.authorizeRequests()
                .antMatchers("/login.html", "//*.css", "/img/", "/third-party/")
                .permitAll();
        // ... and any other request needs to be authorized
        http.authorizeRequests().antMatchers("/").authenticated();

        // Enable so that the clients can authenticate via HTTP basic for registering
        http.httpBasic();
    }
}

重启程序,再次访问时,就可以看到访问admin-server需要输入用户名和密码了

image

二、spring-cloud + spring-boot-admin集成

微服务盛行的今天,基于spring-boot的微服务框架spring-cloud进入大众视野,许多大公司也纷纷开始使用该框架,都在尝试适用于自己平台的组件。大家都知道spring-cloud框架程序间是通过微服务的注册发现来实现相互的感知的。
spring-boot-admin官方也为我们提供了基于spring-cloud框架的支持。下面我们逐步来实现spring-boot-admin在spring-cloud下的集成使用。

我们需要创建如下三个程序

程序名 功能说明
eureka-server spring-cloud的eureka实现的注册中心。
admin-cloud-server spring-boot-admin的服务端程序,类似与前面的admin-server。
admin-cloud-server spring-boot-admin的客户端程序,类似与前面的admin-client。

2.1 基于spring-cloud的基础搭建

2.1.1eureka-server创建和配置

我们使用spring-cloud提供的eureka组件搭建一个简单的注册中心程序。搭建非常简单。

  • 创建eureka-server程序并添加依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
  • application.properties文件配置
spring.application.name=eureka-server
server.port=8761
#配置不进行自我注册核信息拉取
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
#注册中心地址,其他程序通过次URL进行注册
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
eureka.instance.instance-id=${spring.cloud.client.ipAddress}:${server.port}
eureka.instance.prefer-ip-address=true

为了方便我们后边测试,在application.properties中可以添加如下配置来关闭掉注册中心自我保护模式以及剔除客户端的时间周期

#是否打开自我保护,如果设置为true,很容易会出现红色字体的自我保护提示,不方便测试
eureka.server.enable-self-preservation=false
#清理时间,默认是60*1000毫秒,修改短一点,保证开发时,客户端失效后,能够快速剔除客户端
eureka.server.eviction-interval-timer-in-ms=10000
  • 配置启动类

我们在启动类上添加注册中心相关注解

@SpringBootApplication
@EnableEurekaServer
public class EurekaServer {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServer.class,args);
    }
}

这样我们的注册中心就配置好了,启动主类即可。

2.1.2、admin-cloud-server创建和配置

与上一节中admin-server程序创建流程类似,我们创建spring-boot-admin的服务端程序admin-cloud-server

  • 添加maven依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-server</artifactId>
</dependency>
<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-server-ui</artifactId>
</dependency>
  • application.properties配置文件配置
spring.application.name=admin-cloud-server
server.port=80
#添加eureka注册信息
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
eureka.instance.instance-id=${spring.cloud.client.ipAddress}:${server.port}
eureka.instance.prefer-ip-address=true
management.security.enabled=false
  • 启动类AdminCloudServer配置
@SpringBootApplication
//注册到eureka
@EnableDiscoveryClient
//开启AdminServer
@EnableAdminServer
public class AdminCloudServer {
    public static void main(String[] args) {
        SpringApplication.run(AdminCloudServer.class, args);
    }
}

配置完成后启动配置,启动程序,访问http://127.0.0.1/,可以看到与上一节中admin-server相同的界面

image

2.13、admin-cloud-client创建和配置

我们创建一个名为admin-cloud-client的spring-boot-admin的客户端程序,同时它也是一个spring-cloud程序。

  • 添加maven依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

注意一定要添加spring-boot-starter-actuator

  • application.properties配置
spring.application.name=admin-cloud-client
server.port=8090
#注册中心地址
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
eureka.instance.instance-id=${spring.cloud.client.ipAddress}:${server.port}
eureka.instance.prefer-ip-address=true
#关闭安全控制
management.security.enabled=false
  • 启动类配置
@SpringBootApplication
@EnableDiscoveryClient
public class AdminCloudClient {
    public static void main(String[] args) {
        SpringApplication.run(AdminCloudClient.class,args);
    }
}

我们启动该程序,稍后刷新admin-cloud-server的管理页面,可以看到如下效果

image

可以看到,admin-cloud-client程序也出现在了管理列表中

我们查看eureka-server程序的管理页面http://127.0.0.1:8761,可以看到admin-cloud-server和admin-cloud-client都在注册中心列表中

image

这样,我们基于spring-cloud注册中心方式的spring-boot-admin管理程序就搭建好了。

小结

从原来的单纯的spring-boot版本改为当前的基于spring-cloud注册中心方式的版本非常简单,大致步骤如下:

  • 1、首先我们要添加eureka客户端支持,都需要添加spring-cloud-starter-eureka依赖
  • 2、配置文件中增加eureka注册中心地址。
  • 3、启动来添加eureka客户端注解@EnableDiscoveryClient来注册到注册中心。
    可以从上面看到,客户端不在需要任何spring-boot-admin客户端的依赖核配置,由于使用了注册中心,使用起来更加简单了。

2.2 基于spring-cloud的扩展监控集成

大家都知道spring-cloud做微服务的一个很重要的特性就是支持hystrix(断路器),解决系统雪崩还对短路情况进行了统计,并支持通过安全端点实时输出。spring-cloud已经提供了hystrix-bashbroad组件UI来动态显示单个断路器的情况,又提供了turbine组件来实现分布式时断路器的数据聚合。虽然原本都提供了UI界面,但并未进行统一集成,在生产环境中使用起来不太方便。
spring-boot-admin不仅添加了spring-cloud的支持,同时还增加了对spring-cloud扩展端点的UI支持。下面我们逐步改进程序来体验一下效果。

实现思路是这样:我们在admin-cloud-client中添加hystrix(断路器)功能支持,并创建一个定时器来让它访问一个不可达的地址。然后在admin-cloud-client中集成hystrix以及turbine监控的UI。观察是否能够达到效果。

2.2.1、admin-cloud-client改造

首先,我们增加hystrix和feign依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
</dependency>

并在启动类采用@EnableCircuitBreaker开启断路器自动装配

@SpringBootApplication
@EnableDiscoveryClient
//开启断路器装配
@EnableCircuitBreaker
//开启feign client
@EnableFeignClients
public class AdminCloudClient {
    public static void main(String[] args) {
        SpringApplication.run(AdminCloudClient.class,args);
    }
}

创建一个FeignClient,但是service-id我们配置为不存在的服务id(test-service)

@FeignClient("test-service")
public interface TestClient {
    @RequestMapping("/test")
    void test();
}

接下来,我们创建一个定时任务来调用FeignClient客户端访问test方法,方便稍后看到断路器变化代码如下

@Component
//开启定时任务
@EnableScheduling
public class HystrixJob {
    @Autowired
    private TestClient testClient;
    @Scheduled(cron = "0/20 * * * * ?")
    public void doJob(){
        try{
            testClient.test();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

2.2.2、admin-cloud-server改造

为admin-cloud-server程序添加hystrix的ui依赖

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-server-ui-hystrix</artifactId>
</dependency>

先启动admin-cloud-client再启动admin-cloud-server程序。在控制面板中找到“ADMIN-CLOUD-CLIENT”程序点击右边Details按钮,进入admin-cloud-client程序的管理界面,点击hystrix可以看到断路器相关的统计信息

image

可以看到hystix的UI面板已经集成到了spring-boot-admin中。

接下来我们集成turbine面版UI,首先我们添加turbine的ui和自动装配相关的依赖

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-server-ui-turbine</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-turbine</artifactId>
</dependency>

上面第一个依赖为我们添加了turbine聚合UI的入口,第二个依赖给程序添加了turbine相关的端点,这样程序访问当前程序才能通过访问自己访问到turbine端口
接着我们得在admin-cloud-server程序启动类上添加@EnableTurbine注解开启turbine支持,如下

@SpringBootApplication
//注册到eureka
@EnableDiscoveryClient
//开启AdminServer
@EnableAdminServer
#开启turbine
@EnableTurbine
public class AdminCloudServer {
    public static void main(String[] args) {
        SpringApplication.run(AdminCloudServer.class, args);
    }
}

最后,需要做turbine相关的配置

spring.boot.admin.turbine.clusters=default
#设置turbine端点的service-id,由于目前turbine功能已经集成到了admin-cloud-server程序中,所以这里填写的是该程序注册到注册中心的service-Id
spring.boot.admin.turbine.location=admin-cloud-server
turbine.clusterNameExpression=new String("default")
#设置需要监控的serviceId
turbine.app-config=admin-cloud-client

2.2.3、效果测试

接下来我们还是依次启动admin-cloud-client和admin-cloud-server程序。登录后admin管理页面,我们可以看到界面增加了新的Turbine入口,界面如下

image

点击该入口,可以看到一个聚合hystrix信息的turbine面板

image

这样spring-boot-admin就集成了spring-cloud中turbine组件的功能了。

注意:spirng-boot-admin服务端程序在访问hystrix相关页面的时候会报一个错误

2017-10-24 15:03:21.435  WARN 493284 --- [p-nio-80-exec-7] o.s.c.n.z.f.post.SendResponseFilter      : Error while sending response to client: java.io.IOException: 你的主机中的软件中止了一个已建立的连接。
2017-10-24 15:03:21.446  WARN 493284 --- [p-nio-80-exec-7] o.s.c.n.z.filters.post.SendErrorFilter   : Error during filtering

com.netflix.zuul.exception.ZuulException: Filter threw Exception
    at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:227) ~[zuul-core-1.3.0.jar:1.3.0]
    at com.netflix.zuul.FilterProcessor.runFilters(FilterProcessor.java:157) ~[zuul-core-1.3.0.jar:1.3.0]
    ......

官方也有人提了issue,不过这是zuul的bug,详情见github

2.3、基于MQ的hystrix(断路器)消息收集方式集成

大家都知道hystrix数据的收集是通过spring-boot-admin服务端访问hystrix端点获取的,如果在无法访问http或者我们想要减少http方式的请求时,可以使用MQ来作为消息手机通信方式。官方推荐使用RabbitMQ,所以我们需要先安装RabbitMQ。具体安装方法这里就不讲了。

2.3.1、admin-cloud-client改造

spring-cloud提供了hystri的MQ收集工具包,我们在client程序中增加如下两个依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-netflix-hystrix-stream</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>

由于采用了RabbitMQ,我们还需要在application.properties中增加MQ的连接配置

#RabbitMQ的连接配置
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

这样客户端的改造就完成了

2.3.2、admin-cloud-server改造

首先,我们在server端添加如下maven依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-turbine-amqp</artifactId>
</dependency>

该依赖会自动引入spring-cloud-starter-stream-rabbit与spring-cloud-starter-turbine-stream。

其次,我们删除掉原来的spring-cloud-starter-turbine依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-turbine</artifactId>
</dependency>

接着我们要改造启动类,使用 @EnableTurbineStream 替换 @EnableTurbine

@SpringBootApplication
//注册到eureka
@EnableDiscoveryClient
//开启AdminServer
@EnableAdminServer
//@EnableTurbine
@EnableTurbineStream
public class AdminCloudServer {
    public static void main(String[] args) {
        SpringApplication.run(AdminCloudServer.class, args);
    }
}

接着,application.properties中删除掉之前的如下配置

turbine.clusterNameExpression=new String("default")
#设置需要监控的serviceId
turbine.app-config=admin-cloud-client

除此之外,我们要配置MQ获取到数据后暴露到哪一个端口,假设我们将数据暴露在8088端口,配置如下

# 这是turbine即暴露监控数据的端口,必须跟server.port不同
turbine.stream.port=8088

最后,我们还需要将之前的spring.boot.admin.turbine.location的值admin-cloud-server改为URL的的方式,指向当前程序的8088端口,如下

spring.boot.admin.turbine.location=http://localhost:${turbine.stream.port}/

2.2.3、效果测试

注意: 如果spring.boot.admin.turbine.location不更改为url,会报如下错误,因为端点端口并未暴露到程序监听的80端口,而是暴露到了turbine.stream.port所配置的8088端口

Unable to connect to Command Metric Stream 'api/turbine/stream?cluster=default'.Error: {"isTrusted":true}

同样,我们依次启动admin-cloud-client和admin-cloud-server,在打开server端的turbine面板,我们又可以看到与之前非MQ模式的效果

image

三、其他功能集成

接下来我们简单集成核配置两个基础功能:客户端HTTP BASIC认证配置与服务端监控邮件通知

3.1、客户端HTTP BASIC认证配置

大家可以看到我们的客户程序中添加了management.security.enabled并设置其值为false,目的是关闭端点的安全访问。在生产环境中,我们的admin-client或者admin-cloud-client可能添加了安全访问可控制,这个时候访问端点就需要提供用户名和密码了。
spring-boot-admin支持客户端程序使用HTTP BASIC的安全认证,接下来我们改进一下客户端基于spring-boot-starter-security搭建的安全访问控制配置。
我们假设,admin-client或者admin-cloud-client中我们使用spring-boot-starter-security做了HTTP BASIC安全认证,配置文件中的密码配置为

security.user.name=test
security.user.password=123456

client为单纯的spring-boot程序

如果是单纯使用spring-boot构建(非spring-cloud)的程序,那么我们需要在客户端配置文件中增加如下配置

spring.boot.admin.client.metadata.user.name=${security.user.name}
spring.boot.admin.client.metadata.user.password=${security.user.password}

client为spring-cloud程序

如果使用了spring-cloud,因为我们使用的是没有spring-boot-admin-starter-client依赖的方式,而是通过eureka来获取客户端信息的,所以需要按照如下方式配置在元数据中

eureka.instance.metadata-map.user.name=${security.user.name}
eureka.instance.metadata-map.user.password=${security.user.password}

这样spring-boot-admin服务端程序就可以正常访问客户端程序了。

3.2、客户端上下线通知

spring-boot-admin作为监控管理程序,除了提供实时的程序安全数据端口UI监控外,官方还提供了spring-boot-admin客户端程序异常的通知预警功能。官网提供了八种通知方式,详情见官网,大家可以根据自己的需求集成不同的通知方式。接下来我们搭建一下使用邮件通知方式的预警功能。spring-boot-admin集成邮件通知功能与spring-boot集成邮件发送功能类似。接下来我们逐步集成改进spring-boot-admin服务端(我们以admin-cloud-server为例)。

添加maven依赖

我们在上一节中的admin-cloud-server中添加spring-boot邮件相关依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

修改properties文件配置

我们在application.properties文件中添加如下配置

#邮件通知配置
#邮件服务器地址
spring.mail.host=smtp.qq.com
#发送邮件的邮箱地址
spring.mail.username=test0@qq.com
#QQ邮箱授权码或163邮箱密码
spring.mail.password=******
#添加邮件认证相关设置
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
#需要忽略的状态改变通知,逗号分隔,例如不通知离线到上线的状态,则填写为OFFLINE:UP
#spring.boot.admin.notify.mail.ignore-changes=
#接收通知的邮箱地址,逗号分隔
spring.boot.admin.notify.mail.to=test2@qq.com
#需要抄送的邮箱地址,逗号分隔
spring.boot.admin.notify.mail.cc=test1@qq.com
#邮件发送者,大部分情况与登录名相同
spring.boot.admin.notify.mail.from=${spring.mail.username}
#邮件主题,默认是:#{application.name} (#{application.id}) is #{to.status}
spring.boot.admin.notify.mail.subject=#{application.name} (#{application.id}) is #{to.status}
#邮件内容,默认是:#{application.name} (#{application.id})\nstatus changed from #{from.status} to #{to.status}\n\n#{application.healthUrl}
spring.boot.admin.notify.mail.text=#{application.name} (#{application.id})\nstatus changed from #{from.status} to #{to.status}

测试效果

还是分别启动eureka-server、admin-cloud-server、admin-cloud-client程序。片刻之后我们重启admin-cloud-client
可以在windows任务栏的QQ弹出了admin-client-client状态变表更的邮件提示,我们进入邮箱可以看到两封邮件,效果如下:

image

image

我们点击一个邮件进去可以看到如下的默认邮件内容

image

可以看到邮件详细内容的格式与spring.boot.admin.notify.mail.text参数配置的格式相同,所以我们可以通过更改该配置的内容格式来定制我们想要的预警内容。

小结

通过spring-boot-admin集成邮件通知可以更加丰富监控程序的功能。为生产环境中的安全稳定运行又提供了一层有效的保障。

总结

spring-boot-admin为我们基于spring-boot开发的程序(包括spring-cloud)提供了安全端点的基础监控,对有异常状态(客户端状态变更为上线、下线、未知等)支持多种通知方式。为生产环境的运营维护提供了直观的UI效果。
当然对于当前复杂的生产环境来说,spring-boot-admin所支持的还是一下小部分。未来希望能够看到更多的更开放的监控功能的集成(例如zipkin),并且支持更多自定义的监控开发。

参考资料:

http://codecentric.github.io/spring-boot-admin/1.5.4/

http://www.jianshu.com/p/add65b345be7

相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
25天前
|
存储 运维 安全
Spring运维之boot项目多环境(yaml 多文件 proerties)及分组管理与开发控制
通过以上措施,可以保证Spring Boot项目的配置管理在专业水准上,并且易于维护和管理,符合搜索引擎收录标准。
39 2
|
2月前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
65 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
|
2月前
|
JSON Java Maven
实现Java Spring Boot FCM推送教程
本指南介绍了如何在Spring Boot项目中集成Firebase云消息服务(FCM),包括创建项目、添加依赖、配置服务账户密钥、编写推送服务类以及发送消息等步骤,帮助开发者快速实现推送通知功能。
94 2
|
3月前
|
XML JavaScript Java
Spring Retry 教程
Spring Retry 是 Spring 提供的用于处理方法重试的库,通过 AOP 提供声明式重试机制,不侵入业务逻辑代码。主要步骤包括:添加依赖、启用重试机制、设置重试策略(如异常类型、重试次数、延迟策略等),并可定义重试失败后的回调方法。适用于因瞬时故障导致的操作失败场景。
Spring Retry 教程
|
2月前
|
缓存 NoSQL Java
Springboot自定义注解+aop实现redis自动清除缓存功能
通过上述步骤,我们不仅实现了一个高度灵活的缓存管理机制,还保证了代码的整洁与可维护性。自定义注解与AOP的结合,让缓存清除逻辑与业务逻辑分离,便于未来的扩展和修改。这种设计模式非常适合需要频繁更新缓存的应用场景,大大提高了开发效率和系统的响应速度。
72 2
|
4月前
|
Java 数据库连接 Spring
一文讲明 Spring 的使用 【全网超详细教程】
这篇文章是一份全面的Spring框架使用教程,涵盖了从基础的项目搭建、IOC和AOP概念的介绍,到Spring的依赖注入、动态代理、事务处理等高级主题,并通过代码示例和配置文件展示了如何在实际项目中应用Spring框架的各种功能。
一文讲明 Spring 的使用 【全网超详细教程】
|
2月前
|
JSON Java Maven
实现Java Spring Boot FCM推送教程
详细介绍实现Java Spring Boot FCM推送教程
107 0
|
5月前
|
NoSQL Java 数据库连接
《滚雪球学Spring Boot》教程导航帖(更新于2024.07.16)
📚 《滚雪球学Spring Boot》是由CSDN博主bug菌创作的全面Spring Boot教程。作者是全栈开发专家,在多个技术社区如CSDN、掘金、InfoQ、51CTO等担任博客专家,并拥有超过20万的全网粉丝。该教程分为入门篇和进阶篇,每篇包含详细的教学步骤,涵盖Spring Boot的基础和高级主题。
74 1
《滚雪球学Spring Boot》教程导航帖(更新于2024.07.16)
|
4月前
|
SQL Java 数据库连接
Spring Boot联手MyBatis,打造开发利器:从入门到精通,实战教程带你飞越编程高峰!
【8月更文挑战第29天】Spring Boot与MyBatis分别是Java快速开发和持久层框架的优秀代表。本文通过整合Spring Boot与MyBatis,展示了如何在项目中添加相关依赖、配置数据源及MyBatis,并通过实战示例介绍了实体类、Mapper接口及Controller的创建过程。通过本文,你将学会如何利用这两款工具提高开发效率,实现数据的增删查改等复杂操作,为实际项目开发提供有力支持。
236 0
|
4月前
|
Java 关系型数据库 MySQL