徹底搞懂Spring Boot的系統(tǒng)監(jiān)控機(jī)制
在 Java 世界中,Spring 框架已經(jīng)是最主流的開發(fā)框架了。但傳統(tǒng) Spring 框架存在一個(gè)明顯的問題,那就是 缺少系統(tǒng)監(jiān)控功能。如果想要獲取一個(gè) Spring 應(yīng)用程序的線程工作狀態(tài)以及 JVM 性能指標(biāo)等各種運(yùn)行時(shí)數(shù)據(jù),我們就不得不借助一些第三方工具,這在云原生時(shí)代無疑加重了系統(tǒng)運(yùn)維管理的成本。
好在,Spring Boot 框架誕生了,它不僅繼承了 Spring 框架原有的優(yōu)良特性,而且又引入了一個(gè)創(chuàng)新型的技術(shù)組件,即 Spring Boot Actuator,該組件可以用來實(shí)現(xiàn)內(nèi)嵌的系統(tǒng)監(jiān)控功能,完美地解決了原有 Spring 框架缺少系統(tǒng)監(jiān)控功能的問題。讓我們一起來看一下吧!
Spring Boot Actuator
Actuator 組件是 Spring Boot 中承載系統(tǒng)監(jiān)控功能的組件,該組件通過一系列 HTTP 端點(diǎn)提供監(jiān)控能力。Spring Boot 的強(qiáng)大之處就在于為開發(fā)人員內(nèi)置了一組非常簡(jiǎn)單而實(shí)用的原生監(jiān)控端點(diǎn)。在接下來的內(nèi)容中,我們先介紹一些常用的 Actuator 端點(diǎn)。
原生 Actuator 端點(diǎn)
說到監(jiān)控端點(diǎn),你可能會(huì)覺得這個(gè)概念有點(diǎn)兒抽象。實(shí)際上,所謂的監(jiān)控端點(diǎn),就是一個(gè)普通的 HTTP 請(qǐng)求地址。當(dāng)我們啟動(dòng)一個(gè) Spring Boot 應(yīng)用程序,可以訪問 http://localhost:8080/actuator 這個(gè) HTTP 地址來獲取所有可用的端點(diǎn)信息。
{
"_links":{
"self":{
"href":"http://localhost:8080/actuator",
"templated":false
},
"health-path":{
"href":"http://localhost:8080/actuator/health/{*path}",
"templated":true
},
"health":{
"href":"http://localhost:8080/actuator/health",
"templated":false
},
"info":{
"href":"http://localhost:8080/actuator/info",
"templated":false
}
}
}可以看到,這些都是 HATEOAS 風(fēng)格的 HTTP 端點(diǎn)信息。我們?cè)谶@里找到了兩個(gè)非常常用的端點(diǎn),即 health 端點(diǎn)和 info 端點(diǎn)。以 health 端點(diǎn)為例,我們可以通過該端點(diǎn)進(jìn)一步獲取系統(tǒng)的健康狀態(tài)信息。
{
"status":"UP",
"components":{
"diskSpace":{
"status":"UP",
"details":{
"total":201649549312,
"free":3434250240,
"threshold":10485760
}
},
"ping":{
"status":"UP"
}
}
}可以看到,這里展示了當(dāng)前系統(tǒng)的磁盤空間系統(tǒng)以及網(wǎng)絡(luò)連接信息。事實(shí)上,在 Spring Boot Actuator 中包含了一組類似 health 端點(diǎn)的監(jiān)控端點(diǎn)。我們可以把這些端點(diǎn)按照各自提供的功能進(jìn)行分類,包括應(yīng)用配置、度量指標(biāo)和操作控制這三大類。
圖 1 Spring Boot Actuator 的三大類原生端點(diǎn)
其中,應(yīng)用配置類端點(diǎn)的作用就是提供各種 Spring Boot 應(yīng)用程序相關(guān)的配置信息,典型的包括/beans、/env、/info 等端點(diǎn)。通過這些端點(diǎn),開發(fā)人員可以獲取應(yīng)用程序中所包含的 JavaBean 信息、環(huán)境變量信息以及各種自定義的配置信息等。
圖 2 常見的應(yīng)用配置類端點(diǎn)
顧名思義,度量指標(biāo)類的監(jiān)控端點(diǎn)一方面用來獲取內(nèi)存信息、線程信息等各種重要的度量指標(biāo),同時(shí)也可以正確反映應(yīng)用程序的健康指標(biāo)信息,這部分的常見端點(diǎn)有/metrics、/threaddump 和/health 端點(diǎn)等。
圖 3 常見的度量指標(biāo)類端點(diǎn)
相比這兩類端點(diǎn),操作控制類的端點(diǎn)則數(shù)量較少,常見的只有用來對(duì)應(yīng)用程序執(zhí)行關(guān)閉操作的/shutdown 端點(diǎn)。
如果 Spring Boot Actuator 默認(rèn)提供的端點(diǎn)信息不能滿足需求,我們還可以對(duì)其進(jìn)行修改和擴(kuò)展。常見實(shí)現(xiàn)方案有兩種,一種是擴(kuò)展現(xiàn)有的監(jiān)控端點(diǎn),另一種是自定義新的監(jiān)控端點(diǎn)。
擴(kuò)展 Actuator 端點(diǎn)
接下來,我們來關(guān)注一下如何在現(xiàn)有的監(jiān)控端點(diǎn)上添加定制化功能。我們同樣以前面已經(jīng)介紹的/health 端點(diǎn)為例展開討論。
在 Spring Boot 中,Health 端點(diǎn)用于檢查正在運(yùn)行的應(yīng)用程序健康狀態(tài)。Health 端點(diǎn)信息的豐富程度取決于當(dāng)下應(yīng)用程序所處的環(huán)境,一個(gè)現(xiàn)實(shí)環(huán)境下的 Health 端點(diǎn)信息如下所示。通過這些信息,我們可以判斷該環(huán)境中包含了 MySQL 數(shù)據(jù)庫(kù)。
{
"status":"UP",
"components":{
"db":{
"status":"UP",
"details":{
"database":"MySQL",
"result":1,
"validationQuery":"/* ping */ SELECT 1"
}
},
"diskSpace":{
"status":"UP",
"details":{
"total":201649549312,
"free":3491287040,
"threshold":10485760
}
},
"ping":{
"status":"UP"
}
}
}現(xiàn)在,我們希望在 Health 端點(diǎn)中暴露某個(gè)應(yīng)用程序的當(dāng)前運(yùn)行時(shí)狀態(tài)。這時(shí)候就可以自定義一個(gè) CustomHealthIndicator 端點(diǎn)。我們明確,健康狀態(tài)信息是由 HealthIndicator 接口從 Spring 的 ApplicationContext 中進(jìn)行獲取的,所以這個(gè) CustomHealthIndicator 需要實(shí)現(xiàn) HealthIndicator 接口。
@Component
publicclass CustomHealthIndicator implements HealthIndicator {
@Override
public Health health() {
try {
URL url = new URL("http://localhost:8083/health/");
HttpURLConnection conn = (HttpURLConnection)
url.openConnection();
int statusCode = conn.getResponseCode();
if (statusCode >= 200 && statusCode < 300) {
return Health.up().build();
} else {
return Health.down().withDetail("HTTP Status Code", statusCode).build();
}
} catch (IOException e) {
return Health.down(e).build();
}
}
}我們需要提供 health() 方法的具體實(shí)現(xiàn)并返回一個(gè) Health 結(jié)果對(duì)象。該結(jié)果對(duì)象應(yīng)該包括一個(gè)狀態(tài),并且可以根據(jù)需要添加任何細(xì)節(jié)信息。
以上代碼用一種簡(jiǎn)單而直接的方式判斷某個(gè)服務(wù)是否正在運(yùn)行。我們構(gòu)建一個(gè) HTTP 請(qǐng)求,然后根據(jù) HTTP 響應(yīng)得出健康診斷的結(jié)論。如果 HTTP 響應(yīng)的狀態(tài)碼處于 200~300 之間,我們就認(rèn)為該服務(wù)正在運(yùn)行,Health.up().build() 方法將返回一種 UP 響應(yīng),如下所示。
{
"status": "UP",
"details": {
"custom":{
"status": "UP"
}
…
}
}如果狀態(tài)碼不是處于這個(gè)區(qū)間(例如返回的是 404 代表服務(wù)不可用)就返回一個(gè) DOWN 響應(yīng)并給出具體的狀態(tài)碼,如下所示。
{
"status": "DOWN",
"details": {
"custom":{
"status": "DOWN",
"details": {
"HTTP Status Code": "404"
}
},
…
}
}如果 HTTP 請(qǐng)求直接拋出了異常,我們同樣返回一個(gè) Down 響應(yīng),同時(shí)把異常信息一起返回,效果如下所示:
{
"status": "DOWN",
"details": {
"custom":{
"status": "DOWN",
"details": {
"error": "java.net.ConnectException: Connection refused: connect"
}
},
…
}
}顯然,通過擴(kuò)展 Health 端點(diǎn)為我們實(shí)時(shí)監(jiān)控系統(tǒng)中各個(gè)服務(wù)的正常運(yùn)行狀態(tài)提供了很好的支持,你可以根據(jù)需要構(gòu)建一系列有用的 HealthIndicator 實(shí)現(xiàn)類并添加報(bào)警等監(jiān)控手段。
自定義 Actuator 端點(diǎn)
除了對(duì)現(xiàn)有的監(jiān)控端點(diǎn)進(jìn)行動(dòng)態(tài)擴(kuò)展,有時(shí)候我們還可以根據(jù)業(yè)務(wù)場(chǎng)景的需要?jiǎng)?chuàng)建新的監(jiān)控端點(diǎn)。這里舉一個(gè)簡(jiǎn)單的例子。現(xiàn)在,假設(shè)我們的需求是獲取當(dāng)前操作系統(tǒng)的計(jì)算機(jī)名稱,那么就可以實(shí)現(xiàn)這樣一個(gè)新的 CustomEndpoint。
@Configuration
@Endpoint(id = "computername", enableByDefault=true)
public class CustomEndpoint {
@ReadOperation
public Map<String, Object> getMySystemInfo() {
Map<String,Object> result= new HashMap<>();
Map<String, String> map = System.getenv();
result.put("computername",map.get("COMPUTERNAME"));
return result;
}
}可以看到,CustomEndpoint 通過 System.getenv() 方法獲取了系統(tǒng)的環(huán)境變量,然后再通過環(huán)境變量獲取了計(jì)算機(jī)名稱。現(xiàn)在,讓我們執(zhí)行這個(gè) CustomEndpoint 端點(diǎn),得到的結(jié)果是這樣的。
{
"computername":"LAPTOP-EQB59J5P"
}Spring Boot Admin
Spring Boot 還基于 Actuator 組件為開發(fā)人員提供了可視化的系統(tǒng)監(jiān)控組件,這就是 Spring Boot Admin。通過 Admin 組件,我們可以獲取系統(tǒng)運(yùn)行時(shí)的各項(xiàng)關(guān)鍵指標(biāo),并通過友好的交互界面進(jìn)行動(dòng)態(tài)管理。
Spring Boot Admin 會(huì)消費(fèi)前面介紹到的各種 Actuator 的端點(diǎn)信息并將這些信息進(jìn)行統(tǒng)計(jì)和聚合,它的基本原理是這樣的。
圖 4 Spring Boot Admin 基本原理圖
從上圖中,我們首先需要明確存在一個(gè)服務(wù)器組件 Admin Server,它負(fù)責(zé)從各個(gè) Admin Client 所暴露的 Actuator 端點(diǎn)中收集各種監(jiān)控信息。注意,這里的 Admin Server 和 Admin Client 本質(zhì)上都是一個(gè)個(gè) Spring Boot 應(yīng)用程序。然后,Admin Server 會(huì)對(duì)這些監(jiān)控信息進(jìn)行加工處理,并最終通過 Web UI 以可視化的效果展示給開發(fā)人員。
Spring Boot Admin 的功能非常強(qiáng)大,包括顯示健康狀態(tài)、JVM、內(nèi)存等度量明細(xì)信息,以及線程、HTTP 跟蹤等監(jiān)控信息?;?Admin Server,這些功能都通過可視化的 UI 界面進(jìn)行展示。這里,我截取了幾張效果圖。這是 Admin Server 監(jiān)控信息的主界面。
圖 5 Admin Server 監(jiān)控信息主界面
在這里,我們看到了熟悉的“Health”信息。然后,我們注意到在界面的左下角有一個(gè)“JVM”選項(xiàng),點(diǎn)擊該選項(xiàng)可以獲取與 JVM 相關(guān)的監(jiān)控信息。
圖 6 Admin Server 中的 JVM 監(jiān)控信息
最后,我們來看一下非常有用的“Thread Dump”可視化功能。Admin Server 通過這一功能提供了一個(gè)連續(xù)性的可視化 Dump 快照信息監(jiān)控界面。
圖 7 Admin Server 中的 Thread Dump 信息
總結(jié)
好了,以上就是我這節(jié)課想要和你分享的內(nèi)容,最后我們來對(duì)今天的內(nèi)容進(jìn)行一個(gè)簡(jiǎn)單的梳理吧!
今天我們主要介紹了基于 Spring 產(chǎn)生的 Spring Boot 框架。其中,Spring Boot 內(nèi)置的 Actuator 組件為開發(fā)人員管理應(yīng)用程序的運(yùn)行時(shí)狀態(tài)提供了更加直接且高效的手段。
在今天的內(nèi)容中,我們引入了 Actuator 組件并介紹了該組件所提供的一系列核心端點(diǎn)。更為重要的是,我們還重點(diǎn)分析了如何對(duì) Actuator 端點(diǎn)進(jìn)行擴(kuò)展以及創(chuàng)建自定義 Actuator 端點(diǎn)的實(shí)現(xiàn)方法。這些實(shí)現(xiàn)方法都可以直接應(yīng)用到日常開發(fā)過程中。而作為延伸,在今天內(nèi)容的最后,我們還分析了 Spring Boot Admin 這一組件提供的強(qiáng)大可視化監(jiān)控效果。
圖片


































