SpringBoot指標監(jiān)控的實現
一、SpringBoot——Actuator
1.1 快速開始
未來每一個微服務在運算部署以后,我們都需要對其進行監(jiān)控、追蹤、審計和控制等等。Springboot就抽取了Actuator場景,使得我們每個微服務快速引用即可獲得生產級別的應用監(jiān)控、審計等功能。
那么,我們要怎么用呢?
首先,導入我們的場景:
<!--指示監(jiān)控--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
導入場景后,我們啟動我們的主程序,我們來訪問一下這個actuator。
他告訴我們我們現在可以訪問的有http://localhost:8080/actuator和http://localhost:8080/actuator/health。
我們來看一下這個health。(下圖的意思是正常,如果是宕機狀態(tài)的話,他的值是DOWN)
在上面的網址:http://localhost:8080/actuator/health 中,actuator后的health是actuator模塊的一個端點。類似的端點還有很多,借用一下官網的表吧:
端點 | 描述 |
---|---|
auditevents | 公開當前應用程序的審計事件信息。需要一個AuditEventRepository豆子。 |
beans | 顯示應用程序中所有 Spring bean 的完整列表。 |
caches | 公開可用的緩存。 |
conditions | 顯示在配置和自動配置類上評估的條件以及它們匹配或不匹配的原因。 |
configprops | 顯示所有 的整理列表@ConfigurationProperties。 |
env | 從 Spring 的ConfigurableEnvironment. |
flyway | 顯示已應用的任何 Flyway 數據庫遷移。需要一顆或多Flyway顆豆子。 |
health | 顯示應用程序運行狀況信息。 |
httptrace | 顯示 HTTP 跟蹤信息(默認情況下,最后 100 個 HTTP 請求-響應交換)。需要一個HttpTraceRepository豆子。 |
info | 顯示任意應用程序信息。 |
integrationgraph | 顯示 Spring 集成圖。需要依賴于spring-integration-core. |
loggers | 顯示和修改應用程序中記錄器的配置。 |
liquibase | 顯示已應用的任何 Liquibase 數據庫遷移。需要一顆或多Liquibase顆豆子。 |
metrics | 顯示當前應用程序的“指標”信息。 |
mappings | 顯示所有@RequestMapping路徑的整理列表。 |
quartz | 顯示有關 Quartz 調度程序作業(yè)的信息。 |
scheduledtasks | 顯示應用程序中的計劃任務。 |
sessions | 允許從 Spring Session 支持的會話存儲中檢索和刪除用戶會話。需要使用 Spring Session 的基于 Servlet 的 Web 應用程序。 |
shutdown | 讓應用程序正常關閉。默認禁用。 |
startup | 顯示由收集的啟動步驟數據ApplicationStartup。需要SpringApplication使用BufferingApplicationStartup. |
threaddump | 執(zhí)行線程轉儲。 |
注意:雖然我們的Springboot有這么多Actuator的監(jiān)控端點,但是,我們剛才也看到了,他默認情況下在HTTP就給我們開了一個health的端點。其他端點默認是無法訪問的,得要我們手動開啟才行。但是在我們的JMX中默認暴露的就是所有的端點了。
什么東西?JMX??JMX是什么?
JMX(Java Management Extensions,即Java管理擴展)是一個為應用程序、設備、系統等植入管理功能的框架。JMX可以跨越一系列異構操作系統平臺、系統體系結構和網絡傳輸協議,靈活的開發(fā)無縫集成的系統、網絡和服務管理應用。(來源于百度百科)
那我們怎么打開它呢?
簡單,我們打開cmd,輸入jconsole。
然后,選擇我們現在的那個SpringBoot的項目。
在我們的MBean菜單項中,可以找到org.springframework.boot,Endpoint(端點),里面那些就是我們所對應的端點及其信息了。
我們可以通過點擊Beans端點下的操作,再點擊他的beans按鈕查看我們當前所有的bean。
但是這種方式看起來,屬實不舒服。所以,我們就想,能不能打開web端的這些個端點信息呢?答案肯定是可以的。
官網給出的打開方式如下:
解釋一下:
- management.endpoints.jmx.exposure.exclude:開啟的 jmx 的端點不包括哪些
- management.endpoints.jmx.exposure.include: 開始 jmx 的哪些端點(默認是所有)
- management.endpoints.web.exposure.exclude:開啟的 web 的端點不包括哪些
- management.endpoints.web.exposure.include:開啟web的哪些端點(默認是health)
舉兩個案例:
停止通過 JMX 公開所有端點而僅公開health和info端點
management: endpoints: jmx: exposure: include: "health,info"
通過 HTTP 公開除env和beans端點之外的所有端點
management: endpoints: web: exposure: include: "*" exclude: "env,beans"
我們可以嘗試打開所有的端點看一下:
management: endpoints: web: exposure: include: '*'
編譯一下,然后我們看一下我們的beans端點:
里面有我們所有的Bean,包括他們是不是單例,他們的全類名和依賴等等信息。
我們還可以訪問我們的conditions端點,查看我們所有的配置(包括我們成功配置的和沒有配置的)
還有他們?yōu)槭裁茨軌蚺渲蒙希?br />
以及他們?yōu)槭裁床荒軌蚺渲蒙希?br />
我們再來看一個常用的端點:metrics。
他可以看很多消息,具體翻譯一下即可,比如第一個http.server.requests,說的就是我們的http請求。我們可以訪問來看一下。
直接在/metrics后邊加上面的字符串就可以了。
1.2 簡單介紹最常用的幾個端點
1.2.1 health(健康狀況)
健康檢查端點,一般用于云平臺,平臺會定時的檢查應用的監(jiān)控狀況,為此,我們就需要使用health端點為平臺返回當前應用的一系列組件的健康狀況的集合。
重要的幾點:
1、健康端點返回的結果,應該是一系列健康檢查后的一個匯總報告
2、很多的健康檢查默認已經自動配置好了,比如:數據庫、redis等
3、可以很容易的添加自定義的健康檢查機制
前面我們已經說過了端點,好像沒啥特別的呀,別急嘛。那主要是因為我們沒有讓他顯示詳細的信息。
現在,我們來讓health端點顯示詳細信息,在配置文件中這么配置:(注意:配置所有的端點的時候,我們用的是復數的endpoints,而配置具體某個端點的時候,我們用的是endpoint)
management: endpoint: health: show-details: always
此時我們再訪問health端點:
解釋一下:
1、首先是db,數據庫,健康,通過isValid方法判斷出來。
2、然后是diskSpace,我們的磁盤空間,總計是240054693888,空閑是148654080000,使用10485760。
3、最后是ping,表示能ping通
1.2.2 metrics(運行時指標)
指標端點主要用于提供詳細的、層級的、空間指標信息,這些信息可以被pull(主動推送)或者push(被動獲?。┓绞降玫健?br />
重要的幾點:
1、通過metrics對接多種監(jiān)控系統
2、簡化核心metrics的開發(fā)
3、添加自定義metrics或者擴展已有metrics
這個我們前面已經講過了。他里面含有我們很多的指標信息。具體有哪些我們可以進入/actuator/metrics下進行查看。然后,我們找到我們要查看的指標信息對應的字符串,將那段字符串后接到/metrics/后邊即可。
1.2.3 loggers(日志記錄)
這個感覺也沒啥好說的,自己訪問去看一下即可。
1.3 開啟或關閉某個端點
上面講的那種直接開啟web端所有的端點的方式,其實還是比較危險的,因此,我們一般需要修改默認的配置。讓他不要開啟那么多的端點給我們的http或者JMX。我們修改他的默認配置。(默認是true,true情況下開啟JMX下所有的端點,開啟http下的health端點)
management: endpoints: enabled-by-default: false
然后我們想開啟某個端點的話,我們就在配置文件給他的enable屬性賦予true。
比如,開啟我們的health和info端點
management: endpoint: health: show-details: always enabled: true info: enabled: true
此時,我們再訪問我們的/actuator可以看到,他只開啟了health和info兩個端點。
去我們的JMX看一下:(也只剩下兩個了)
1.4 定制端點
1.4.1 定制我們的Health端點
我們知道這個端點默認的給我們設置了數據庫和磁盤信息的健康情況。但是,當我們引入其他的組件的時候,我們也希望他判斷一下,這個組件健不健康,健康的話,給我們返回什么信息,不健康的話,又給我們返回什么信息。
下面,我們就模仿磁盤給出的信息的格式,來給Health端點定制一個對我們自己的某個組件的檢查。
很簡單,只需要寫一個類繼承AbstractHealthIndicator類或者實現HealthIndicator接口,然后實現他的doHealthCheck方法。
我們可以參照DiskSpaceHealthIndicator類的doHealthCheck方法來寫一個。
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // package org.springframework.boot.actuate.system; import java.io.File; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.boot.actuate.health.AbstractHealthIndicator; import org.springframework.boot.actuate.health.Health.Builder; import org.springframework.core.log.LogMessage; import org.springframework.util.unit.DataSize; public class DiskSpaceHealthIndicator extends AbstractHealthIndicator { private static final Log logger = LogFactory.getLog(DiskSpaceHealthIndicator.class); private final File path; private final DataSize threshold; public DiskSpaceHealthIndicator(File path, DataSize threshold) { super("DiskSpace health check failed"); this.path = path; this.threshold = threshold; } protected void doHealthCheck(Builder builder) throws Exception { long diskFreeInBytes = this.path.getUsableSpace(); if (diskFreeInBytes >= this.threshold.toBytes()) { builder.up(); } else { logger.warn(LogMessage.format("Free disk space below threshold. Available: %d bytes (threshold: %s)", diskFreeInBytes, this.threshold)); builder.down(); } builder.withDetail("total", this.path.getTotalSpace()).withDetail("free", diskFreeInBytes).withDetail("threshold", this.threshold.toBytes()).withDetail("exists", this.path.exists()); } }
來,我們繼承并重寫doHealthCheck方法的代碼如下:
package com.example.boot.health; import org.springframework.boot.actuate.health.AbstractHealthIndicator; import org.springframework.boot.actuate.health.Health; import org.springframework.stereotype.Component; import java.util.HashMap; import java.util.Map; @Component public class MyIndicator extends AbstractHealthIndicator { @Override protected void doHealthCheck(Health.Builder builder) throws Exception { //判斷的變量 boolean flag = true; //存儲詳細信息 Map<String, Object> msg = new HashMap<>(); //判斷是否健康 if(flag){ //健康 builder.up(); msg.put("code",200); msg.put("detail","我各個地方都沒有問題"); }else { //不健康 builder.down(); msg.put("code",500); msg.put("detail","服務器好像出了什么毛病"); } //將數據寫入檢查器 builder.withDetail("codes",100) .withDetails(msg); } }
結果如下:
1.4.2 定制我們的Info端點
對于info信息的定制,我們有兩種定制方式。
方式一、在yaml文件中直接配置即可。以info開頭,后邊自己隨便加變量和屬性值。(只有一級目錄,有二級目錄會報錯)
info: word: hello,world appName: 我是Info的appName
運行:
我們還可以拿pom.xml的東西,通過@@獲取。
info: word: hello,world appName: 我是Info的appName mavenProjectName: @project.name@ mavenAGV: [@project.artifactId@, @project.groupId@, @project.version@]
結果:
方式二、編寫一個類實現InfoContributor接口
package com.example.boot.info; import org.springframework.boot.actuate.info.Info; import org.springframework.boot.actuate.info.InfoContributor; import org.springframework.stereotype.Component; @Component public class MyInfo implements InfoContributor { @Override public void contribute(Info.Builder builder) { builder.withDetail("AppName","Hello,World") .withDetail("msg","我是實現了InfoContributor的類的消息"); } }
結果:
1.4.3 定制我們的metrics端點
先打開我們的metrics端點。
management: endpoint: health: show-details: always enabled: true info: enabled: true metrics: enabled: true
然后,假如我們現在要計算某個方法被調用的次數。
package com.example.boot.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.boot.bean.User; import com.example.boot.mapper.UserMapper; import com.example.boot.service.UserService; import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.MeterRegistry; import org.springframework.stereotype.Service; import java.util.List; @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { Counter counter; //在構造器傳入參數MeterRegistry registry UserServiceImpl(MeterRegistry registry){ //設置在metrics端點下的名稱 counter = registry.counter("userServiceImpl.list.count"); } @Override public List<User> list() { //次數加1 counter.increment(); return super.list(); } }
編譯一下,我們可以去看看此時的metrics端點。
然后訪問幾次我們的localhost:8080/user。
然后看一下我們的metrics/userServiceImpl.list.count。(可以看到我們調用了10次)
1.4.4 定制我們自己的端點
package com.example.boot.endpoint; import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.boot.actuate.endpoint.annotation.WriteOperation; import org.springframework.stereotype.Component; import java.util.HashMap; import java.util.Map; /** * 使用@Endpoint標注我們的端點類,并使用id賦值取名 */ @Endpoint(id = "myEndPoint") @Component public class MyEndPoint { /** * 端點的讀操作 * 返回值無所謂,這里以Map為例返回,比較好看 */ @ReadOperation public Map<String,Object> getDockerInfo(){ Map<String, Object> map = new HashMap<>(); map.put("dockerInfo","docker started......"); return map; } /** * 端點的寫操作 */ @WriteOperation public void stopDocker(){ System.out.println("docker stopped......."); } }
定義完成后,我們可以打開我們的監(jiān)控看一下:發(fā)現他是開著的。
訪問一下:(讀操作)
至于寫操作要怎么執(zhí)行,我們只能打開我們的cmd,進我們的JMX看看了。
我們點擊stopDocker。
編譯器后臺輸出:docker stopped…
1.5 SpringBoot——Admin Server
用來可視化我們所有的監(jiān)控指數。(包括所有我們開啟的端點的信息)具體可以點擊這個鏈接觀看尚硅谷的視頻(時長13分25秒,每一秒都干貨滿滿)。
運行的圖大致如下:(部分截圖僅供參考)
圖1:
圖2:
圖3:
到此這篇關于SpringBoot指標監(jiān)控的實現的文章就介紹到這了,更多相關SpringBoot指標監(jiān)控內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring Cloud 動態(tài)刷新配置信息教程詳解
這篇文章主要介紹了Spring Cloud 動態(tài)刷新配置信息的教程,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2018-06-06springboot通過SchedulingConfigurer實現多定時任務注冊及動態(tài)修改執(zhí)行周期(示例詳解)
這篇文章主要介紹了springboot通過SchedulingConfigurer實現多定時任務注冊及動態(tài)修改執(zhí)行周期,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-06-06