spring-boot-admin基礎搭建教程

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,可以看到簡單的界面效果,由于目前沒有客戶端程序所以列表中沒有記錄

接下來我們將之前的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界面中看到了

點擊Details按鈕,可以看到更多程序的信息,例如

從圖中我們可以看到內存使用的情況,這些數據都是通過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", "http://*.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需要輸入用戶名和密碼了

登錄效果圖

二、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相同的界面

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的管理頁面,可以看到如下效果

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

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

這樣,我們基于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可以看到斷路器相關的統計信息

可以看到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入口,界面如下

點擊該入口,可以看到一個聚合hystrix信息的turbine面板

這樣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模式的效果

三、其他功能集成

接下來我們簡單集成核配置兩個基礎功能:客戶端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.png

可以看到郵件詳細內容的格式與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.lxweimin.com/p/add65b345be7

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,048評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,414評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,169評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,722評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,465評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,823評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,813評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,000評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,554評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,295評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,513評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,035評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,722評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,125評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,430評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,237評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,482評論 2 379

推薦閱讀更多精彩內容