歡迎您光臨本站 註冊首頁

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

←手機掃碼閱讀     limiyoyo @ 2020-06-21 , reply:0

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

pom中引入jar

  org.springframework.bootspring-boot-starter-actuator

 

引入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,     2, TimeUnit.SECONDS,     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() {    //補充信息    Mapdetail = 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 Mapcontributors = 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> 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) {    Mapinfo = 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:

  org.jolokiajolokia-core

 

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

在這裡插入圖片描述

監控延伸

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


   


[limiyoyo ] Spring Boot Actuator監控的簡單使用方法示例代碼詳解已經有273次圍觀

http://coctec.com/docs/java/show-post-239346.html