面試官:聊一聊SpringBoot服務監控機制

前言

任何一個服務若是沒有監控,那就是兩眼一抹黑,沒法知道當前服務的運行狀況,也就沒法對可能出現的異常情況進行很好的處理,因此對任意一個服務來講,監控都是必不可少的。java

就目前而言,大部分微服務應用都是基於 SpringBoot 來構建,因此瞭解 SpringBoot 的監控特性是很是有必要的,而 SpringBoot 也提供了一些特性來幫助咱們監控應用。web

本文基於 SpringBoot 2.3.1.RELEASE 版本演示。spring

SpringBoot 監控

SpringBoot 中的監控能夠分爲 HTTP 端點和 JMX 兩種方式來監控當前應用的運行情況和指標收集json

HTTP Endpoints 監控

執行器端點容許您監視應用程序並與之交互。SpringBoot 包括許多內置的端點,並容許咱們添加本身的端點。能夠經過 HTTPJMX 啓用或禁用每一個端點,並公開(使其能夠遠程訪問)。每一個端點都有一個惟一的 id,訪問時能夠經過以下地址進行訪問:http:ip:port/{id}(SpringBoot 1.x ),而在 SpringBoot 2.x 版本中,默認新增了一個 /actuator 做爲基本路,訪問地址則對應爲 :http:ip:port/actuator/{id}緩存

使用 HTTP 監控很是簡單,在 SpringBoot 項目中,引入以下依賴:tomcat

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

默認就能夠經過地址 http:localhost:8080/actuator/health,訪問以後獲得以下結果:安全

image

SpringBoot 中提供了很是多的默認端點監控,可是出於安全考慮,默認狀況下有些端點並非開啓狀態,如 shutdown 端點就是默認關閉的。springboot

內置端點

SpringBoot 中默認提供的經常使用內置端點以下:服務器

端點 id 描述
auditevents 公開當前應用程序的審計事件信息,須要 AuditEventRepository Bean。
beans 展現程序中全部的 Bean。
caches 公開可用的緩存。
conditions 展現配置類或者自動裝配類中的條件,以及它們匹配或者不匹配的緣由。
configprops 顯示全部 @ConfigurationProperties 中的配置屬性。
env 顯示 ConfigurableEnvironment 中的全部環境。
health 顯示應用程序運行情況信息。
httptrace 顯示 HTTP 跟蹤信息(默認狀況下統計最近 100 次請求),須要 HttpTraceRepository Bean。
info 顯示任意程序信息。
integrationgraph 顯示 Spring 集成圖,須要依賴 spring-integration-core。
loggers 展現和修改應用中的 loggers 配置。
metrics 展現當前應用監控指標的度量。
mappings 展現全部 @RequestMapping 路徑。
scheduledtasks 展現應用中的全部定時任務信息。
sessions 容許從 Spring 會話支持的會話存儲中檢索和刪除用戶會話。須要使用基於 Spring Session web應用程序。
shutdown 優雅的關閉程序,默認禁止了該端點的訪問。

雖說這裏的大部分端點都是默認開啓的,可是默認暴露(容許對外訪問)的只有 healthinfo 端點,因此若是須要容許端點對外暴露,能夠經過以下配置(若是想要暴露全部的端點,則能夠直接配置 "*" ):session

management:
  endpoints:
    web:
      exposure:
        include: [health,info,mappings] //或者直接配置 "*"

另外,開啓或禁用某一個端點,也能夠經過經過以下配置進行動態控制:

management.endpoint.<id>.enabled=true

接下來咱們挑選幾個重點的端點來介紹一下。

health 端點

health 斷點默認只是展現當前應用健康信息,可是咱們能夠經過另外一個配置打開詳細信息,這樣不只僅會監控當前應用,還會監控與當前應用相關的其餘第三方應用,如 Redis

management:
  endpoint:
    health:
      show-details: always

這個配置打開以後,咱們鏈接上 Redis 以後再次訪問 health 端點,就能夠展現 Redis 服務的健康信息了:

image

loggers 端點

訪問 http://localhost:8080/actuator/loggers 能夠查看當前應用的日誌級別等信息:

image

這裏面自己並不特別,可是有一個功能卻很是有用,好比咱們生產環境日誌級別通常都是 info,可是如今有一個 bug 經過 info 級別沒法排查,那麼咱們就能夠臨時修改 log 級別。

好比上圖中的 ROOT 節點是 info 級別,那麼咱們能夠經過 postman 等工具來發一個 post 請求修改日誌級別。

image

修改以後就會發現,日誌由原來的 info 變成了 debug

image

metrics 端點

metrics 是一個很是重要的監控端點,其監控內容覆蓋了 JVM 內存、堆、類加載、處理器和 tomcat 容器等一些重要指標:

image

能夠看到這裏麪包含了很是多的指標,任意訪問一個指標就能夠查看對應的指標信息:

image

自定義監控端點

經過上面的介紹,能夠看到 SpringBoot 提供的監控很是強大,可是就算再全面的監控也不可能知足全部人的需求,因此 SpringBoot 也支持自定義監控端點。

自定義監控端點經常使用註解

自定義一個監控端點主要有以下經常使用註解:

  • @Endpoint:定義一個監控端點,同時支持 HTTPJMX 兩種方式。
  • @WebEndpoint:定義一個監控端點,只支持 HTTP 方式。
  • @JmxEndpoint:定義一個監控端點,只支持 JMX 方式。

以上三個註解做用在類上,表示當前類是一個監控端點,另外還有一些註解會用在方法和參數上:

  • @ReadOperation:做用在方法上,可用來返回端點展現的信息(經過 Get 方法請求)。
  • @WriteOperation:做用在方法上,可用來修改端點展現的信息(經過 Post 方法請求)。
  • @DeleteOperation:做用在方法上,可用來刪除對應端點信息(經過 Delete 方法請求)。
  • @Selector:做用在參數上,用來定位一個端點的具體指標路由。

來,一塊兒寫一個本身的監控端點

  • 定義一個類,並使用 @Endpoint 註解標註標識,同時定義幾個方法用 @ReadOperation@WriteOperation 註解來標註:
@Endpoint(id="myEndpoint")
@Component
public class MyEndpoint {
    private String STATUS = "up";
    private String DETAIL = "一切正常";

//    @ReadOperation
//    public String test1(){
//        return "wolf";
//    }

//    @ReadOperation
//    public Map<String,String> test2(){
//        Map<String,String> 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//動態修改指標
    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;
            }
        }
    }
}
  1. @Component 註解表示將該類交給 Spring 進行管理,或者也能夠再定義一個 Configuration 類來加載該 Bean 也能夠,固然,若是咱們須要提供給第三方使用,若是沒法保證當前包名被掃描,則須要使用 SpringBoot 的自動裝配機制將該類進行管理。
  2. @ReadOperation 方法能夠返回 String 或者 JSONObject 或者 Map 集合等。
  3. 參數上加了 @Selector 註解則表示訪問斷端點的時候能夠直接訪問子節點。

完成了上面的類,啓動 SpringBoot 應用,接下來就能夠直接經過 http://localhost:8080/actuator/myEndpoint 進行訪問了:

image

同時,由於 test3_1 方法使用了 @Selector 註解,因此咱們能夠經過這個方法每個指標的明細:

image

而帶有 @WriteOperation 註解的方法能夠用來修改指標,這個方法須要用 post 進行訪問,訪問的參數能夠直接使用字符串傳參,也能夠直接使用 json 進行傳參,修改以後再次查看就能夠發現指標已經被動態修改:

image

JMX 監控

JMX 全稱爲 Java Management Extensions,即 Java 管理擴展。它提供了對 Java 應用程序和 JVM 的監控管理。經過JMX 咱們能夠監控服務器中各類資源的使用狀況以及線程,內存和 CPU 等使用狀況。

打開 jdk 下提供的工具 jConsole

image

打開以後這裏會監控到咱們已經啓動的應用,雙擊進入:

image

如何手動註冊一個 JMX MBean

  • 定義一個接口 SystemInfoMBean(注意名字必需要用 MBean 結尾):
public interface SystemInfoMBean {
    int getCpuCore();
    long getTotalMemory();
    void shutdown();
}
  • 再定義一個類實現 SystemInfoMBean 接口,實現類的明明方式爲接口名去掉 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);
    }
}
  • 最後就是須要將該實現類進行註冊:
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);//註冊
        System.in.read();//防止程序結束
    }
}

運行該 main 方法,再打開 jConsole 就能夠看到成功註冊了一個 MBean

image

一樣的,Spring 當中只要咱們使用了 @@Endpoint 或者 @JmxEndpoint 註解,就會自動幫咱們註冊一個 MBean,其原理也是利用了自動裝配機制。

其餘監控

除了 SpringBoot 自帶的監控以外,也有其餘第三方開源的強大監控系統,如 Prometheus,並且 SpringBoot 也將其進行了集成,使用 Prometheus 時只須要引入以下 jar 包便可:

<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

固然,若是使用 Prometheus 的話須要單獨安裝,並且通常會選擇 Prometheus + Grafana 來共同實現一個監控平臺,在這裏就不作過多介紹,若是感興趣的朋友能夠本身去了解下這兩種軟件的使用。

總結

本文主要講述了 Spring Boot actuator 的使用,並分別介紹了其中兩種監控類型 HTTPJMX,最後經過一個例子來實現了自定義的端點,同時也實現了手動註冊一個 MBean 的方法。

相關文章
相關標籤/搜索