在Spring Boot的眾多Starter POMs中有一個特殊的模塊,它不同于其他模塊那樣大多用于開發(fā)業(yè)務(wù)功能或是連接一些其他外部資源。它完全是一個用于暴露自身信息的模塊,所以很明顯,它的主要作用是用于監(jiān)控與管理,它就是:spring-boot-starter-actuator
。
spring-boot-starter-actuator
模塊的實現(xiàn)對于實施微服務(wù)的中小團隊來說,可以有效地減少監(jiān)控系統(tǒng)在采集應(yīng)用指標(biāo)時的開發(fā)量。當(dāng)然,它也并不是萬能的,有時候我們也需要對其做一些簡單的擴展來幫助我們實現(xiàn)自身系統(tǒng)個性化的監(jiān)控需求。下面,在本文中,我們將詳解的介紹一些關(guān)于spring-boot-starter-actuator
模塊的內(nèi)容,包括它的原生提供的端點以及一些常用的擴展和配置方式。
初識Actuator
下面,我們可以通過對快速入門中實現(xiàn)的Spring Boot應(yīng)用增加spring-boot-starter-actuator
模塊功能,來對它有一個直觀的認識。
在現(xiàn)有的Spring Boot應(yīng)用中引入該模塊非常簡單,只需要在pom.xml
的dependencies節(jié)點中,新增spring-boot-starter-actuator的依賴即可,具體如下:
1
2
3
4
|
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> |
通過增加該依賴之后,重新啟動應(yīng)用。此時,我們可以在控制臺中看到如下圖所示的輸出:
上圖顯示了一批端點定義,這些端點并非我們自己在程序中創(chuàng)建,而是由spring-boot-starter-actuator
模塊根據(jù)應(yīng)用依賴和配置自動創(chuàng)建出來的監(jiān)控和管理端點。通過這些端點,我們可以實時的獲取應(yīng)用的各項監(jiān)控指標(biāo),比如:訪問/health端點,我們可以獲得如下返回的應(yīng)用健康信息:
1
2
3
4
5
6
7
8
9
|
{ "status" : "UP" , "diskSpace" : { "status" : "UP" , "total" : 491270434816 , "free" : 383870214144 , "threshold" : 10485760 } } |
原生端點
通過在快速入門示例中添加spring-boot-starter-actuator
模塊,我們已經(jīng)對它有了一個初步的認識。接下來,我們詳細介紹一下spring-boot-starter-actuator
模塊中已經(jīng)實現(xiàn)的一些原生端點。如果根據(jù)端點的作用來說,我們可以原生端點分為三大類:
- 應(yīng)用配置類:獲取應(yīng)用程序中加載的應(yīng)用配置、環(huán)境變量、自動化配置報告等與Spring Boot應(yīng)用密切相關(guān)的配置類信息。
- 度量指標(biāo)類:獲取應(yīng)用程序運行過程中用于監(jiān)控的度量指標(biāo),比如:內(nèi)存信息、線程池信息、HTTP請求統(tǒng)計等。
- 操作控制類:提供了對應(yīng)用的關(guān)閉等操作類功能。
下面我們來詳細了解一下這三類端點都分別可以為我們提供怎么樣的有用信息和強大功能,以及我們?nèi)绾稳U展和配置它們。
應(yīng)用配置類
由于Spring Boot為了改善傳統(tǒng)Spring應(yīng)用繁雜的配置內(nèi)容,采用了包掃描和自動化配置的機制來加載原本集中于xml文件中的各項內(nèi)容。雖然這樣的做法,讓我們的代碼變得非常簡潔,但是整個應(yīng)用的實例創(chuàng)建和依賴關(guān)系等信息都被離散到了各個配置類的注解上,這使得我們分析整個應(yīng)用中資源和實例的各種關(guān)系變得非常的困難。而這類端點就可以幫助我們輕松的獲取一系列關(guān)于Spring 應(yīng)用配置內(nèi)容的詳細報告,比如:自動化配置的報告、Bean創(chuàng)建的報告、環(huán)境屬性的報告等。
- /autoconfig:該端點用來獲取應(yīng)用的自動化配置報告,其中包括所有自動化配置的候選項。同時還列出了每個候選項自動化配置的各個先決條件是否滿足。所以,該端點可以幫助我們方便的找到一些自動化配置為什么沒有生效的具體原因。該報告內(nèi)容將自動化配置內(nèi)容分為兩部分:
- positiveMatches中返回的是條件匹配成功的自動化配置
- negativeMatches中返回的是條件匹配不成功的自動化配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
{ "positiveMatches" : { // 條件匹配成功的 "EndpointWebMvcAutoConfiguration" : [ { "condition" : "OnClassCondition" , "message" : "@ConditionalOnClass classes found: javax.servlet.Servlet,org.springframework.web.servlet.DispatcherServlet" }, { "condition" : "OnWebApplicationCondition" , "message" : "found web application StandardServletEnvironment" } ], ... }, "negativeMatches" : { // 條件不匹配成功的 "HealthIndicatorAutoConfiguration.DataSourcesHealthIndicatorConfiguration" : [ { "condition" : "OnClassCondition" , "message" : "required @ConditionalOnClass classes not found: org.springframework.jdbc.core.JdbcTemplate" } ], ... } } |
從如上示例中我們可以看到,每個自動化配置候選項中都有一系列的條件,比如上面沒有成功匹配的HealthIndicatorAutoConfiguration.DataSourcesHealthIndicatorConfiguration
配置,它的先決條件就是需要在工程中包含org.springframework.jdbc.core.JdbcTemplate
類,由于我們沒有引入相關(guān)的依賴,它就不會執(zhí)行自動化配置內(nèi)容。所以,當(dāng)我們發(fā)現(xiàn)有一些期望的配置沒有生效時,就可以通過該端點來查看沒有生效的具體原因。
- /beans:該端點用來獲取應(yīng)用上下文中創(chuàng)建的所有Bean。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
[ { "context" : "hello:dev:8881" , "parent" : null , "beans" : [ { "bean" : "org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration$DispatcherServletConfiguration" , "scope" : "singleton" , "type" : "org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration$DispatcherServletConfiguration$$EnhancerBySpringCGLIB$$3440282b" , "resource" : "null" , "dependencies" : [ "serverProperties" , "spring.mvc.CONFIGURATION_PROPERTIES" , "multipartConfigElement" ] }, { "bean" : "dispatcherServlet" , "scope" : "singleton" , "type" : "org.springframework.web.servlet.DispatcherServlet" , "resource" : "class path resource [org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfiguration$DispatcherServletConfiguration.class]" , "dependencies" : [] } ] } ] |
如上示例中,我們可以看到在每個bean中都包含了下面這幾個信息:
- bean:Bean的名稱
- scope:Bean的作用域
- type:Bean的Java類型
- reource:class文件的具體路徑
- dependencies:依賴的Bean名稱
/configprops:該端點用來獲取應(yīng)用中配置的屬性信息報告。從下面該端點返回示例的片段中,我們看到返回了關(guān)于該短信的配置信息,prefix屬性代表了屬性的配置前綴,properties
代表了各個屬性的名稱和值。所以,我們可以通過該報告來看到各個屬性的配置路徑,比如我們要關(guān)閉該端點,就可以通過使用endpoints.configprops.enabled=false
來完成設(shè)置。
1
2
3
4
5
6
7
8
9
10
11
|
{ "configurationPropertiesReportEndpoint" : { "prefix" : "endpoints.configprops" , "properties" : { "id" : "configprops" , "sensitive" : true , "enabled" : true } }, ... } |
/env:該端點與/configprops
不同,它用來獲取應(yīng)用所有可用的環(huán)境屬性報告。包括:環(huán)境變量、JVM屬性、應(yīng)用的配置配置、命令行中的參數(shù)。從下面該端點返回的示例片段中,我們可以看到它不僅返回了應(yīng)用的配置屬性,還返回了系統(tǒng)屬性、環(huán)境變量等豐富的配置信息,其中也包括了應(yīng)用還沒有沒有使用的配置。所以它可以幫助我們方便地看到當(dāng)前應(yīng)用可以加載的配置信息,并配合@ConfigurationProperties
注解將它們引入到我們的應(yīng)用程序中來進行使用。另外,為了配置屬性的安全,對于一些類似密碼等敏感信息,該端點都會進行隱私保護,但是我們需要讓屬性名中包含:password、secret、key這些關(guān)鍵詞,這樣該端點在返回它們的時候會使用*來替代實際的屬性值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
{ "profiles" : [ "dev" ], "server.ports" : { "local.server.port" : 8881 }, "servletContextInitParams" : { }, "systemProperties" : { "idea.version" : "2016.1.3" , "java.runtime.name" : "Java(TM) SE Runtime Environment" , "sun.boot.library.path" : "C:\\Program Files\\Java\\jdk1.8.0_91\\jre\\bin" , "java.vm.version" : "25.91-b15" , "java.vm.vendor" : "Oracle Corporation" , ... }, "systemEnvironment" : { "configsetroot" : "C:\\WINDOWS\\ConfigSetRoot" , "RABBITMQ_BASE" : "E:\\tools\\rabbitmq" , ... }, "applicationConfig: [classpath:/application-dev.properties]" : { "server.port" : "8881" }, "applicationConfig: [classpath:/application.properties]" : { "server.port" : "8885" , "spring.profiles.active" : "dev" , "info.app.name" : "spring-boot-hello" , "info.app.version" : "v1.0.0" , "spring.application.name" : "hello" } } |
/mappings:該端點用來返回所有Spring MVC的控制器映射關(guān)系報告。從下面的示例片段中,我們可以看該報告的信息與我們在啟用Spring MVC的Web應(yīng)用時輸出的日志信息類似,其中bean
屬性標(biāo)識了該映射關(guān)系的請求處理器,method
屬性標(biāo)識了該映射關(guān)系的具體處理類和處理函數(shù)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
{ "/webjars/**" : { "bean" : "resourceHandlerMapping" }, "/**" : { "bean" : "resourceHandlerMapping" }, "/**/favicon.ico" : { "bean" : "faviconHandlerMapping" }, "{[/hello]}" : { "bean" : "requestMappingHandlerMapping" , "method" : "public java.lang.String com.didispace.web.HelloController.index()" }, "{[/mappings || /mappings.json],methods=[GET],produces=[application/json]}" : { "bean" : "endpointHandlerMapping" , "method" : "public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()" }, ... } |
/info:該端點用來返回一些應(yīng)用自定義的信息。默認情況下,該端點只會返回一個空的json內(nèi)容。我們可以在application.properties
配置文件中通過info
前綴來設(shè)置一些屬性,比如下面這樣:
1
2
|
info.app.name=spring-boot-hello info.app.version=v1. 0.0 |
再訪問/info端點,我們可以得到下面的返回報告,其中就包含了上面我們在應(yīng)用自定義的兩個參數(shù)。
1
2
3
4
5
6
|
{ "app" : { "name" : "spring-boot-hello" , "version" : "v1.0.0" } } |
度量指標(biāo)類
上面我們所介紹的應(yīng)用配置類端點所提供的信息報告在應(yīng)用啟動的時候都已經(jīng)基本確定了其返回內(nèi)容,可以說是一個靜態(tài)報告。而度量指標(biāo)類端點提供的報告內(nèi)容則是動態(tài)變化的,這些端點提供了應(yīng)用程序在運行過程中的一些快照信息,比如:內(nèi)存使用情況、HTTP請求統(tǒng)計、外部資源指標(biāo)等。這些端點對于我們構(gòu)建微服務(wù)架構(gòu)中的監(jiān)控系統(tǒng)非常有幫助,由于Spring Boot應(yīng)用自身實現(xiàn)了這些端點,所以我們可以很方便地利用它們來收集我們想要的信息,以制定出各種自動化策略。下面,我們就來分別看看這些強大的端點功能。
/metrics:該端點用來返回當(dāng)前應(yīng)用的各類重要度量指標(biāo),比如:內(nèi)存信息、線程信息、垃圾回收信息等。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
{ "mem" : 541305 , "mem.free" : 317864 , "processors" : 8 , "instance.uptime" : 33376471 , "uptime" : 33385352 , "systemload.average" : - 1 , "heap.committed" : 476672 , "heap.init" : 262144 , "heap.used" : 158807 , "heap" : 3701248 , "nonheap.committed" : 65856 , "nonheap.init" : 2496 , "nonheap.used" : 64633 , "nonheap" : 0 , "threads.peak" : 22 , "threads.daemon" : 20 , "threads.totalStarted" : 26 , "threads" : 22 , "classes" : 7669 , "classes.loaded" : 7669 , "classes.unloaded" : 0 , "gc.ps_scavenge.count" : 7 , "gc.ps_scavenge.time" : 118 , "gc.ps_marksweep.count" : 2 , "gc.ps_marksweep.time" : 234 , "httpsessions.max" : - 1 , "httpsessions.active" : 0 , "gauge.response.beans" : 55 , "gauge.response.env" : 10 , "gauge.response.hello" : 5 , "gauge.response.metrics" : 4 , "gauge.response.configprops" : 153 , "gauge.response.star-star" : 5 , "counter.status.200.beans" : 1 , "counter.status.200.metrics" : 3 , "counter.status.200.configprops" : 1 , "counter.status.404.star-star" : 2 , "counter.status.200.hello" : 11 , "counter.status.200.env" : 1 } |
從上面的示例中,我們看到有這些重要的度量值:
- 系統(tǒng)信息:包括處理器數(shù)量processors、運行時間uptime和instance.uptime、系統(tǒng)平均負載systemload.average。
- mem.*:內(nèi)存概要信息,包括分配給應(yīng)用的總內(nèi)存數(shù)量以及當(dāng)前空閑的內(nèi)存數(shù)量。這些信息來自java.lang.Runtime。
- heap.*:堆內(nèi)存使用情況。這些信息來自java.lang.management.MemoryMXBean接口中g(shù)etHeapMemoryUsage方法獲取的java.lang.management.MemoryUsage。
- nonheap.*:非堆內(nèi)存使用情況。這些信息來自java.lang.management.MemoryMXBean接口中g(shù)etNonHeapMemoryUsage方法獲取的java.lang.management.MemoryUsage。
- threads.*:線程使用情況,包括線程數(shù)、守護線程數(shù)(daemon)、線程峰值(peak)等,這些數(shù)據(jù)均來自java.lang.management.ThreadMXBean。
- classes.*:應(yīng)用加載和卸載的類統(tǒng)計。這些數(shù)據(jù)均來自java.lang.management.ClassLoadingMXBean。
- gc.*:垃圾收集器的詳細信息,包括垃圾回收次數(shù)gc.ps_scavenge.count、垃圾回收消耗時間gc.ps_scavenge.time、標(biāo)記-清除算法的次數(shù)gc.ps_marksweep.count、標(biāo)記-清除算法的消耗時間gc.ps_marksweep.time。這些數(shù)據(jù)均來自java.lang.management.GarbageCollectorMXBean。
- httpsessions.*:Tomcat容器的會話使用情況。包括最大會話數(shù)httpsessions.max和活躍會話數(shù)httpsessions.active。該度量指標(biāo)信息僅在引入了嵌入式Tomcat作為應(yīng)用容器的時候才會提供。
- gauge.*:HTTP請求的性能指標(biāo)之一,它主要用來反映一個絕對數(shù)值。比如上面示例中的gauge.response.hello: 5,它表示上一次hello請求的延遲時間為5毫秒。
- counter.*:HTTP請求的性能指標(biāo)之一,它主要作為計數(shù)器來使用,記錄了增加量和減少量。如上示例中counter.status.200.hello: 11,它代表了hello請求返回200狀態(tài)的次數(shù)為11。
對于gauge.*
和counter.*
的統(tǒng)計,這里有一個特殊的內(nèi)容請求star-star,它代表了對靜態(tài)資源的訪問。這兩類度量指標(biāo)非常有用,我們不僅可以使用它默認的統(tǒng)計指標(biāo),還可以在程序中輕松的增加自定義統(tǒng)計值。只需要通過注入org.springframework.boot.actuate.metrics.CounterService和org.springframework.boot.actuate.metrics.GaugeService
來實現(xiàn)自定義的統(tǒng)計指標(biāo)信息。比如:我們可以像下面這樣自定義實現(xiàn)對hello接口的訪問次數(shù)統(tǒng)計。
1
2
3
4
5
6
7
8
9
10
|
@RestController public class HelloController { @Autowired private CounterService counterService; @RequestMapping ( "/hello" ) public String greet() { counterService.increment( "didispace.hello.count" ); return "" ; } } |
/metrics端點可以提供應(yīng)用運行狀態(tài)的完整度量指標(biāo)報告,這項功能非常的實用,但是對于監(jiān)控系統(tǒng)中的各項監(jiān)控功能,它們的監(jiān)控內(nèi)容、數(shù)據(jù)收集頻率都有所不同,如果我們每次都通過全量獲取報告的方式來收集,略顯粗暴。所以,我們還可以通過/metrics/{name}接口來更細粒度的獲取度量信息,比如我們可以通過訪問/metrics/mem.free來獲取當(dāng)前可用內(nèi)存數(shù)量。
/health:該端點在一開始的示例中我們已經(jīng)使用過了,它用來獲取應(yīng)用的各類健康指標(biāo)信息。在spring-boot-starter-actuator模塊中自帶實現(xiàn)了一些常用資源的健康指標(biāo)檢測器。這些檢測器都通過HealthIndicator
接口實現(xiàn),并且會根據(jù)依賴關(guān)系的引入實現(xiàn)自動化裝配,比如用于檢測磁盤的DiskSpaceHealthIndicator
、檢測DataSource連接是否可用的DataSourceHealthIndicator
等。有時候,我們可能還會用到一些Spring Boot的Starter POMs中還沒有封裝的產(chǎn)品來進行開發(fā),比如:當(dāng)使用RocketMQ作為消息代理時,由于沒有自動化配置的檢測器,所以我們需要自己來實現(xiàn)一個用來采集健康信息的檢測器。比如,我們可以在Spring Boot的應(yīng)用中,為org.springframework.boot.actuate.health.HealthIndicator
接口實現(xiàn)一個對RocketMQ的檢測器類:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@Component public class RocketMQHealthIndicator implements HealthIndicator { @Override public Health health() { int errorCode = check(); if (errorCode != 0 ) { return Health.down().withDetail( "Error Code" , errorCode).build(); } return Health.up().build(); } private int check() { // 對監(jiān)控對象的檢測操作 } } |
通過重寫health()函數(shù)來實現(xiàn)健康檢查,返回的Heath對象中,共有兩項內(nèi)容,一個是狀態(tài)信息,除了該示例中的UP與DOWN之外,還有UNKNOWN和OUT_OF_SERVICE,可以根據(jù)需要來實現(xiàn)返回;還有一個詳細信息,采用Map的方式存儲,在這里通過withDetail函數(shù),注入了一個Error Code信息,我們也可以填入一下其他信息,比如,檢測對象的IP地址、端口等。重新啟動應(yīng)用,并訪問/health接口,我們在返回的JSON字符串中,將會包含了如下信息:
1
2
3
|
"rocketMQ" : { "status" : "UP" } |
/dump:該端點用來暴露程序運行中的線程信息。它使用java.lang.management.ThreadMXBean的dumpAllThreads
方法來返回所有含有同步信息的活動線程詳情。
/trace:該端點用來返回基本的HTTP跟蹤信息。默認情況下,跟蹤信息的存儲采用org.springframework.boot.actuate.trace.InMemoryTraceRepository
實現(xiàn)的內(nèi)存方式,始終保留最近的100條請求記錄。它記錄的內(nèi)容格式如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
[ { "timestamp" : 1482570022463 , "info" : { "method" : "GET" , "path" : "/metrics/mem" , "headers" : { "request" : { "host" : "localhost:8881" , "connection" : "keep-alive" , "cache-control" : "no-cache" , "user-agent" : "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36" , "postman-token" : "9817ea4d-ad9d-b2fc-7685-9dff1a1bc193" , "accept" : "*/*" , "accept-encoding" : "gzip, deflate, sdch" , "accept-language" : "zh-CN,zh;q=0.8" }, "response" : { "X-Application-Context" : "hello:dev:8881" , "Content-Type" : "application/json;charset=UTF-8" , "Transfer-Encoding" : "chunked" , "Date" : "Sat, 24 Dec 2016 09:00:22 GMT" , "status" : "200" } } } }, ... ] |
操作控制類
仔細的讀者可能會發(fā)現(xiàn),我們在“初識Actuator”時運行示例的控制臺中輸出的所有監(jiān)控端點,已經(jīng)在介紹應(yīng)用配置類端點和度量指標(biāo)類端點時都講解完了。那么還有哪些是操作控制類端點呢?實際上,由于之前介紹的所有端點都是用來反映應(yīng)用自身的屬性或是運行中的狀態(tài),相對于操作控制類端點沒有那么敏感,所以他們默認都是啟用的。而操作控制類端點擁有更強大的控制能力,如果要使用它們的話,需要通過屬性來配置開啟。
在原生端點中,只提供了一個用來關(guān)閉應(yīng)用的端點:/shutdown。我們可以通過如下配置開啟它:
1
|
endpoints.shutdown.enabled= true |
在配置了上述屬性之后,只需要訪問該應(yīng)用的/shutdown端點就能實現(xiàn)關(guān)閉該應(yīng)用的遠程操作。由于開放關(guān)閉應(yīng)用的操作本身是一件非常危險的事,所以真正在線上使用的時候,我們需要對其加入一定的保護機制,比如:定制Actuator的端點路徑、整合Spring Security進行安全校驗等。
以上所述是小編給大家介紹的Spring Boot Actuator監(jiān)控端點小結(jié),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對服務(wù)器之家網(wǎng)站的支持!
原文鏈接:http://blog.didispace.com/spring-boot-actuator-1/