Spring Boot Actuator監控(各個介面介紹)
Spring Boot Actuator 提供了 一些介面,向外部提供本應用程式的監控資訊。
介面分為三大類:
- 應用配置類:獲取應用程式中載入的應用配置、環境變數、自動化配置報告等與Spring Boot應用密切相關的配置類資訊。
- 度量指標類:獲取應用程式執行過程中用於監控的度量指標,比如:記憶體資訊、執行緒池資訊、HTTP請求統計等。
- 操作控制類:提供了對應用的關閉等操作類功能。
使用Spring Boot Actuator需要引入jar包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
啟動專案會看到一些對映
2018-11-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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() 2018-11-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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 2018-11-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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) 2018-11-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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() 2018-11-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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) 2018-11-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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) 2018-11-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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>) 2018-11-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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() 2018-11-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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() 2018-11-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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() 2018-11-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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() 2018-11-16 10:09:27.983 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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() 2018-11-16 10:09:27.983 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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) 2018-11-16 10:09:27.983 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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() 2018-11-16 10:09:27.983 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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) 2018-11-16 10:09:27.983 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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() 2018-11-16 10:09:27.983 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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() 2018-11-16 10:09:28.399 INFO [main]org.springframework.jmx.export.annotation.AnnotationMBeanExporter.afterSingletonsInstantiated:431 -Registering beans for JMX exposure on startup
訪問這些介面就能獲取到各項監控指標
HTTP 方法 | 路徑 | 描述 |
---|---|---|
應用配置類 |
||
GET | /autoconfig | 該端點用來獲取應用的自動化配置報告,其中包括所有自動化配置的候選項。同時還列出了每個候選項自動化配置的各個先決條件是否滿足。所以,該端點可以幫助我們方便的找到一些自動化配置為什麼沒有生效的具體原因。該報告內容將自動化配置內容分為兩部分:
|
GET | /configprops | 描述配置屬性(包含預設值)
|
GET | /beans | 描述應用程式上下文裡全部的Bean,以及它們的關係
|
GET | /env | 獲取應用所有可用的環境屬性報告。包括:環境變數、JVM屬性、應用的配置配置、命令列中的引數 |
GET | /env/{name} | 根據名稱獲取特定的環境屬性值 /env 介面還能用來獲取單個屬性的值,只需要在請求時在 /env 後加上屬性名即可。 |
GET | /info | 該端點用來返回一些應用自定義的資訊。預設情況下,該端點只會返回一個空的json內容。 我們可以在 |
GET | /mappings | 描述全部的URI路徑,以及它們和控制器(包含Actuator端點)的對映關係 羅列出應用程式釋出的全部介面
|
度量指標類(提供的報告內容則是動態變化的) |
||
GET | /metrics | 報告各種應用程式度量資訊,比如記憶體用量、HTTP請求計數、執行緒資訊、垃圾回收資訊等。
對於 |
GET | /metrics/{name} | 報告指定名稱的應用程式度量值 |
GET | /health | 報告應用程式的健康指標,這些值由HealthIndicator的實現類提供 |
GET | /dump | 獲取執行緒活動的快照。它使用java.lang.management.ThreadMXBean 的dumpAllThreads 方法來返回所有含有同步資訊的活動執行緒詳情。 |
GET | /trace | 提供基本的HTTP請求跟蹤資訊(時間戳、HTTP頭等)。 預設情況下,跟蹤資訊的儲存採用 |
操作控制類(操作控制類介面預設是關閉的,如果要使用它們的話,需要通過屬性來配置開啟。) |
||
POST | /shutdown | 關閉應用程式,要求endpoints.shutdown.enabled設定為true |
但是在實際操作的時候報錯,訪問/beans告訴我沒許可權,spring boot 1.5.8
解決辦法開啟HTTP basic認證
新增依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
application.yml 新增使用者名稱和密碼
security:
user:
name: admin #鑑權賬號
password: 123456 #鑑權密碼
basic:
enabled: true
path: /admin 鑑權路徑
management:
port: 8089 #actuator暴露介面使用的埠,為了和api介面使用的埠進行分離
context-path: /admin #actuator暴露介面的字首
security:
enabled: true #actuator是否需要安全保證
roles: SUPERUSER
這樣在啟動訪問localhost:8089/admin/beans就會出現視窗讓輸入賬號密碼然後就可以看到監控資訊了
[{"context":"application:8088:management","parent":"application:8088","beans":[{"bean":"embeddedServletContainerFactory","aliases":[],"scope":"singleton","type":"org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory","resource":"null","dependencies":[]},{"bean":"endpointWebMvcChildContextConfiguration","aliases":
各個介面示例
/autoconfig示例
positiveMatches
中返回的是條件匹配成功的自動化配置negativeMatches
中返回的是條件匹配不成功的自動化配置
{
"positiveMatches":{
"DruidDataSourceAutoConfigure":[
{
"condition":"OnClassCondition",
"message":"@ConditionalOnClass found required class 'com.alibaba.druid.pool.DruidDataSource'; @ConditionalOnMissingClass did not find unwanted class"
}
]
},
"negativeMatches":{
"DruidFilterConfiguration#commonsLogFilter":{
"notMatched":[
{
"condition":"OnPropertyCondition",
"message":"@ConditionalOnProperty (spring.datasource.druid.filter.commons-log.enabled) did not find property 'enabled'"
}
],
"matched":[
]
}
}
/beans示例
- bean:Bean的名稱
- scope:Bean的作用域
- type:Bean的Java型別
- reource:class檔案的具體路徑
- dependencies:依賴的Bean名稱
[
{
"context":"application:8088",
"parent":null,
"beans":[
{
"bean":"redisConfig",
"aliases":[
],
"scope":"singleton",
"type":"com.sid.common.RedisConfig$$EnhancerBySpringCGLIB$$51a9e057",
"resource":"file [D:/gitrep/springboot/target/classes/com/sid/common/RedisConfig.class]",
"dependencies":[
]
}
}
]
/configprops示例
prefix
屬性代表了屬性的配置字首properties
代表了各個屬性的名稱和值
{"spring.redis-org.springframework.boot.autoconfigure.data.redis.RedisProperties":{
"prefix":"spring.redis",
"properties":{
"sentinel":null,
"cluster":null,
"database":0,
"password":"******",
"port":6379,
"host":"192.168.2.240",
"pool":{
"maxIdle":70,
"minIdle":0,
"maxActive":70,
"maxWait":3000
},
"ssl":false,
"url":null,
"timeout":0
}
}
}
/env示例
{
"profiles":[
],
"server.ports":{
"local.management.port":8089,
"local.server.port":8088
},
"servletContextInitParams":{
},
"systemProperties":Object{...},
"systemEnvironment":Object{...},
"applicationConfig: [classpath:/application.yml]":Object{...}
}
/mappings示例
bean
屬性標識了該對映關係的請求處理器method
屬性標識了該對映關係的具體處理類和處理函式
{
"/webjars/**":{
"bean":"resourceHandlerMapping"
},
"/**":{
"bean":"resourceHandlerMapping"
},
"/**/favicon.ico":{
"bean":"faviconHandlerMapping"
},
"{[/user/add]}":{
"bean":"requestMappingHandlerMapping",
"method":"public com.sid.model.User com.sid.controller.UserController.addUser(com.sid.model.User)"
},
"{[/user/delete]}":{
"bean":"requestMappingHandlerMapping",
"method":"public int com.sid.controller.UserController.deleteUser(java.lang.String)"
},
"{[/user/selectAll]}":{
"bean":"requestMappingHandlerMapping",
"method":"public com.github.pagehelper.PageInfo<com.sid.model.User> com.sid.controller.UserController.selectAll(int,int)"
},
"{[/error]}":{
"bean":"requestMappingHandlerMapping",
"method":"public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)"
},
"{[/error],produces=[text/html]}":{
"bean":"requestMappingHandlerMapping",
"method":"public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)"
}
}
/info示例
/metrics示例
- 系統資訊:包括處理器數量
processors
、執行時間uptime
和instance.uptime
、系統平均負載systemload.average
。 mem.*
:記憶體概要資訊,包括分配給應用的總記憶體數量以及當前空閒的記憶體數量。這些資訊來自java.lang.Runtime
。heap.*
:堆記憶體使用情況。這些資訊來自java.lang.management.MemoryMXBean
介面中getHeapMemoryUsage
方法獲取的java.lang.management.MemoryUsage
。nonheap.*
:非堆記憶體使用情況。這些資訊來自java.lang.management.MemoryMXBean
介面中getNonHeapMemoryUsage
方法獲取的java.lang.management.MemoryUsage
。threads.*
:執行緒使用情況,包括執行緒數、守護執行緒數(daemon)、執行緒峰值(peak)等,這些資料均來自java.lang.management.ThreadMXBean
。classes.*
:應用載入和解除安裝的類統計。這些資料均來自java.lang.management.ClassLoadingMXBean
。gc.*
:垃圾收集器的詳細資訊,包括垃圾回收次數gc.ps_scavenge.count
、垃圾回收消耗時間gc.ps_scavenge.time
、標記-清除演算法的次數gc.ps_marksweep.count
、標記-清除演算法的消耗時間gc.ps_marksweep.time
。這些資料均來自java.lang.management.GarbageCollectorMXBean
。httpsessions.*
:Tomcat容器的會話使用情況。包括最大會話數httpsessions.max
和活躍會話數httpsessions.active
。該度量指標資訊僅在引入了嵌入式Tomcat作為應用容器的時候才會提供。gauge.*
:HTTP請求的效能指標之一,它主要用來反映一個絕對數值。比如上面示例中的gauge.response.hello: 5
,它表示上一次hello
請求的延遲時間為5毫秒。counter.*
:HTTP請求的效能指標之一,它主要作為計數器來使用,記錄了增加量和減少量。如上示例中counter.status.200.hello: 11
,它代表了hello
請求返回200
狀態的次數為11。
對於gauge.*
和counter.*
的統計,這裡有一個特殊的內容請求star-star
,它代表了對靜態資源的訪問。這兩類度量指標非常有用,我們不僅可以使用它預設的統計指標,還可以在程式中輕鬆的增加自定義統計值
{
"mem":705295,
"mem.free":494933,
"processors":4,
"instance.uptime":1944236,
"uptime":1950389,
"systemload.average":-1,
"heap.committed":634880,
"heap.init":262144,
"heap.used":139946,
"heap":3702784,
"nonheap.committed":71936,
"nonheap.init":2496,
"nonheap.used":70417,
"nonheap":0,
"threads.peak":62,
"threads.daemon":45,
"threads.totalStarted":85,
"threads":48,
"classes":9363,
"classes.loaded":9364,
"classes.unloaded":1,
"gc.ps_scavenge.count":8,
"gc.ps_scavenge.time":129,
"gc.ps_marksweep.count":2,
"gc.ps_marksweep.time":106,
"httpsessions.max":-1,
"httpsessions.active":0,
"gauge.response.user.selectAll":302,
"counter.status.500.user.selectAll":1
}
對 /metrics 介面提供的資訊進行簡單分類如下表:
分類 | 字首 | 報告內容 |
---|---|---|
垃圾收集器 | gc.* | 已經發生過的垃圾收集次數,以及垃圾收集所耗費的時間,適用於標記-清理垃圾收集器和並行垃圾收集器(資料來源自java.lang.management. GarbageCollectorMXBean) |
記憶體 | mem.* | 分配給應用程式的記憶體數量和空閒的記憶體數量(資料來源自java.lang. Runtime) |
堆 | heap.* | 當前記憶體用量(資料來源自java.lang.management.MemoryUsage) |
類載入器 | classes.* | JVM類載入器載入與解除安裝的類的數量(資料來源自java.lang. management.ClassLoadingMXBean) |
系統 | processors、instance.uptime、uptime、systemload.average | 系統資訊,例如處理器數量(資料來源自java.lang.Runtime)、執行時間(資料來源自java.lang.management.RuntimeMXBean)、平均負載(資料來源自java.lang.management.OperatingSystemMXBean) |
執行緒池 | thread.* | 執行緒、守護執行緒的數量,以及JVM啟動後的執行緒數量峰值(資料來源自 java.lang .management.ThreadMXBean) |
資料來源 | datasource.* | 資料來源連線的數量(源自資料來源的元資料,僅當Spring應用程式上下文裡存在 DataSource Bean 的時候才會有這個資訊) |
Tomcat 會話 | httpsessions.* | Tomcat的活躍會話數和最大會話數(資料來源自嵌入式Tomcat的Bean,僅在使用嵌入式Tomcat伺服器執行應用程式時才有這個資訊) |
HTTP | counter.status.、gauge.response. | 多種應用程式服務HTTP請求的度量值與計數器 |
這裡的一些度量值,比如資料來源和Tomcat會話,僅在應用程式中執行特定元件時才有資料。
HTTP的計數器和度量值說明:counter.status 後的值是HTTP狀態碼,隨後是所請求的路徑。
比如:"counter.status.500.user.selectAll":1 表明/user/selectAll介面返回 500狀態碼的次數為1。
HTTP響應的度量值說明:gauge.response,後是對應的路徑。
度量值是以毫秒為單位的時間,表示最近處理該路徑請求的耗時。
比如:"gauge.response.user.selectAll":302 表明/user/selectAll介面最近一次請求耗時302毫秒。
這裡還有幾個特殊的值需要注意。root路徑指向的是根路徑或/。
star-star代表了那些Spring 認為是靜態資源的路徑,包括圖片、JavaScript和樣式表,其中還包含了那些找不到的資源。
這就是經常會看到 counter.status.404.star-star,這是返回了HTTP 404 (NOT FOUND) 狀態的請求數。
/health示例
{
"status":"UP",
"diskSpace":{
"status":"UP",
"total":154151153664,
"free":147728592896,
"threshold":10485760
},
"redis":{
"status":"UP",
"version":"3.2.10"
},
"db":{
"status":"UP",
"database":"MySQL",
"hello":1
}
}
/dump示例
{
"threadName":"http-nio-8088-Acceptor-0",
"threadId":80,
"blockedTime":-1,
"blockedCount":10,
"waitedTime":-1,
"waitedCount":0,
"lockName":null,
"lockOwnerId":-1,
"lockOwnerName":null,
"inNative":true,
"suspended":false,
"threadState":"RUNNABLE",
"stackTrace":[
{
"methodName":"accept0",
"fileName":"ServerSocketChannelImpl.java",
"lineNumber":-2,
"className":"sun.nio.ch.ServerSocketChannelImpl",
"nativeMethod":true
},
{
"methodName":"accept",
"fileName":"ServerSocketChannelImpl.java",
"lineNumber":422,
"className":"sun.nio.ch.ServerSocketChannelImpl",
"nativeMethod":false
},
{
"methodName":"accept",
"fileName":"ServerSocketChannelImpl.java",
"lineNumber":250,
"className":"sun.nio.ch.ServerSocketChannelImpl",
"nativeMethod":false
},
{
"methodName":"run",
"fileName":"NioEndpoint.java",
"lineNumber":455,
"className":"org.apache.tomcat.util.net.NioEndpoint$Acceptor",
"nativeMethod":false
},
{
"methodName":"run",
"fileName":"Thread.java",
"lineNumber":748,
"className":"java.lang.Thread",
"nativeMethod":false
}
],
"lockedMonitors":[
{
"className":"java.lang.Object",
"identityHashCode":1089871804,
"lockedStackDepth":2,
"lockedStackFrame":{
"methodName":"accept",
"fileName":"ServerSocketChannelImpl.java",
"lineNumber":250,
"className":"sun.nio.ch.ServerSocketChannelImpl",
"nativeMethod":false
}
}
],
"lockedSynchronizers":[
],
"lockInfo":null
}
/trace示例
{
"timestamp":1542336977009,
"info":{
"method":"POST",
"path":"/sid/user/selectAll",
"headers":{
"request":{
"cache-control":"no-cache",
"postman-token":"5c8f7b21-0d94-47f7-a3bd-93d3c2585792",
"user-agent":"PostmanRuntime/7.4.0",
"accept":"*/*",
"host":"localhost:8088",
"accept-encoding":"gzip, deflate",
"content-type":"multipart/form-data; boundary=--------------------------397337630825961403061295",
"content-length":"271",
"connection":"keep-alive"
},
"response":{
"X-Application-Context":"application:8088",
"status":"500"
}
},
"timeTaken":"260"
}
}