1. 程式人生 > 程式設計 >Spring Boot Actuator監控的簡單使用方法示例程式碼詳解

Spring Boot Actuator監控的簡單使用方法示例程式碼詳解

Spring Boot Actuator幫助我們實現了許多中介軟體比如mysql、es、redis、mq等中介軟體的健康指示器。
通過 Spring Boot 的自動配置,這些指示器會自動生效。當這些元件有問題的時候,HealthIndicator 會返回 DOWN 或 OUT_OF_SERVICE 狀態,health 端點 HTTP 響應狀態碼也會變為 503,我們可以以此來配置程式健康狀態監控報警。
使用步驟也非常簡單,這裡演示的是執行緒池的監控。模擬執行緒池滿了狀態下將HealthInicator指示器變為Down的狀態。

pom中引入jar

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

引入properties配置

spring.application.name=boot


# server.servlet.context-path=/boot
# management.server.servlet.context-path=/boot
# JVM (Micrometer)要求給應用設定commonTag
management.metrics.tags.application=${spring.application.name}
#去掉重複的metrics
spring.metrics.servo.enabled=false

management.endpoint.metrics.enabled=true
management.endpoint.metrics.sensitive=false
#顯式配置不需要許可權驗證對外開放的端點
management.endpoints.web.exposure.include=*
management.endpoints.jmx.exposure.include=*

management.endpoint.health.show-details=always
#Actuator 的 Web 訪問方式的根地址為 /actuator,可以通過 management.endpoints.web.base-path 引數進行修改
management.endpoints.web.base-path=/actuator
management.metrics.export.prometheus.enabled=true

程式碼

/**
  * @Author jeffSmile
  * @Date 下午 6:10 2020/5/24 0024
  * @Description 定義一個介面,來把耗時很長的任務提交到這個 demoThreadPool 執行緒池,以模擬執行緒池佇列滿的情況
  **/

 @GetMapping("slowTask")
 public void slowTask() {
  ThreadPoolProvider.getDemoThreadPool().execute(() -> {
   try {
    TimeUnit.HOURS.sleep(1);
   } catch (InterruptedException e) {
   }
  });
 }
package com.mongo.boot.service;

import jodd.util.concurrent.ThreadFactoryBuilder;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolProvider {

 //一個工作執行緒的執行緒池,佇列長度10
 private static ThreadPoolExecutor demoThreadPool = new ThreadPoolExecutor(
   1,1,2,TimeUnit.SECONDS,new ArrayBlockingQueue<>(10),new ThreadFactoryBuilder().setNameFormat("demo-threadpool-%d").get());
 //核心執行緒數10,最大執行緒數50的執行緒池,佇列長度50
 private static ThreadPoolExecutor ioThreadPool = new ThreadPoolExecutor(
   10,50,new ArrayBlockingQueue<>(100),new ThreadFactoryBuilder().setNameFormat("io-threadpool-%d").get());

 public static ThreadPoolExecutor getDemoThreadPool() {
  return demoThreadPool;
 }

 public static ThreadPoolExecutor getIOThreadPool() {
  return ioThreadPool;
 }
}
package com.mongo.boot.service;

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @Author jeffSmile
 * @Date 下午 6:12 2020/5/24 0024
 * @Description 自定義的 HealthIndicator 類,用於單一執行緒池的健康狀態
 **/

public class ThreadPoolHealthIndicator implements HealthIndicator {
 private ThreadPoolExecutor threadPool;

 public ThreadPoolHealthIndicator(ThreadPoolExecutor threadPool) {
  this.threadPool = threadPool;
 }

 @Override
 public Health health() {
  //補充資訊
  Map<String,Integer> detail = new HashMap<>();
  //隊列當前元素個數
  detail.put("queue_size",threadPool.getQueue().size());
  //佇列剩餘容量
  detail.put("queue_remaining",threadPool.getQueue().remainingCapacity());

  //如果還有剩餘量則返回UP,否則返回DOWN
  if (threadPool.getQueue().remainingCapacity() > 0) {
   return Health.up().withDetails(detail).build();
  } else {
   return Health.down().withDetails(detail).build();
  }
 }
}
package com.mongo.boot.service;

import org.springframework.boot.actuate.health.CompositeHealthContributor;
import org.springframework.boot.actuate.health.HealthContributor;
import org.springframework.boot.actuate.health.NamedContributor;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/***
 * @Author jeffSmile
 * @Date 下午 6:13 2020/5/24 0024
 * @Description 定義一個 CompositeHealthContributor,來聚合兩個 ThreadPoolHealthIndicator 的例項,
 * 分別對應 ThreadPoolProvider 中定義的兩個執行緒池
 **/

@Component
public class ThreadPoolsHealthContributor implements CompositeHealthContributor {

 //儲存所有的子HealthContributor
 private Map<String,HealthContributor> contributors = new HashMap<>();

 ThreadPoolsHealthContributor() {
  //對應ThreadPoolProvider中定義的兩個執行緒池
  this.contributors.put("demoThreadPool",new ThreadPoolHealthIndicator(ThreadPoolProvider.getDemoThreadPool()));
  this.contributors.put("ioThreadPool",new ThreadPoolHealthIndicator(ThreadPoolProvider.getIOThreadPool()));
 }

 @Override
 public HealthContributor getContributor(String name) {
  //根據name找到某一個HealthContributor
  return contributors.get(name);
 }

 @Override
 public Iterator<NamedContributor<HealthContributor>> iterator() {
  //返回NamedContributor的迭代器,NamedContributor也就是Contributor例項+一個命名
  return contributors.entrySet().stream()
    .map((entry) -> NamedContributor.of(entry.getKey(),entry.getValue())).iterator();
 }
}

啟動springboot驗證

這裡我訪問:http://localhost:8080/slowTask

在這裡插入圖片描述

每次訪問都向demo執行緒池中提交一個耗時1小時的任務,而demo執行緒池的核心和最大執行緒數都是1,佇列長度為10,那麼當訪問11次之後,任務將被直接拒絕掉!

在這裡插入圖片描述
在這裡插入圖片描述

此時訪問:http://localhost:8080/actuator/health

在這裡插入圖片描述

demo執行緒池佇列已經滿了,狀態變為DOWN。

在這裡插入圖片描述

監控內部重要元件的狀態資料

通過 Actuator 的 InfoContributor 功能,對外暴露程式內部重要元件的狀態資料!
實現一個 ThreadPoolInfoContributor 來展現執行緒池的資訊:

package com.mongo.boot.config;

import com.mongo.boot.service.ThreadPoolProvider;
import org.springframework.boot.actuate.info.Info;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ThreadPoolExecutor;


/**
 * @Author jeffSmile
 * @Date 下午 6:37 2020/5/24 0024
 * @Description 通過 Actuator 的 InfoContributor 功能,對外暴露程式內部重要元件的狀態資料
 **/

@Component
public class ThreadPoolInfoContributor implements InfoContributor {

 private static Map threadPoolInfo(ThreadPoolExecutor threadPool) {
  Map<String,Object> info = new HashMap<>();
  info.put("poolSize",threadPool.getPoolSize());//當前池大小
  info.put("corePoolSize",threadPool.getCorePoolSize());//設定的核心池大小
  info.put("largestPoolSize",threadPool.getLargestPoolSize());//最大達到過的池大小
  info.put("maximumPoolSize",threadPool.getMaximumPoolSize());//設定的最大池大小
  info.put("completedTaskCount",threadPool.getCompletedTaskCount());//總完成任務數
  return info;
 }

 @Override
 public void contribute(Info.Builder builder) {
  builder.withDetail("demoThreadPool",threadPoolInfo(ThreadPoolProvider.getDemoThreadPool()));
  builder.withDetail("ioThreadPool",threadPoolInfo(ThreadPoolProvider.getIOThreadPool()));
 }
}

直接訪問http://localhost:8080/actuator/info

在這裡插入圖片描述

如果開啟jmx,還可以使用jconsole來檢視執行緒池的狀態資訊:

#開啟 JMX
spring.jmx.enabled=true

開啟jconcole介面之後,進入MBean這個tab,可以在EndPoint下的Info操作這裡看到我們的Bean資訊。

在這裡插入圖片描述

不過,除了jconsole之外,我們可以把JMX協議轉為http協議,這裡引入jolokia:

<dependency>
 <groupId>org.jolokia</groupId>
 <artifactId>jolokia-core</artifactId>
</dependency>

重啟後訪問:http://localhost:8080/actuator/jolokia/exec/org.springframework.boot:type=Endpoint,name=Info/info

在這裡插入圖片描述

監控延伸

通過Micrometer+promethues+grafana的組合也可以進行一些生產級別的實踐。

到此這篇關於Spring Boot Actuator監控的簡單使用的文章就介紹到這了,更多相關Spring Boot Actuator監控內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!