微服務的特色決定了功能模塊的部署是分佈式的,大部分功能模塊都是運行在不一樣的機器上,彼此經過服務調用進行交互,先後臺的業務流會通過不少個微服務的處理和傳遞,出現了異常如何快速定位是哪一個環節出現了問題?html
在這種框架下,微服務的監控顯得尤其重要。本文主要結合Spring Boot Actuator,跟你們一塊兒分享微服務Spring Boot Actuator的常見用法,方便咱們在平常中對咱們的微服務進行監控治理。java
Spring Boot使用「習慣優於配置的理念」,採用包掃描和自動化配置的機制來加載依賴jar中的Spring bean,不須要任何Xml配置,就能夠實現Spring的全部配置。雖然這樣作能讓咱們的代碼變得很是簡潔,可是整個應用的實例建立和依賴關係等信息都被離散到了各個配置類的註解上,這使得咱們分析整個應用中資源和實例的各類關係變得很是的困難。web
Actuator是Spring Boot提供的對應用系統的自省和監控的集成功能,能夠查看應用配置的詳細信息,例如自動化配置信息、建立的Spring beans以及一些環境屬性等。spring
Actuator監控只須要添加如下依賴就能夠完成數據庫
<dependencies> <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> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> </dependencies>
爲了保證actuator暴露的監控接口的安全性,須要添加安全控制的依賴spring-boot-start-security依賴,訪問應用監控端點時,都須要輸入驗證信息。Security依賴,能夠選擇不加,不進行安全管理,但不建議這麼作。apache
Actuator監控分紅兩類:原生端點和用戶自定義端點;自定義端點主要是指擴展性,用戶能夠根據本身的實際應用,定義一些比較關心的指標,在運行期進行監控。後端
原生端點是在應用程序裏提供衆多 Web 接口,經過它們瞭解應用程序運行時的內部情況。原生端點又能夠分紅三類:瀏覽器
Actuator 提供了 13 個接口,具體以下表所示。tomcat
HTTP 方法 | 路徑 | 描述 |
---|---|---|
GET | /autoconfig | 提供了一份自動配置報告,記錄哪些自動配置條件經過了,哪些沒經過 |
GET | /configprops | 描述配置屬性(包含默認值)如何注入Bean |
GET | /beans | 描述應用程序上下文裏所有的Bean,以及它們的關係 |
GET | /dump | 獲取線程活動的快照 |
GET | /env | 獲取所有環境屬性 |
GET | /env/{name} | 根據名稱獲取特定的環境屬性值 |
GET | /health | 報告應用程序的健康指標,這些值由HealthIndicator的實現類提供 |
GET | /info | 獲取應用程序的定製信息,這些信息由info打頭的屬性提供 |
GET | /mappings | 描述所有的URI路徑,以及它們和控制器(包含Actuator端點)的映射關係 |
GET | /metrics | 報告各類應用程序度量信息,好比內存用量和HTTP請求計數 |
GET | /metrics/{name} | 報告指定名稱的應用程序度量值 |
POST | /shutdown | 關閉應用程序,要求endpoints.shutdown.enabled設置爲true |
GET | /trace | 提供基本的HTTP請求跟蹤信息(時間戳、HTTP頭等) |
項目依賴安全
<dependencies> <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> </dependencies>
配置文件
server: port: 8080 management: security: enabled: false #關掉安全認證 port: 8088 #管理端口調整成8088 context-path: /monitor #actuator的訪問路徑 endpoints: shutdown: enabled: true info: app: name: spring-boot-actuator version: 1.0.0
management.security.enabled=false
默認有一部分信息須要安全驗證以後才能夠查看,若是去掉這些安全認證,直接設置management.security.enabled=falsemanagement.context-path=/monitor
表明啓用單獨的url地址來監控Spring Boot應用,爲了安全通常都啓用獨立的端口來訪問後端的監控信息endpoints.shutdown.enabled=true
啓用接口關閉Spring Boot配置完成以後,啓動項目就能夠繼續驗證各個監控功能了。
Spring Boot的自動配置功能很是便利,但有時候也意味着出問題比較難找出具體的緣由。使用 autoconfig 能夠在應用運行時查看代碼了某個配置在什麼條件下生效,或者某個自動配置爲何沒有生效。
啓動示例項目,訪問:http://localhost:8088/monitor/autoconfig
返回部分信息以下:
{ "positiveMatches": { "DevToolsDataSourceAutoConfiguration": { "notMatched": [ { "condition": "DevToolsDataSourceAutoConfiguration.DevToolsDataSourceCondition", "message": "DevTools DataSource Condition did not find a single DataSource bean" } ], "matched": [ ] }, "RemoteDevToolsAutoConfiguration": { "notMatched": [ { "condition": "OnPropertyCondition", "message": "@ConditionalOnProperty (spring.devtools.remote.secret) did not find property 'secret'" } ], "matched": [ { "condition": "OnClassCondition", "message": "@ConditionalOnClass found required classes 'javax.servlet.Filter', 'org.springframework.http.server.ServerHttpRequest'; @ConditionalOnMissingClass did not find unwanted class" } ] } } }
查看配置文件中設置的屬性內容,以及一些配置屬性的默認值。
啓動示例項目,訪問:http://localhost:8088/monitor/configprops
返回部分信息以下:
{ ... "environmentEndpoint": { "prefix": "endpoints.env", "properties": { "id": "env", "sensitive": true, "enabled": true } }, "spring.http.multipart-org.springframework.boot.autoconfigure.web.MultipartProperties": { "prefix": "spring.http.multipart", "properties": { "maxRequestSize": "10MB", "fileSizeThreshold": "0", "location": null, "maxFileSize": "1MB", "enabled": true, "resolveLazily": false } }, "infoEndpoint": { "prefix": "endpoints.info", "properties": { "id": "info", "sensitive": false, "enabled": true } } ... }
根據示例就能夠看出,展現了bean的別名、類型、是否單例、類的地址、依賴等信息。
啓動示例項目,訪問:http://localhost:8088/monitor/beans
返回部分信息以下:
[ { "context": "application:8080:management", "parent": "application:8080", "beans": [ { "bean": "embeddedServletContainerFactory", "aliases": [ ], "scope": "singleton", "type": "org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory", "resource": "null", "dependencies": [ ] }, { "bean": "endpointWebMvcChildContextConfiguration", "aliases": [ ], "scope": "singleton", "type": "org.springframework.boot.actuate.autoconfigure.EndpointWebMvcChildContextConfiguration$$EnhancerBySpringCGLIB$$a4a10f9d", "resource": "null", "dependencies": [ ] } } ]
/dump 接口會生成當前線程活動的快照。這個功能很是好,方便咱們在平常定位問題的時候查看線程的狀況。
主要展現了線程名、線程ID、線程的狀態、是否等待鎖資源等信息。
啓動示例項目,訪問:http://localhost:8088/monitor/dump
返回部分信息以下:
[ { "threadName": "http-nio-8088-exec-6", "threadId": 49, "blockedTime": -1, "blockedCount": 0, "waitedTime": -1, "waitedCount": 2, "lockName": "java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@1630a501", "lockOwnerId": -1, "lockOwnerName": null, "inNative": false, "suspended": false, "threadState": "WAITING", "stackTrace": [ { "methodName": "park", "fileName": "Unsafe.java", "lineNumber": -2, "className": "sun.misc.Unsafe", "nativeMethod": true }, { "methodName": "park", "fileName": "LockSupport.java", "lineNumber": 175, "className": "java.util.concurrent.locks.LockSupport", "nativeMethod": false }, { "methodName": "await", "fileName": "AbstractQueuedSynchronizer.java", "lineNumber": 2039, "className": "java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject", "nativeMethod": false }, ... { "methodName": "getTask", "fileName": "ThreadPoolExecutor.java", "lineNumber": 1067, "className": "java.util.concurrent.ThreadPoolExecutor", "nativeMethod": false }, { "methodName": "runWorker", "fileName": "ThreadPoolExecutor.java", "lineNumber": 1127, "className": "java.util.concurrent.ThreadPoolExecutor", "nativeMethod": false }, { "methodName": "run", "fileName": "ThreadPoolExecutor.java", "lineNumber": 617, "className": "java.util.concurrent.ThreadPoolExecutor$Worker", "nativeMethod": false }, { "methodName": "run", "fileName": "TaskThread.java", "lineNumber": 61, "className": "org.apache.tomcat.util.threads.TaskThread$WrappingRunnable", "nativeMethod": false }, { "methodName": "run", "fileName": "Thread.java", "lineNumber": 745, "className": "java.lang.Thread", "nativeMethod": false } ], "lockedMonitors": [ ], "lockedSynchronizers": [ ], "lockInfo": { "className": "java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject", "identityHashCode": 372286721 } } ... ]
展現了系統環境變量的配置信息,包括使用的環境變量、JVM 屬性、命令行參數、項目使用的jar包等信息。和configprops不一樣的是,configprops關注於配置信息,env關注運行環境信息。
啓動示例項目,訪問:http://localhost:8088/monitor/env
返回部分信息以下:
{ "profiles": [ ], "server.ports": { "local.management.port": 8088, "local.server.port": 8080 }, "servletContextInitParams": { }, "systemProperties": { "com.sun.management.jmxremote.authenticate": "false", "java.runtime.name": "Java(TM) SE Runtime Environment", "spring.output.ansi.enabled": "always", "sun.boot.library.path": "C:\\Program Files\\Java\\jdk1.8.0_101\\jre\\bin", "java.vm.version": "25.101-b13", "java.vm.vendor": "Oracle Corporation", "java.vendor.url": "http://java.oracle.com/", "java.rmi.server.randomIDs": "true", "path.separator": ";", "java.vm.name": "Java HotSpot(TM) 64-Bit Server VM", "file.encoding.pkg": "sun.io", "user.country": "CN", "user.script": "", "sun.java.launcher": "SUN_STANDARD", "sun.os.patch.level": "", "PID": "5268", "com.sun.management.jmxremote.port": "60093", "java.vm.specification.name": "Java Virtual Machine Spe
爲了不敏感信息暴露到 /env 裏,全部名爲password、secret、key(或者名字中最後一段是這些)的屬性在 /env 裏都會加上「*」。舉個例子,若是有一個屬性名字是database.password,那麼它在/env中的顯示效果是這樣的:
"database.password":"******"
/env/{name}用法
就是env的擴展 能夠獲取指定配置信息,好比:http://localhost:8088/monitor/env/java.vm.version
,返回:{"java.vm.version":"25.101-b13"}
能夠看到 HealthEndPoint 給咱們提供默認的監控結果,包含 磁盤檢測和數據庫檢測
啓動示例項目,訪問:http://localhost:8088/monitor/health
返回部分信息,下面的JSON響應是由狀態、磁盤空間和db。描述了應用程序的總體健康狀態,UP 代表應用程序是健康的。磁盤空間描述總磁盤空間,剩餘的磁盤空間和最小閾值。application.properties
閾值是可配置的
{ "status": "UP", "diskSpace": { "status": "UP", "total": 209715195904, "free": 183253909504, "threshold": 10485760 } "db": { "status": "UP", "database": "MySQL", "hello": 1 } }
其實看 Spring Boot-actuator 源碼,你會發現 HealthEndPoint 提供的信息不只限於此,org.springframework.boot.actuate.health 包下 你會發現 ElasticsearchHealthIndicator、RedisHealthIndicator、RabbitHealthIndicator 等
info就是咱們本身配置在配置文件中以Info開頭的配置信息,好比咱們在示例項目中的配置是:
info: app: name: spring-boot-actuator version: 1.0.0
啓動示例項目,訪問:http://localhost:8088/monitor/info
返回部分信息以下:
{ "app": { "name": "spring-boot-actuator", "version": "1.0.0" } }
描述所有的URI路徑,以及它們和控制器的映射關係
啓動示例項目,訪問:http://localhost:8088/monitor/mappings
返回部分信息以下:
{ "/**/favicon.ico": { "bean": "faviconHandlerMapping" }, "{[/hello]}": { "bean": "requestMappingHandlerMapping", "method": "public java.lang.String com.neo.controller.HelloController.index()" }, "{[/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)" } }
最重要的監控內容之一,主要監控了JVM內容使用、GC狀況、類加載信息等。
啓動示例項目,訪問:http://localhost:8088/monitor/metrics
返回部分信息以下:
{ "mem": 337132, "mem.free": 183380, "processors": 4, "instance.uptime": 254552, "uptime": 259702, "systemload.average": -1.0, "heap.committed": 292864, "heap.init": 129024, "heap.used": 109483, "heap": 1827840, "nonheap.committed": 45248, "nonheap.init": 2496, "nonheap.used": 44269, "nonheap": 0, "threads.peak": 63, "threads.daemon": 43, "threads.totalStarted": 83, "threads": 46, "classes": 6357, "classes.loaded": 6357, "classes.unloaded": 0, "gc.ps_scavenge.count": 8, "gc.ps_scavenge.time": 99, "gc.ps_marksweep.count": 1, "gc.ps_marksweep.time": 43, "httpsessions.max": -1, "httpsessions.active": 0 }
對 /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.200.metrics 代表/metrics端點返回 200(OK) 狀態碼的次數。
HTTP的度量信息在結構上也差很少,卻在報告另外一類信息。它們所有以gauge.response 開頭,,代表這是HTTP響應的度量信息。前綴後是對應的路徑。度量值是以毫秒爲單位的時間,反映了最近處理該路徑請求的耗時。
這裏還有幾個特殊的值須要注意。root路徑指向的是根路徑或/。star-star表明了那些Spring 認爲是靜態資源的路徑,包括圖片、JavaScript和樣式表,其中還包含了那些找不到的資源。這就是爲何你常常會看到 counter.status.404.star-star,這是返回了HTTP 404 (NOT FOUND) 狀態的請求數。
/metrics
接口會返回全部的可用度量值,但你也可能只對某個值感興趣。要獲取單個值,請求時能夠在URL後加上對應的鍵名。例如,要查看空閒內存大小,能夠向/metrics/mem.free
發一 個GET請求。例如訪問:http://localhost:8088/monitor/metrics/mem.free
,返回:{"mem.free":178123}
。
開啓接口優雅關閉Spring Boot應用,要使用這個功能首先須要在配置文件中開啓:
endpoints: shutdown: enabled: true
配置完成以後,啓動示例項目,訪問:http://localhost:8088/monitor/shutdown
返回部分信息以下:
{ "message": "Shutting down, bye..." }
此時你會發現應用已經被關閉。
/trace 接口能報告全部Web請求的詳細信息,包括請求方法、路徑、時間戳以及請求和響應的頭信息,記錄每一次請求的詳細信息。
啓動示例項目,先訪問一次:http://localhost:8080/hello
,再到瀏覽器執行:http://localhost:8088/monitor/trace
查看返回信息:
[ { "timestamp": 1516780334777, "info": { "method": "GET", "path": "/hello", "headers": { "request": { "host": "localhost:8080", "connection": "keep-alive", "cache-control": "max-age=0", "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36", "upgrade-insecure-requests": "1", "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", "accept-encoding": "gzip, deflate, br", "accept-language": "zh-CN,zh;q=0.9", "cookie": "UM_distinctid=16053ba344f1cd-0dc220c44cc94-b7a103e-13c680-16053ba3450751; Hm_lvt_0fb30c642c5f6453f17d881f529a1141=1513076406,1514961720,1515649377; CNZZDATA1260945749=232252692-1513233181-%7C1516085149; Hm_lvt_6d8e8bb59814010152d98507a18ad229=1515247964,1515296008,1515672972,1516086283" }, "response": { "X-Application-Context": "application:8080", "Content-Type": "text/html;charset=UTF-8", "Content-Length": "11", "Date": "Wed, 24 Jan 2018 07:52:14 GMT", "status": "200" } }, "timeTaken": "4" } } ]
上述信息展現了,/hello請求的詳細信息。
根據上面表格,鑑權爲false的,表示不敏感,能夠隨意訪問,不然就是作了一些保護,不能隨意訪問。
endpoints.mappings.sensitive=false
這樣須要對每個都設置,比較麻煩。敏感方法默認是須要用戶擁有ACTUATOR角色,所以,也能夠設置關閉安全限制:
management.security.enabled=false
或者配合Spring Security作細粒度控制。
雖然Actuator的接口都頗有用,但你不必定須要所有這些接口。默認狀況下,全部接口(除 了/shutdown)都啓用。好比要禁用 /metrics 接口,則能夠設置以下:
endpoints.metrics.enabled = false
若是你只想打開一兩個接口,那就先禁用所有接口,而後啓用那幾個你要的,這樣更方便。
endpoints.enabled = false endpoints.metrics.enabled = true
Spring Boot Actuator: Production-ready features
對沒有監控的微服務Say No!
Spring Boot Actuator 使用
舊的屬性 | 新的屬性 |
endpoints.<id>.* | management.endpoint.<id>.* |
endpoints.cors.* | management.endpoints.web.cors.* |
endpoints.jmx.* | management.endpoints.jmx.* |
management.address | management.server.address |
management.context-path | management.server.servlet.context-path |
management.ssl.* | management.server.ssl.* |
management.port | management.server.port |
全部 endpoints 默認狀況下都已移至 /actuator。就是多了跟路徑 actuator ;
上個版本中的 management/context-path: 和 management/port: 改成 : 官網配置 https://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/reference/html/common-application-properties.html
# Add the "X-Application-Context" HTTP header in each response. management.server.add-application-context-header=false management.server.address=127.0.0.1 management.server.port=8088 management.server.servlet.context-path=/monitor ## default health,info management.endpoints.web.exposure.include=health,info management.endpoints.web.exposure.exclude= management.endpoints.web.base-path=/actuator
另外,您還可使用新的單獨屬性 management.endpoints.web.base-path 爲管理端點設置基本路徑。
例如,若是你設置management.server.servlet.context-path=/monitor和management.endpoints.web.base-path=/actuator,你就能夠在下面的路徑到達終點健康:/monitor/actuator/health
若是你想恢復 1.x 的行爲(即具備/health代替/actuator/health),設置如下屬性:management.endpoints.web.base-path=/
HTTP 方法 | 路徑 | 描述 |
---|---|---|
GET | /autoconfig | 提供了一份自動配置報告,記錄哪些自動配置條件經過了,哪些沒經過 |
GET | /configprops | 描述配置屬性(包含默認值)如何注入Bean |
GET | /beans | 描述應用程序上下文裏所有的Bean,以及它們的關係 |
GET | /dump | 獲取線程活動的快照 |
GET | /env | 獲取所有環境屬性 |
GET | /env/{name} | 根據名稱獲取特定的環境屬性值 |
GET | /health | 報告應用程序的健康指標,這些值由HealthIndicator的實現類提供 |
GET | /info | 獲取應用程序的定製信息,這些信息由info打頭的屬性提供 |
GET | /mappings | 描述所有的URI路徑,以及它們和控制器(包含Actuator端點)的映射關係 |
GET | /metrics | 報告各類應用程序度量信息,好比內存用量和HTTP請求計數 |
GET | /metrics/{name} | 報告指定名稱的應用程序度量值 |
POST | /shutdown | 關閉應用程序,要求endpoints.shutdown.enabled設置爲true |
GET | /trace | 提供基本的HTTP請求跟蹤信息(時間戳、HTTP頭等) |
名稱 | 1.x 端點 | 2.0 端點(改變) |
訪問路徑 | /ID | /management.server.servlet.context-path/management.endpoints.web.base-path/ID |
默認端點 | /ID | /actuator/ID : 由於:base-path=/actuator 爲默認值 |
事件 | /auditevents | 該after參數再也不須要 |
自動配置映射條件 | /autoconfig | 重命名爲 /conditions |
doc | /docs : spring-boot-actuator-docs | 再也不可用 |
健康信息 | /health | 如今有一個 management.endpoint.health.show-details 選項 never, always, when-authenticated, 而不是依靠 sensitive 標誌來肯定 health 端點是否必須顯示所有細節。 默認狀況下,/actuator/health公開而且不顯示細節。 |
路由信息 | /trace | 重命名爲 /httptrace |
同時注意只有端點/health和/info端點是暴露的。
Property | Default |
management.endpoints.jmx.exposure.exclude | |
management.endpoints.jmx.exposure.include | * |
management.endpoints.web.exposure.exclude | |
management.endpoints.web.exposure.include | info, health |