手把手教你實(shí)現(xiàn)SpringBoot的監(jiān)控!

大家好,我是寶哥!
SpringBoot 監(jiān)控
| HTTP Endpoints 監(jiān)控
使用 HTTP 監(jiān)控非常簡(jiǎn)單,在 SpringBoot 項(xiàng)目中,引入如下依賴:
<dependencies>
????<dependency>
????????<groupId>org.springframework.bootgroupId>
????????<artifactId>spring-boot-starter-actuatorartifactId>
????dependency>
dependencies>
默認(rèn)就可以通過地址 http:localhost:8080/actuator/health,訪問之后得到如下結(jié)果:

內(nèi)置端點(diǎn)
SpringBoot 中默認(rèn)提供的常用內(nèi)置端點(diǎn)如下:

雖然說這里的大部分端點(diǎn)都是默認(rèn)開啟的,但是默認(rèn)暴露(允許對(duì)外訪問)的只有 health 和 info 端點(diǎn),所以如果需要允許端點(diǎn)對(duì)外暴露,可以通過如下配置(如果想要暴露所有的端點(diǎn),則可以直接配置?"*"?):
management:
??endpoints:
????web:
??????exposure:
????????include:?[health,info,mappings]?//或者直接配置?"*"
另外,開啟或禁用某一個(gè)端點(diǎn),也可以通過通過如下配置進(jìn)行動(dòng)態(tài)控制:
management.endpoint.<id>.enabled=true
health 端點(diǎn)
health 斷點(diǎn)默認(rèn)只是展示當(dāng)前應(yīng)用健康信息,但是我們可以通過另一個(gè)配置打開詳細(xì)信息,這樣不僅僅會(huì)監(jiān)控當(dāng)前應(yīng)用,還會(huì)監(jiān)控與當(dāng)前應(yīng)用相關(guān)的其他第三方應(yīng)用,如 Redis。
management:
??endpoint:
????health:
??????show-details:?always
這個(gè)配置打開之后,我們連接上 Redis 之后再次訪問 health 端點(diǎn),就可以展示 Redis 服務(wù)的健康信息了:

loggers 端點(diǎn)
訪問 http://localhost:8080/actuator/loggers 可以查看當(dāng)前應(yīng)用的日志級(jí)別等信息:

比如上圖中的 ROOT 節(jié)點(diǎn)是 info 級(jí)別,那么我們可以通過 postman 等工具來發(fā)一個(gè) post 請(qǐng)求修改日志級(jí)別。

修改之后就會(huì)發(fā)現(xiàn),日志由原來的 info 變成了 debug:

metrics 端點(diǎn)
metrics 是一個(gè)非常重要的監(jiān)控端點(diǎn),其監(jiān)控內(nèi)容覆蓋了 JVM 內(nèi)存、堆、類加載、處理器和 tomcat 容器等一些重要指標(biāo):

可以看到這里面包含了非常多的指標(biāo),任意訪問一個(gè)指標(biāo)就可以查看對(duì)應(yīng)的指標(biāo)信息:

自定義監(jiān)控端點(diǎn)
@Endpoint:定義一個(gè)監(jiān)控端點(diǎn),同時(shí)支持 HTTP 和 JMX 兩種方式。
@WebEndpoint:定義一個(gè)監(jiān)控端點(diǎn),只支持 HTTP 方式。
@JmxEndpoint:定義一個(gè)監(jiān)控端點(diǎn),只支持 JMX 方式。
@ReadOperation:作用在方法上,可用來返回端點(diǎn)展示的信息(通過 Get 方法請(qǐng)求)。
@WriteOperation:作用在方法上,可用來修改端點(diǎn)展示的信息(通過 Post 方法請(qǐng)求)。
@DeleteOperation:作用在方法上,可用來刪除對(duì)應(yīng)端點(diǎn)信息(通過 Delete 方法請(qǐng)求)。
@Selector:作用在參數(shù)上,用來定位一個(gè)端點(diǎn)的具體指標(biāo)路由。
來,一起寫一個(gè)自己的監(jiān)控端點(diǎn),定義一個(gè)類,并使用?@Endpoint 注解標(biāo)注標(biāo)識(shí),同時(shí)定義幾個(gè)方法用?@ReadOperation 和?@WriteOperation 注解來標(biāo)注:
@Endpoint(id="myEndpoint")
@Component
public?class?MyEndpoint?{
????private?String?STATUS?=?"up";
????private?String?DETAIL?=?"一切正常";
//????@ReadOperation
//????public?String?test1(){
//????????return?"wolf";
//????}
//????@ReadOperation
//????public?Map?test2(){
//????????Map?map?=?new?HashMap();
//????????map.put("status","up");
//????????return?map;
//????}
????@ReadOperation
????public?JSONObject?test3(){
????????JSONObject?jsonObject=?new?JSONObject();
????????jsonObject.put("status",STATUS);
????????jsonObject.put("detail",DETAIL);
????????return?jsonObject;
????}
????@ReadOperation
????public?JSONObject?test3_1(@Selector?String?name){
????????JSONObject?jsonObject=?new?JSONObject();
????????if?("status".equals(name)){
????????????jsonObject.put("status",STATUS);
????????}else?if?("detail".equals(name)){
????????????jsonObject.put("detail",DETAIL);
????????}
????????return?jsonObject;
????}
????@WriteOperation//動(dòng)態(tài)修改指標(biāo)
????public?void?test4(@Selector?String?name,@Nullable?String?value){
????????if?(!StringUtils.isEmpty(value)){
????????????if?("status".equals(name)){
????????????????STATUS?=?value;
????????????}else?if?("detail".equals(name)){
????????????????DETAIL?=?value;
????????????}
????????}
????}
}
完成了上面的類,啟動(dòng) SpringBoot 應(yīng)用,接下來就可以直接通過 http://localhost:8080/actuator/myEndpoint 進(jìn)行訪問了:

同時(shí),因?yàn)?test3_1 方法使用了?@Selector 注解,所以我們可以通過這個(gè)方法每一個(gè)指標(biāo)的明細(xì):

而帶有?@WriteOperation 注解的方法可以用來修改指標(biāo),這個(gè)方法需要用 post 進(jìn)行訪問,訪問的參數(shù)可以直接使用字符串傳參,也可以直接使用 json 進(jìn)行傳參,修改之后再次查看就可以發(fā)現(xiàn)指標(biāo)已經(jīng)被動(dòng)態(tài)修改:

| JMX 監(jiān)控
打開 jdk 下提供的工具 jConsole:

打開之后這里會(huì)監(jiān)控到我們已經(jīng)啟動(dòng)的應(yīng)用,雙擊進(jìn)入:

如何手動(dòng)注冊(cè)一個(gè) JMX MBean?
定義一個(gè)接口 SystemInfoMBean(注意名字必須要用 MBean 結(jié)尾):
public?interface?SystemInfoMBean?{
????int?getCpuCore();
????long?getTotalMemory();
????void?shutdown();
}
再定義一個(gè)類實(shí)現(xiàn) SystemInfoMBean 接口,實(shí)現(xiàn)類的命名方式為接口名去掉 MBean:
public?class?SystemInfo?implements?SystemInfoMBean?{
????@Override
????public?int?getCpuCore()?{
????????return?Runtime.getRuntime().availableProcessors();
????}
????@Override
????public?long?getTotalMemory()?{
????????return?Runtime.getRuntime().totalMemory();
????}
????@Override
????public?void?shutdown()?{
????????System.exit(0);
????}
}
最后就是需要將該實(shí)現(xiàn)類進(jìn)行注冊(cè):
public?class?JmxRegisterMain?{
????public?static?void?main(String[]?args)?throws?NotCompliantMBeanException,?InstanceAlreadyExistsException,?MBeanRegistrationException,?MalformedObjectNameException,?IOException?{
????????MBeanServer?mBeanServer=?ManagementFactory.getPlatformMBeanServer();
????????ObjectName?objectName=new?ObjectName("com.lonely.wolf.note.springboot.actuator.jmx:type=SystemInfo");
????????SystemInfo?SystemInfo?=new?SystemInfo();
????????mBeanServer.registerMBean(SystemInfo,objectName);//注冊(cè)
????????System.in.read();//防止程序結(jié)束
????}
}
運(yùn)行該 main 方法,再打開 jConsole 就可以看到成功注冊(cè)了一個(gè) MBean:

除了 SpringBoot 自帶的監(jiān)控之外,也有其他第三方開源的強(qiáng)大監(jiān)控系統(tǒng),如 Prometheus,而且 SpringBoot 也將其進(jìn)行了集成,使用 Prometheus 時(shí)只需要引入如下 jar 包即可:
<dependency>
????<groupId>io.micrometergroupId>
????<artifactId>micrometer-registry-prometheusartifactId>
dependency>
總結(jié)
作者:雙子孤狼 原文:https://blog.csdn.net/zwx900102/article/details/115446997
精彩推薦:
一套牛逼哄哄的開源的監(jiān)控系統(tǒng)(附源碼)
Alibaba開源的高并發(fā)手冊(cè),幾乎涵蓋了所有高并發(fā)操作!
SQL優(yōu)化萬能公式:5 大步驟 + 10 個(gè)案例
SpringBoot集成WebSocket,實(shí)現(xiàn)后臺(tái)向前端推送信息
OAuth 2 實(shí)現(xiàn)單點(diǎn)登錄,通俗易懂!
