微服務的特色決定了功能模塊的部署是分佈式的,大部分功能模塊都是運行在不一樣的機器上,彼此經過服務調用進行交互,先後臺的業務流會通過不少個微服務的處理和傳遞,出現異常如何快速定位便成爲了一個問題,在這種框架下微服務的監控顯得尤其重要。html
Spring Boot 是一個自帶監控的開源框架,組件 Spring Boot Actuator 負責監控應用的各項靜態和動態的變量。項目結合 Spring Boot Actuator 的使用,即可輕鬆對 Spring Boot 應用監控治理,Spring Boot 的 Actuator 提供了不少生產級的特性,好比監控和度量 Spring Boot 應用程序,這些特性能夠經過衆多 REST 接口、遠程 Shell 和 JMX 得到。java
Spring Boot 使用「習慣優於配置的理念」,採用包掃描和自動化配置的機制來加載依賴 jar 中的 Spring Bean,不須要任何 XML 配置,就能夠實現 Spring 的全部配置。雖然這樣作能讓代碼變得很是簡潔,可是整個應用的實例建立和依賴關係等信息都被離散到了各個配置類的註解上,這使得咱們分析整個應用中資源和實例的各類關係變得很是的困難。web
<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>
添加 spring-boot-starter-web 主要是爲了保持應用運行狀態。redis
Spring Boot Actuator 是 Spring Boot 提供的對應用系統的檢查和監控的集成功能,能夠查看應用配置的詳細信息,例如自動化配置信息、建立的 Spring beans 以及一些環境屬性等。算法
Actuator 監控分紅兩類:原生端點和用戶自定義端點。自定義端點主要是指擴展性,用戶能夠根據本身的實際應用,定義一些比較關心的指標,在運行期進行監控。spring
原生端點是在應用程序裏提供衆多 Web 接口,經過它們瞭解應用程序運行時的內部情況,原生端點又能夠分紅三類:數據庫
Actuator 提供了 13 個接口,具體以下表所示。apache
management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=beans,trace
// 設置完重啓後,再次訪問地址就會變成 /manage/* management.endpoints.web.base-path=/manage
health 主要用來檢查應用的運行狀態,這是咱們使用最高頻的一個監控點,一般使用此接口提醒咱們應用實例的運行狀態,以及應用不「健康」的緣由,如數據庫鏈接、磁盤空間不夠等。tomcat
默認狀況下 health 的狀態是開放的,添加依賴後啓動項目,訪問:http://localhost:8080/actuator/health
便可看到應用的狀態。安全
{ "status" : "UP" }
默認狀況下,最終的 Spring Boot 應用的狀態是由 HealthAggregator 彙總而成的,彙總的算法是:
health 經過合併幾個健康指數檢查應用的健康狀況。Spring Boot Actuator 有幾個預約義的健康指標好比 DataSourceHealthIndicator、DiskSpaceHealthIndicator、MongoHealthIndicator、RedisHealthIndicator 等,它使用這些健康指標做爲健康檢查的一部分。
舉個例子,若是你的應用使用 Redis,RedisHealthindicator 將被看成檢查的一部分;若是使用 MongoDB,那麼 MongoHealthIndicator 將被看成檢查的一部分。
能夠在配置文件中關閉特定的健康檢查指標,好比關閉 Redis 的健康檢查:
management.health.redise.enabled=false
默認全部的這些健康指標被看成健康檢查的一部分。
詳細的健康檢查信息
默認只是展現了簡單的 UP 和 DOWN 狀態,爲了查詢更詳細的監控指標信息,能夠在配置文件中添加如下信息:
management.endpoint.health.show-details=always
http://localhost:8080/actuator/health
,返回信息以下:{ "status": "UP", "diskSpace": { "status": "UP", "total": 209715195904, "free": 183253909504, "threshold": 10485760 } }
其實看 Spring Boot-actuator 源碼,會發現 HealthEndPoint 提供的信息不只限於此,在 org.springframework.boot.actuate.health 包下會發現 ElasticsearchHealthIndicator、RedisHealthIndicator、RabbitHealthIndicator 等。
info.app.name=spring-boot-actuator info.app.version= 1.0.0 info.app.test= test
http://localhost:8080/actuator/info
返回部分信息以下:{ "app": { "name": "spring-boot-actuator", "version": "1.0.0", "test":"test" } }
http://localhost:8080/actuator/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": [ ] } } ]
Spring Boot 的自動配置功能很是便利,但有時候也意味着出問題比較難找出具體的緣由。使用 conditions 能夠在應用運行時查看代碼瞭解某個配置在什麼條件下生效,或者某個自動配置爲何沒有生效。
啓動示例項目,訪問網址 http://localhost:8080/actuator/conditions
返回部分信息以下:
{ "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:8080/actuator/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 } } ... }
展現了系統環境變量的配置信息,包括使用的環境變量、JVM 屬性、命令行參數、項目使用的 jar 包等信息。和 configprops 不一樣的是,configprops 關注於配置信息,env 關注運行環境信息。
啓動示例項目,訪問網址 http://localhost:8080/actuator/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
"database.password":"******"
就是 env 的擴展能夠獲取指定配置信息,好比http://localhost:8080/actuator/env/java.vm.version,返回 {"java.vm.version":"25.101-b13"}
http://localhost:8080/actuator/heapdump
會自動生成一個 JVM 的堆文件 heapdump,咱們可使用 JDK 自帶的 JVM 監控工具 VisualVM 打開此文件查看內存快照。相似以下圖:該端點用來返回基本的 HTTP 跟蹤信息。默認狀況下,跟蹤信息的存儲採用 org.springframework.boot.actuate.trace.InMemoryTraceRepository 實現的內存方式,始終保留最近的 100 條請求記錄。
啓動示例項目,訪問網址 http://localhost:8080/actuator/httptrace
,返回信息以下:
{ "traces": [ { "timestamp": "2018-11-21T12:42:25.333Z", "principal": null, "session": null, "request": { "method": "GET", "uri": "http://localhost:8080/actuator/heapdump", "headers": { "cookie": [ "Hm_lvt_0fb30c642c5f6453f17d881f529a1141=1513076406,1514961720,1515649377; Hm_lvt_6d8e8bb59814010152d98507a18ad229=1515247964,1515296008,1515672972,1516086283; UM_distinctid=1647364371ef6-003ab9d0469ea5-b7a103e-100200-1647364371f104; CNZZDATA1260945749=232252692-1513233181-%7C1537492730" ], "accept-language": [ "zh-CN,zh;q=0.9" ], "upgrade-insecure-requests": [ "1" ], "host": [ "localhost:8080" ], "connection": [ "keep-alive" ], "accept-encoding": [ "gzip, deflate, br" ], "accept": [ "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8" ], "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" ] }, "remoteAddress": null }, "response": { "status": 200, "headers": { "Accept-Ranges": [ "bytes" ], "Content-Length": [ "39454385" ], "Date": [ "Wed, 21 Nov 2018 12:42:25 GMT" ], "Content-Type": [ "application/octet-stream" ] } }, "timeTaken": 1380 }, { ... }, ... ] }
http://localhost:8080/actuator/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 接口提供的信息進行簡單分類以下表:
解釋說明
http://localhost:8080/actuator/metrics/mem.free
,返回:{"mem.free":178123}。management.endpoint.shutdown.enabled=true
shutdown 接口默認只支持 post 請求。
curl -X POST "http://localhost:8080/actuator/shutdown" { "message": "Shutting down, bye..." }
http://localhost:8080/actuator/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)" } }
/threaddump 接口會生成當前線程活動的快照,這個功能很是好,方便咱們在平常定位問題的時候查看線程的狀況,主要展現了線程名、線程 ID、線程的狀態、是否等待鎖資源等信息。
啓動示例項目,訪問網址 http://localhost:8080/actuator/threaddump
返回部分信息以下:
[ { "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": "run", "fileName": "TaskThread.java", "lineNumber": 61, "className": "org.apache.tomcat.util.threads.TaskThread$WrappingRunnable", "nativeMethod": false } ... ], "lockInfo": { "className": "java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject", "identityHashCode": 372286721 } } ... ]
通過這節課實踐咱們發現 Spring Boot Actuator 做爲 Spring Boot 自帶的監控組件很是強大,它能夠監控和管理 Spring Boot 應用,如健康檢查、審計、統計和 HTTP 追蹤等,全部的這些特性能夠經過 JMX 或者 HTTP endpoints 來得到。使用 Spring Boot Actuator 以後,可讓咱們經過很簡單的接口或者命令來查詢應用的一切運行狀態,從而達到對應用的運行狀況瞭如指掌。