Spring Boot Actuator:健康檢查、審計、統計和監控


作者:alvin_wang    來源:簡書
鏈接:https://www.jianshu.com/p/d5943e303a1f

Spring Boot Actuator可以幫助你監控和管理Spring Boot應用,比如健康檢查、審計、統計和HTTP追蹤等。所有的這些特性可以通過JMX或者HTTP endpoints來獲得。

Actuator同時還可以與外部應用監控系統整合,比如 Prometheus, Graphite, DataDog, Influx, Wavefront, New Relic等。這些系統提供了非常好的儀表盤、圖標、分析和告警等功能,使得你可以通過統一的接口輕松的監控和管理你的應用。

Actuator使用Micrometer來整合上面提到的外部應用監控系統。這使得只要通過非常小的配置就可以集成任何應用監控系統。

我將把Spring Boot Actuator教程分為兩部分:

  • 第一部分(本文)教你如何配置Actuator和通過Http endpoints來進入這些特征。
  • 第二部分教你如何整合Actuator和外部應用監控系統。

創建一個有Actuator的Spring Boot工程

首先讓我們建一個依賴acutator的簡單應用。

你可以使用Spring Boot CLI創建應用:

spring init -d=web,actuator -n=actuator actuator

或者,你可以使用Spring Initializr網站來創建應用:

 
Spring initialzr.png

增加Spring Boot Actuator到一個存在的應用

你可以增加spring-boot-actuator模塊到一個已經存在的應用,通過使用下面的依賴。

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

對於Gradle,依賴如下:

dependencies {
    compile("org.springframework.boot:spring-boot-starter-actuator")
}

使用Actuator Endpoints來監控應用

Actuator創建了所謂的endpoint來暴露HTTP或者JMX來監控和管理應用。

舉個例子,有一個叫/health的endpoint,提供了關於應用健康的基礎信息。/metricsendpoints展示了幾個有用的度量信息,比如JVM內存使用情況、系統CPU使用情況、打開的文件等等。/loggersendpoint展示了應用的日志和可以讓你在運行時改變日志等級。

值得注意的是,每一給actuator endpoint可以被顯式的打開和關閉。此外,這些endpoints也需要通過HTTP或者JMX暴露出來,使得它們能被遠程進入。

讓我們運行應用並且嘗試進入默認通過HTTP暴露的打開狀態的actuator endpoints。之后,我們將學習如何打開更多的endpoints並且通過HTTP暴露它們。

在應用的根目錄下打開命令行工具運行以下命令:

mvn spring-boot:run

應用默認使用8080端口運行。一旦這個應用啟動了,你可以通過http://localhost:8080/actuator來展示所有通過HTTP暴露的endpoints。

{"_links":{"self":{"href":"http://localhost:8080/actuator","templated":false},"health":{"href":"http://localhost:8080/actuator/health","templated":false},"info":{"href":"http://localhost:8080/actuator/info","templated":false}}}

打開http://localhost:8080/actuator/health,則會顯示如下內容:

{"status":"UP"}

狀態將是UP只要應用是健康的。如果應用不健康將會顯示DOWN,比如與儀表盤的連接異常或者缺水磁盤空間等。下一節我們將學習spring boot如何決定應用的健康和如何修復這些健康問題。

infoendpoint(http://localhost:8080/actuator/info)展示了關於應用的一般信息,這些信息從編譯文件比如META-INF/build-info.properties或者Git文件比如git.properties或者任何環境的property中獲取。你將在下一節中學習如何改變這個endpoint的輸出。

默認,只有healthinfo通過HTTP暴露了出來。這也是為什么/actuator頁面只展示了healthinfoendpoints。我們將學習如何暴露其他的endpoint。首先,讓我們看看其他的endpoints是什么。

以下是一些非常有用的actuator endpoints列表。你可以在official documentation上面看到完整的列表。

Endpoint ID Description
auditevents 顯示應用暴露的審計事件 (比如認證進入、訂單失敗)
info 顯示應用的基本信息
health 顯示應用的健康狀態
metrics 顯示應用多樣的度量信息
loggers 顯示和修改配置的loggers
logfile 返回log file中的內容(如果logging.file或者logging.path被設置)
httptrace 顯示HTTP足跡,最近100個HTTP request/repsponse
env 顯示當前的環境特性
flyway 顯示數據庫遷移路徑的詳細信息
liquidbase 顯示Liquibase 數據庫遷移的纖細信息
shutdown 讓你逐步關閉應用
mappings 顯示所有的@RequestMapping路徑
scheduledtasks 顯示應用中的調度任務
threaddump 執行一個線程dump
heapdump 返回一個GZip壓縮的JVM堆dump

打開和關閉Actuator Endpoints

默認,上述所有的endpints都是打開的,除了shutdown endpoint。

你可以通過設置management.endpoint.<id>.enabled to true or false(id是endpoint的id)來決定打開還是關閉一個actuator endpoint。

舉個例子,要想打開shutdown endpoint,增加以下內容在你的application.properties文件中:

management.endpoint.shutdown.enabled=true

暴露Actuator Endpoints

默認,素偶偶的actuator endpoint通過JMX被暴露,而通過HTTP暴露的只有healthinfo

以下是你可以通過應用的properties可以通過HTTP和JMX暴露的actuator endpoint。

  • 通過HTTP暴露Actuator endpoints。

    # Use "*" to expose all endpoints, or a comma-separated list to expose selected ones
    management.endpoints.web.exposure.include=health,info 
    management.endpoints.web.exposure.exclude
  • 通過JMX暴露Actuator endpoints。

    # Use "*" to expose all endpoints, or a comma-separated list to expose selected ones
    management.endpoints.jmx.exposure.include=*
    management.endpoints.jmx.exposure.exclude=

通過設置management.endpoints.web.exposure.include*,我們可以在http://localhost:8080/actuator頁面看到如下內容。

{"_links":{"self":{"href":"http://localhost:8080/actuator","templated":false},"auditevents":{"href":"http://localhost:8080/actuator/auditevents","templated":false},"beans":{"href":"http://localhost:8080/actuator/beans","templated":false},"health":{"href":"http://localhost:8080/actuator/health","templated":false},"conditions":{"href":"http://localhost:8080/actuator/conditions","templated":false},"configprops":{"href":"http://localhost:8080/actuator/configprops","templated":false},"env":{"href":"http://localhost:8080/actuator/env","templated":false},"env-toMatch":{"href":"http://localhost:8080/actuator/env/{toMatch}","templated":true},"info":{"href":"http://localhost:8080/actuator/info","templated":false},"loggers":{"href":"http://localhost:8080/actuator/loggers","templated":false},"loggers-name":{"href":"http://localhost:8080/actuator/loggers/{name}","templated":true},"heapdump":{"href":"http://localhost:8080/actuator/heapdump","templated":false},"threaddump":{"href":"http://localhost:8080/actuator/threaddump","templated":false},"prometheus":{"href":"http://localhost:8080/actuator/prometheus","templated":false},"metrics-requiredMetricName":{"href":"http://localhost:8080/actuator/metrics/{requiredMetricName}","templated":true},"metrics":{"href":"http://localhost:8080/actuator/metrics","templated":false},"scheduledtasks":{"href":"http://localhost:8080/actuator/scheduledtasks","templated":false},"httptrace":{"href":"http://localhost:8080/actuator/httptrace","templated":false},"mappings":{"href":"http://localhost:8080/actuator/mappings","templated":false}}} 

解析常用的actuator endpoint

/health endpoint

health endpoint通過合並幾個健康指數檢查應用的健康情況。

Spring Boot Actuator有幾個預定義的健康指標比如DataSourceHealthIndicator, DiskSpaceHealthIndicator, MongoHealthIndicator, RedisHealthIndicator, CassandraHealthIndicator等。它使用這些健康指標作為健康檢查的一部分。

舉個例子,如果你的應用使用RedisRedisHealthindicator將被當作檢查的一部分。如果使用MongoDB,那么MongoHealthIndicator將被當作檢查的一部分。

你也可以關閉特定的健康檢查指標,比如在prpperties中使用如下命令:

management.health.mongo.enabled=false

默認,所有的這些健康指標被當作健康檢查的一部分。

顯示詳細的健康信息

health endpoint只展示了簡單的UPDOWN狀態。為了獲得健康檢查中所有指標的詳細信息,你可以通過在application.yaml中增加如下內容:

management:
  endpoint:
    health:
      show-details: always

一旦你打開上述開關,你在/health中可以看到如下詳細內容:

{"status":"UP","details":{"diskSpace":{"status":"UP","details":{"total":250790436864,"free":27172782080,"threshold":10485760}}}}

health endpoint現在包含了DiskSpaceHealthIndicator

如果你的應用包含database(比如MySQL),health endpoint將顯示如下內容:

{
   "status":"UP",
   "details":{
      "db":{
         "status":"UP",
         "details":{
            "database":"MySQL",
            "hello":1
         }
      },
      "diskSpace":{
         "status":"UP",
         "details":{
            "total":250790436864,
            "free":100330897408,
            "threshold":10485760
         }
      }
   }
}

如果你的MySQL server沒有啟起來,狀態將會變成DOWN

{
   "status":"DOWN",
   "details":{
      "db":{
         "status":"DOWN",
         "details":{
            "error":"org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30006ms."
         }
      },
      "diskSpace":{
         "status":"UP",
         "details":{
            "total":250790436864,
            "free":100324585472,
            "threshold":10485760
         }
      }
   }
}

創建一個自定義的健康指標

你可以通過實現HealthIndicator接口來自定義一個健康指標,或者繼承AbstractHealthIndicator類。

package com.example.actuator.health;

import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.stereotype.Component;

@Component
public class CustomHealthIndicator extends AbstractHealthIndicator {

    @Override
    protected void doHealthCheck(Health.Builder builder) throws Exception {
        // Use the builder to build the health status details that should be reported.
        // If you throw an exception, the status will be DOWN with the exception message.
        
        builder.up()
                .withDetail("app", "Alive and Kicking")
                .withDetail("error", "Nothing! I'm good.");
    }
}

一旦你增加上面的健康指標到你的應用中去后,health endpoint將展示如下細節:

{
   "status":"UP",
   "details":{
      "custom":{
         "status":"UP",
         "details":{
            "app":"Alive and Kicking",
            "error":"Nothing! I'm good."
         }
      },
      "diskSpace":{
         "status":"UP",
         "details":{
            "total":250790436864,
            "free":97949245440,
            "threshold":10485760
         }
      }
   }
}

/metrics endpoint

metrics endpoint展示了你可以追蹤的所有的度量。

{
    "names": [
        "jvm.memory.max",
        "http.server.requests",
        "process.files.max",
        ...
        "tomcat.threads.busy",
        "process.start.time",
        "tomcat.servlet.error"
    ]
}

想要獲得每個度量的詳細信息,你需要傳遞度量的名稱到URL中,像

http://localhost:8080/actuator/metrics/{MetricName}

舉個例子,獲得systems.cpu.usage的詳細信息,使用以下URLhttp://localhost:8080/actuator/metrics/system.cpu.usage。它將顯示如下內容:

{
    "name": "system.cpu.usage",
    "measurements": [
    {
        "statistic": "VALUE",
        "value": 0
    }
    ],
"availableTags": []
}

/loggers endpoint

loggers endpoint,可以通過訪問http://localhost:8080/actuator/loggers來進入。它展示了應用中可配置的loggers的列表和相關的日志等級。

你同樣能夠使用http://localhost:8080/actuator/loggers/{name}來展示特定logger的細節。

舉個例子,為了獲得root logger的細節,你可以使用http://localhost:8080/actuator/loggers/root

{
   "configuredLevel":"INFO",
   "effectiveLevel":"INFO"
}

在運行時改變日志等級

loggers endpoint也允許你在運行時改變應用的日志等級。

舉個例子,為了改變root logger的等級為DEBUG ,發送一個POST請求到http://localhost:8080/actuator/loggers/root,加入如下參數

{
   "configuredLevel": "DEBUG"
}

這個功能對於線上問題的排查非常有用。

同時,你可以通過傳遞null值給configuredLevel來重置日志等級。

/info endpoint

info endpoint展示了應用的基本信息。它通過META-INF/build-info.properties來獲得編譯信息,通過git.properties來獲得Git信息。它同時可以展示任何其他信息,只要這個環境property中含有infokey。

你可以增加properties到application.yaml中,比如:

# INFO ENDPOINT CONFIGURATION
info:
  app:
    name: @project.name@
    description: @project.description@
    version: @project.version@
    encoding: @project.build.sourceEncoding@
    java:
      version: @java.version@

 

注意,我使用了Spring Boot的Automatic property expansion 特征來擴展來自maven工程的properties。

一旦你增加上面的properties,info endpoint將展示如下信息:

{
    "app": {
    "name": "actuator",
    "description": "Demo project for Spring Boot",
    "version": "0.0.1-SNAPSHOT",
    "encoding": "UTF-8",
    "java": {
        "version": "1.8.0_161"
        }
    }
}

使用Spring Security來保證Actuator Endpoints安全

Actuator endpoints是敏感的,必須保障進入是被授權的。如果Spring Security是包含在你的應用中,那么endpoint是通過HTTP認證被保護起來的。

如果沒有, 你可以增加以下以來到你的應用中去:

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

接下去讓我們看一下如何覆寫spring security配置,並且定義你自己的進入規則。

下面的例子展示了一個簡單的spring securiy配置。它使用叫做EndPointRequest

ReqeustMatcher工廠模式來配置Actuator endpoints進入規則。

package com.example.actuator.config;

import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.boot.actuate.context.ShutdownEndpoint;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class ActuatorSecurityConfig extends WebSecurityConfigurerAdapter {

    /*
        This spring security configuration does the following

        1. Restrict access to the Shutdown endpoint to the ACTUATOR_ADMIN role.
        2. Allow access to all other actuator endpoints.
        3. Allow access to static resources.
        4. Allow access to the home page (/).
        5. All other requests need to be authenticated.
        5. Enable http basic authentication to make the configuration complete.
           You are free to use any other form of authentication.
     */

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                    .requestMatchers(EndpointRequest.to(ShutdownEndpoint.class))
                        .hasRole("ACTUATOR_ADMIN")
                    .requestMatchers(EndpointRequest.toAnyEndpoint())
                        .permitAll()
                    .requestMatchers(PathRequest.toStaticResources().atCommonLocations())
                        .permitAll()
                    .antMatchers("/")
                        .permitAll()
                    .antMatchers("/**")
                        .authenticated()
                .and()
                .httpBasic();
    }
}

 

為了能夠測試以上的配置,你可以在application.yaml中增加spring security用戶。

# Spring Security Default user name and password
spring:
  security:
    user:
      name: actuator
      password: actuator
      roles: ACTUATOR_ADMIN

你可以在Github上看到完整的代碼。

下一部分:Spring Boot Metrics監控之Prometheus&Grafana

更多學習資源

翻譯源




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM