Spring boot——Actuator 詳解


 

一、什么是 Actuator

Spring Boot Actuator 模塊提供了生產級別的功能,比如健康檢查,審計,指標收集,HTTP 跟蹤等,幫助我們監控和管理Spring Boot 應用。

這個模塊是一個采集應用內部信息暴露給外部的模塊,上述的功能都可以通過HTTP 和 JMX 訪問。

因為暴露內部信息的特性,Actuator 也可以和一些外部的應用監控系統整合(PrometheusGraphiteDataDogInfluxWavefrontNew Relic等)。

這些監控系統提供了出色的儀表板,圖形,分析和警報,可幫助你通過一個統一友好的界面,監視和管理你的應用程序。

Actuator使用Micrometer與這些外部應用程序監視系統集成。這樣一來,只需很少的配置即可輕松集成外部的監控系統。

Micrometer 為 Java 平台上的性能數據收集提供了一個通用的 API,應用程序只需要使用 Micrometer 的通用 API 來收集性能指標即可。
Micrometer 會負責完成與不同監控系統的適配工作。這就使得切換監控系統變得很容易。

需要注意的是:

SpringBoot 1.x 和 2.x 的 Actuator 監控設定差超多,不僅提供的 endpoint 路徑不一樣,連 application.properties 的配置也不一樣,此處介紹的為 SpringBoot 2.x 版本。

 

二、集成 Actuator

如果要使用 SpringBoot Actuator 提供的監控功能,需要先加入相關的 maven dependency:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

只要加上了這個 maven dependency,SpringBoot 在運行時就會自動開啟/actuator/health/actuator/info這兩個 endpoint,我們就可以透過這兩個 endpoint 查看當前 SpringBoot 運行的情況。

Actuator 其實還提供更多樣化的 endpoint 讓我們監控 SpringBoot Application,但是因為安全因素,所以需要另外設置才能打開這些 endpoint,詳細的設置方式下面解說。

訪問http://localhost:8099/actuator,查看暴露出來的端點:

 

三、Endpoints 介紹

Spring Boot 提供了所謂的 endpoints (下文翻譯為端點)給外部來與應用程序進行訪問和交互。

打比方來說,/health 端點 提供了關於應用健康情況的一些基礎信息。metrics 端點提供了一些有用的應用程序指標(JVM 內存使用、系統CPU使用等)。

這些 Actuator 模塊本來就有的端點我們稱之為原生端點。根據端點的作用的話,我們大概可以分為三大類:

  • 應用配置類:獲取應用程序中加載的應用配置、環境變量、自動化配置報告等與Spring Boot應用密切相關的配置類信息。
  • 度量指標類:獲取應用程序運行過程中用於監控的度量指標,比如:內存信息、線程池信息、HTTP請求統計等。
  • 操作控制類:提供了對應用的關閉等操作類功能。

需要注意的就是:

  • 每一個端點都可以通過配置來單獨禁用或者啟動
  • 不同於Actuator 1.x,Actuator 2.x 的大多數端點默認被禁掉。 Actuator 2.x 中的默認端點增加了/actuator前綴。默認暴露的兩個端點為/actuator/health和 /actuator/info

Actuator 提供的所有 endpoint:

此處使用的是 SpringBoot 2.2.8 版本,Spring 官方文件

HTTP方法 Endpoint 描述
GET /actuator 查看有哪些 Actuator endpoint 是開放的
GET /actuator/auditevent 查看 audit 的事件,例如認證進入、訂單失敗,需要搭配 Spring security 使用,sample code
GET /actuator/beans 查看運行當下裡面全部的 bean,以及他們的關係
GET /actuator/conditions 查看自動配置的結果,記錄哪些自動配置條件通過了,哪些沒通過
GET /actuator/configprops 查看注入帶有 @ConfigurationProperties 類的 properties 值為何(包含默認值)
GET /actuator/env (常用) 查看全部環境屬性,可以看到 SpringBoot 載入了哪些 properties,以及這些 properties 的值(但是會自動*掉帶有 key、password、secret 等關鍵字的 properties 的值,保護安全資訊)
GET /actuator/flyway 查看 flyway DB 的 migration 資訊
GET /actuator/health (常用) 查看當前 SpringBoot 運行的健康指標,值由 HealthIndicator 的實現類提供(所以可以自定義一些健康指標資訊,加到這裡面)
GET /actuator/heapdump 取得 JVM 當下的 heap dump,會下載一個檔案
GET /actuator/info 查看 properties 中 info 開頭的屬性的值,沒啥用
GET /actuator/mappings 查看全部的 endpoint(包含 Actuator 的),以及他們和 Controller 的關係
GET /actuator/metrics(常用) 查看有哪些指標可以看(ex: jvm.memory.max、system.cpu.usage),要再使用/actuator/metrics/{metric.name}分別查看各指標的詳細資訊
GET /actuator/scheduledtasks 查看定時任務的資訊
POST /actuator/shutdown 唯一一個需要 POST 請求的 endpoint,關閉這個 SpringBoot 程式

 

四、端點配置

  • 默認暴露

我們可以通過以下配置,來配置通過JMX 和 HTTP 暴露的端點。

Property Default
management.endpoints.jmx.exposure.exclude  
management.endpoints.jmx.exposure.include *
management.endpoints.web.exposure.exclude  
management.endpoints.web.exposure.include info, healt

因為安全的因素,所以 Actuator 默認只會開放/actuator/health/actuator/info這兩個 endpoint,如果要開放其他 endpoint 的話,需要額外在 application.properties 中做設置。

  • 暴露配置
# 可以這樣寫,就會開啟所有endpoints(不包含shutdown)
management.endpoints.web.exposure.include=*

# 也可以這樣寫,就只會開啟指定的endpoint,因此此處只會再額外開啟/actuator/beans和/actuator/mappings
management.endpoints.web.exposure.include=beans,mappings

# exclude可以用來關閉某些endpoints
# exclude通常會跟include一起用,就是先include了全部,然後再exclude /actuator/beans這個endpoint
management.endpoints.web.exposure.exclude=beans
management.endpoints.web.exposure.include=*

# 如果要開啟/actuator/shutdown,要額外再加這一行
management.endpoint.shutdown.enabled=true
  • 路徑映射

默認情況下所有端點都暴露在“/actuator”路徑下,也可以改變/actuator的路徑,可以自定義成自己想要的:

#這樣寫的話,原本內建的/actuator/xxx路徑,都會變成/manage/xxx,可以用來防止被其他人猜到
management.endpoints.web.base-path=/manage

#同時可以將health修改成healthcheck
management.endpoints.web.path-mapping.health=healthcheck
  • 管理端口調整
#指定端口,默認跟server.port一樣,可以防止被其他人猜到
management.server.port=10111
  • 端點響應緩存

 對於一些不帶參數的端點請求會自動進行緩存,我們可以通過如下方式配置緩存時間,下面配置表示 beans 端點的緩存時間為 100s

management.endpoint.beans.cache.time-to-live=100s

 

五、端點保護

如果開啟了 Actuator 默認不打開的 endpoints,建議一定要加上 Spring security 之類的做 endpoint 保護,避免重要資訊外洩。因為端點的信息和產生的交互都是非常敏感的,必須防止未經授權的外部訪問。

這里我們使用 Spring Security 保護,首先添加相關依賴:

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

添加之后,我們需要定義安全校驗規則,來覆蓋Spring Security 的默認配置。

這里我給出了兩個版本的模板配置:

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 { /* * version1: * 1. 限制 '/shutdown'端點的訪問,只允許ACTUATOR訪問 * 2. 允許外部訪問其他的端點 * 3. 允許外部訪問靜態資源 * 4. 允許外部訪問 '/' * 5. 其他的訪問需要被校驗 * version2: * 1. 限制所有端點的訪問,只允許ACTUATOR訪問 * 2. 允許外部訪問靜態資源 * 3. 允許外部訪問 '/' * 4. 其他的訪問需要被校驗 */ @Override protected void configure(HttpSecurity http) throws Exception { // version1 // http // .authorizeRequests() // .requestMatchers(EndpointRequest.to(ShutdownEndpoint.class)) // .hasRole("ADMIN") // .requestMatchers(EndpointRequest.toAnyEndpoint()) // .permitAll() // .requestMatchers(PathRequest.toStaticResources().atCommonLocations()) // .permitAll() // .antMatchers("/") // .permitAll() // .antMatchers("/**") // .authenticated() // .and() // .httpBasic(); // version2  http .authorizeRequests() .requestMatchers(EndpointRequest.toAnyEndpoint()) .hasRole("ADMIN") .requestMatchers(PathRequest.toStaticResources().atCommonLocations()) .permitAll() .antMatchers("/") .permitAll() .antMatchers("/**") .authenticated() .and() .httpBasic(); } }

application.properties的相關配置如下:

# Spring Security Default user name and password
spring.security.user.name=actuator spring.security.user.password=actuator spring.security.user.roles=ADMIN
我們使用瀏覽器訪問 http://localhost:8080/actuator/health 端點接口,會先彈出個登錄框,只有登錄后才能訪問。

 

六、重要端點解析

/health 端點

  • /health配置

當我們開啟health的健康端點時,我們能夠查到應用健康信息是一個匯總的信息,訪問 http://127.0.0.1:10111/actuator/health時,我們獲取到的信息是{"status":"UP"},status的值還有可能是 DOWN

要想查看詳細的應用健康信息需要配置:
management.endpoint.health.show-details=always
該屬性可以使用以下值之一進行配置:
  1. never:不展示詳細信息,up或者down的狀態,默認配置
  2. when-authorized:詳細信息將會展示給通過認證的用戶。授權的角色可以通過management.endpoint.health.roles配置
  3. always:對所有用戶暴露詳細信息
按照上述配置,配置成 always之后,我們啟動項目再次訪問  http://127.0.0.1:10111/actuator/health,獲取的信息如下:
{
    "status": "UP",
    "details": {
        "diskSpace": {
            "status": "UP",
            "details": {
                "total": 250685575168,
                "free": 172252426240,
                "threshold": 10485760
            }
        },
        "redis": {
            "status": "UP",
            "details": {
                "version": "3.2.11"
            }
        },
        "db": {
            "status": "UP",
            "details": {
                "database": "Oracle",
                "hello": "Hello"
            }
        }
    }
}
從上面的應用的詳細健康信息發現,健康信息包含 磁盤空間redisDB,啟用監控的這個spring boot應用確實是連接了redis和oracle DB,actuator就自動給監控起來了,確實是很方便、很有用。

/health端點有很多自動配置的健康指示器:如redis、rabbitmq、db等組件。當你的項目有依賴對應組件的時候,這些健康指示器就會被自動裝配,繼而采集對應的信息。

如上面的 diskSpace 節點信息就是DiskSpaceHealthIndicator 在起作用。

上述截圖取自官方文檔

當如上的組件有一個狀態異常,應用服務的整體狀態即為down。我們也可以通過配置禁用某個組件的健康監測。
management.health.mongo.enabled: false

或者禁用所有自動配置的健康指示器:

management.health.defaults.enabled: false
  • /health原理
Spring boot的健康信息都是從 ApplicationContext中的各種 HealthIndicator Beans中收集到的,Spring boot框架中包含了大量的 HealthIndicators的實現類,當然你也可以實現自己認為的健康狀態。
默認情況下,最終的spring boot應用的狀態是由 HealthAggregator匯總而成的,匯總的算法是:
  1. 設置狀態碼順序:setStatusOrder(Status.DOWN, Status.OUT_OF_SERVICE, Status.UP, Status.UNKNOWN)
  2. 過濾掉不能識別的狀態碼。
  3. 如果無任何狀態碼,整個spring boot應用的狀態是 UNKNOWN
  4. 將所有收集到的狀態碼按照 1 中的順序排序。
  5. 返回有序狀態碼序列中的第一個狀態碼,作為整個spring boot應用的狀態。

源代碼請參見:org.springframework.boot.actuate.health.OrderedHealthAggregator

Spring boot框架自帶的  HealthIndicators 目前包括:
Name Description
CassandraHealthIndicator Checks that a Cassandra database is up.
DiskSpaceHealthIndicator Checks for low disk space.
DataSourceHealthIndicator Checks that a connection to DataSource can be obtained.
ElasticsearchHealthIndicator Checks that an Elasticsearch cluster is up.
InfluxDbHealthIndicator Checks that an InfluxDB server is up.
JmsHealthIndicator Checks that a JMS broker is up.
MailHealthIndicator Checks that a mail server is up.
MongoHealthIndicator Checks that a Mongo database is up.
Neo4jHealthIndicator Checks that a Neo4j server is up.
RabbitHealthIndicator Checks that a Rabbit server is up.
RedisHealthIndicator Checks that a Redis server is up.
SolrHealthIndicator Checks that a Solr server is up.
你可以通過 management.health.defaults.enabled這個配置項將它們全部禁用掉,也可以通過 management.health.xxxx.enabled將其中任意一個禁用掉。
  • 自定義 HealthIndicator
有時候需要提供自定義的健康狀態檢查信息,你可以通過實現 HealthIndicator的接口來實現,並將該實現類注冊為spring bean。
你需要實現其中的 health()方法,並返回自定義的健康狀態響應信息,該響應信息應該包括一個狀態碼和要展示詳細信息。
例如,下面就是一個接口 HealthIndicator的實現類:
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;

@Component
public class MyHealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
        int errorCode = check(); // perform some specific health check
        if (errorCode != 0) {
            return Health.down().withDetail("Error Code", errorCode).build();
        }
        return Health.up().build();
    }

}
另外,除了Spring boot定義的幾個狀態類型,我們也可以自定義狀態類型,用來表示一個新的系統狀態。
在這種情況下,你還需要實現接口 HealthAggregator ,或者通過配置 management.health.status.order 來繼續使用 HealthAggregator的默認實現。
例如,在你自定義的健康檢查 HealthIndicator的實現類中,使用了自定義的狀態類型 FATAL,為了配置該狀態類型的嚴重程度,你需要在application的配置文件中添加如下配置:
management.health.status.order=FATAL, DOWN, OUT_OF_SERVICE, UNKNOWN, UP
在做健康檢查時,響應中的HTTP狀態碼反應了整體的健康狀態,(例如, UP 對應 200, 而 OUT_OF_SERVICE DOWN 對應 503)。
同樣,你也需要為自定義的狀態類型設置對應的HTTP狀態碼,例如,下面的配置可以將 FATAL 映射為 503(服務不可用):
management.health.status.http-mapping.FATAL=503

如果你需要更多的控制,你可以定義自己的 HealthStatusHttpMapper bean。

下面是內置健康狀態類型對應的HTTP狀態碼列表:

Status Mapping
DOWN SERVICE_UNAVAILABLE (503)
OUT_OF_SERVICE SERVICE_UNAVAILABLE (503)
UP No mapping by default, so http status is 200
UNKNOWN No mapping by default, so http status is 200

/metrics 端點

  • 查看所有可追蹤的度量

/metrics端點用來返回當前應用的各類重要度量指標,比如:內存信息、線程信息、垃圾回收信息、tomcat、數據庫連接池等。

{
  "names": [
    "hikaricp.connections",
    "hikaricp.connections.acquire",
    "hikaricp.connections.active",
    "hikaricp.connections.creation",
    "hikaricp.connections.idle",
    "hikaricp.connections.max",
    "hikaricp.connections.min",
    "hikaricp.connections.pending",
    "hikaricp.connections.timeout",
    "hikaricp.connections.usage",
    "jvm.buffer.count",
    "jvm.buffer.memory.used",
    "jvm.buffer.total.capacity",
    "jvm.classes.loaded",
    "jvm.classes.unloaded",
    "jvm.gc.live.data.size",
    "jvm.gc.max.data.size",
    "jvm.gc.memory.allocated",
    "jvm.gc.memory.promoted",
    "jvm.gc.pause",
    "jvm.memory.committed",
    "jvm.memory.max",
    "jvm.memory.used",
    "jvm.threads.daemon",
    "jvm.threads.live",
    "jvm.threads.peak",
    "jvm.threads.states",
    "logback.events",
    "process.cpu.usage",
    "process.start.time",
    "process.uptime",
    "system.cpu.count",
    "system.cpu.usage",
    "tomcat.cache.access",
    "tomcat.cache.hit",
    "tomcat.global.error",
    "tomcat.global.received",
    "tomcat.global.request",
    "tomcat.global.request.max",
    "tomcat.global.sent",
    "tomcat.servlet.error",
    "tomcat.servlet.request",
    "tomcat.servlet.request.max",
    "tomcat.sessions.active.current",
    "tomcat.sessions.active.max",
    "tomcat.sessions.alive.max",
    "tomcat.sessions.created",
    "tomcat.sessions.expired",
    "tomcat.sessions.rejected",
    "tomcat.threads.busy",
    "tomcat.threads.config.max",
    "tomcat.threads.current",
    "zipkin.reporter.messages",
    "zipkin.reporter.messages.total",
    "zipkin.reporter.queue.bytes",
    "zipkin.reporter.queue.spans",
    "zipkin.reporter.spans",
    "zipkin.reporter.spans.dropped",
    "zipkin.reporter.spans.total"
  ]
}

各個指標說明如下:

序號 參數 參數說明 是否監控 監控手段 重要度
JVM
1 jvm.memory.max JVM 最大內存      
2 jvm.memory.committed JVM 可用內存 展示並監控堆內存和 Metaspace 重要
3 jvm.memory.used JVM 已用內存 展示並監控堆內存和 Metaspace 重要
4 jvm.buffer.memory.used JVM 緩沖區已用內存      
5 jvm.buffer.count 當前緩沖區數      
6 jvm.threads.daemon JVM 守護線程數 顯示在監控頁面  
7 jvm.threads.live JVM 當前活躍線程數 顯示在監控頁面;監控達到閾值時報警 重要
8 jvm.threads.peak JVM 峰值線程數 顯示在監控頁面  
9 jvm.classes.loaded 加載 classes 數      
10 jvm.classes.unloaded 未加載的 classes 數      
11 jvm.gc.memory.allocated GC 時,年輕代分配的內存空間      
12 jvm.gc.memory.promoted GC 時,老年代分配的內存空間      
13 jvm.gc.max.data.size GC 時,老年代的最大內存空間      
14 jvm.gc.live.data.size FullGC 時,老年代的內存空間      
15 jvm.gc.pause GC 耗時 顯示在監控頁面  
TOMCAT
16 tomcat.sessions.created tomcat 已創建 session 數      
17 tomcat.sessions.expired tomcat 已過期 session 數      
18 tomcat.sessions.active.current tomcat 活躍 session 數      
19 tomcat.sessions.active.max tomcat 最多活躍 session 數 顯示在監控頁面,超過閾值可報警或者進行動態擴容 重要
20 tomcat.sessions.alive.max.second tomcat 最多活躍 session 數持續時間      
21 tomcat.sessions.rejected 超過 session 最大配置后,拒絕的 session 個數 顯示在監控頁面,方便分析問題  
22 tomcat.global.error 錯誤總數 顯示在監控頁面,方便分析問題  
23 tomcat.global.sent 發送的字節數      
24 tomcat.global.request.max request 最長時間      
25 tomcat.global.request 全局 request 次數和時間      
26 tomcat.global.received 全局 received 次數和時間      
27 tomcat.servlet.request servlet 的請求次數和時間      
28 tomcat.servlet.error servlet 發生錯誤總數      
29 tomcat.servlet.request.max servlet 請求最長時間      
30 tomcat.threads.busy tomcat 繁忙線程 顯示在監控頁面,據此檢查是否有線程夯住  
31 tomcat.threads.current tomcat 當前線程數(包括守護線程) 顯示在監控頁面 重要
32 tomcat.threads.config.max tomcat 配置的線程最大數 顯示在監控頁面 重要
33 tomcat.cache.access tomcat 讀取緩存次數      
34 tomcat.cache.hit tomcat 緩存命中次數      
CPU
35 system.cpu.count CPU 數量      
36 system.load.average.1m load average 超過閾值報警 重要
37 system.cpu.usage 系統 CPU 使用率      
38 process.cpu.usage 當前進程 CPU 使用率 超過閾值報警  
39 http.server.requests http 請求調用情況 顯示 10 個請求量最大,耗時最長的 URL;統計非 200 的請求量 重要
40 process.uptime 應用已運行時間 顯示在監控頁面  
41 process.files.max 允許最大句柄數 配合當前打開句柄數使用  
42 process.start.time 應用啟動時間點 顯示在監控頁面  
43 process.files.open 當前打開句柄數 監控文件句柄使用率,超過閾值后報警 重要
  • 查看某個度量的詳細信息

不同於1.x,Actuator在這個界面看不到具體的指標信息,只是展示了一個指標列表。為了獲取到某個指標的詳細信息,我們可以請求具體的指標信息,像這樣:

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

比如我訪問/actuator/metrics/jvm.memory.max,返回信息如下:

你也可以用query param的方式查看單獨的一塊區域。比如你可以訪問/actuator/metrics/jvm.memory.max?tag=id:Metaspace。結果就是:

  • 添加自定義統計指標
除了使用 metrics 端點默認的這些統計指標外,我們還可以實現自定義統計指標。Metrics 提供 4 種基本的度量類型:Gauge、Counter、Timer、Summary。下面分別進行介紹。

1,Gauge(計量器)

Gauge(計量器)是最簡單的度量類型,只有一個簡單的返回值,他用來記錄一些對象或者事物的瞬時值。

(1)假設我們在一個 Contoller 使用一個類型為 Gauge 的計數器來記錄一個數值:
@RestController
public class HelloController { 
    @GetMapping("/hello")
    public void hello() {
        Metrics.gauge("user.test.gauge", 3);
    }
}

(2)通過 /actuator/metrics 接口可以看到我們自定義的這個指標:

(3)假設我們訪問了 /hello 接口后,再次通過 /actuator/metrics/user.test.gauge 這個自定義度量的消息信息,顯示如下:
 

2,Counter(計數器)

Counter(計數器)簡單理解就是一種只增不減的計數器。它通常用於記錄服務的請求數量、完成的任務數量、錯誤的發生數量等等。

(1)為方便使用首先我們自定義一個計數器服務:

@Service
public class MyCounterService {
    static final Counter userCounter = Metrics.counter("user.counter.total", "services", "demo"); 
    public void processCollectResult() {
        userCounter.increment(1D);
    }
}

(2)然后增加一個 controller,觸發這個服務:

@RestController
public class HelloController {
 
    @Autowired
    MyCounterService myCounterService;
 
    @GetMapping("/hello")
    public void hello() {
        myCounterService.processCollectResult();
    }
}

(3)通過 /actuator/metrics 接口可以看到我們自定義的這個指標:

(4)假設我們訪問了 3 次 /hello 接口,再次通過 /actuator/metrics/user.counter.total 這個自定義度量的消息信息,顯示如下:

3,Timer(計時器)

Timer(計時器)可以同時測量一個特定的代碼邏輯塊的調用(執行)速度和它的時間分布。

簡單來說,就是在調用結束的時間點記錄整個調用塊執行的總時間,適用於測量短時間執行的事件的耗時分布,例如消息隊列消息的消費速率。

(1)假設我們在一個 Contoller 使用 Timer 來記錄某個方法的執行時長:

注意:在實際生產環境中,可以通過 spring-aop 把記錄方法耗時的邏輯抽象到一個切面中,這樣就能減少不必要的冗余的模板代碼。

@RestController
public class HelloController {
 
    private Timer timer = Metrics.timer("user.test.timer","timer", "timersample");
 
    @GetMapping("/hello")
    public void hello() {
 
        // 執行createOrder方法並記錄執行時間
        timer.record(() -> createOrder());
    }
 
    //模擬方法耗時
    private void createOrder() {
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
        }
    }
}

(2)假設我們訪問了 3 次 /hello 接口,再次通過 /actuator/metrics/user.test.timer 這個自定義度量的消息信息,顯示如下:

 

4,Summary(摘要)

Summary(摘要)用於跟蹤事件的分布。它類似於一個計時器,但更一般的情況是,它的大小並不一定是一段時間的測量值。

在 micrometer 中,對應的類是 DistributionSummary,它的用法有點像 Timer,但是記錄的值是需要直接指定,而不是通過測量一個任務的執行時間。

(1)假設我們在一個 Contoller 使用 Summary 來連續記錄三次值:

@RestController
public class HelloController {
 
    private DistributionSummary summary = Metrics.summary("user.test.summary","summary", "summarysample");
 
    @GetMapping("/hello")
    public void hello() {
        summary.record(2D);
        summary.record(3D);
        summary.record(4D);
    }
}

(2)假設我們訪問 /hello 接口后,再次通過 /actuator/metrics/user.test.summary 這個自定義度量的消息信息,顯示如下:

/loggers 端點

  • 查看日志等級

/loggers 端點暴露了我們程序內部配置的所有logger的信息。我們訪問/actuator/loggers可以看到:

你也可以通過下述方式訪問單獨一個logger:

http://localhost:8080/actuator/loggers/{name}

比如我現在訪問 root logger,http://localhost:8080/actuator/loggers/root:

{
    "configuredLevel": "INFO",
    "effectiveLevel": "INFO"
}
  • 改變運行時日志等級

/loggers端點能夠動態修改你的日志等級。

比如,我們可以通過下述方式來修改 root logger的日志等級。我們只需要發起一個URL 為http://localhost:8080/actuator/loggers/rootPOST請求,POST報文如下:

{
   "configuredLevel": "DEBUG"
}

仔細想想,這個功能是不是非常有用。如果在生產環境中,你想要你的應用輸出一些Debug信息以便於你診斷一些異常情況,你只需要按照上述方式就可以修改,而不需要重啟應用。

如果想重置成默認值,把value 改成  null

/info 端點

/info端點可以用來展示應用信息,主要包含三大類:自定義信息、Git 信息、以及項目構建信息。下面主要介紹自定義信息。

(1)自定義信息可以在 application.properties 配置文件中添加,這些以 info 開頭的信息將在 info 端點中顯示出來:

info.app.name=actuator-test-demo
info.app.encoding=UTF-8
info.app.java.source=1.8
info.app.java.target=1.8

啟動項目,訪問http://localhost:8080/actuator/info

{
    "app": {
        "encoding": "UTF-8",
        "java": {
            "source": "1.8.0_131",
            "target": "1.8.0_131"
        },
        "name": "actuator-test-demo"
    }
}

(2)我們也可以通過 Java 代碼自定義信息,只需要將自定義類繼承自 InfoContributor,然后實現該類中的 contribute 方法即可:

@Component
public class MyInfo implements InfoContributor {
    @Override
    public void contribute(Info.Builder builder) {
        Map<String, String> info = new HashMap<>();
        info.put("name", "航歌");
        info.put("email", "service@hangge.com");
        builder.withDetail("author", info);
    }
}

/beans 端點

/beans端點會返回Spring 容器中所有bean的別名、類型、是否單例、依賴等信息。

訪問http://localhost:8080/actuator/beans,返回如下:

/heapdump 端點

訪問:http://localhost:8080/actuator/heapdump會自動生成一個 Jvm 的堆文件 heapdump。我們可以使用 JDK 自帶的 Jvm 監控工具 VisualVM 打開此文件查看內存快照。

/threaddump 端點

這個端點我個人覺得特別有用,方便我們在日常定位問題的時候查看線程的情況。 主要展示了線程名、線程ID、線程的狀態、是否等待鎖資源、線程堆棧等信息。就是可能查看起來不太直觀。
訪問 http://localhost:8080/actuator/threaddump返回如下:

這個端點屬於操作控制類端點,可以優雅關閉 Spring Boot 應用。要使用這個功能首先需要在配置文件中開啟:

management.endpoint.shutdown.enabled=true

由於 shutdown 接口默認只支持 POST 請求,我們啟動Demo項目,發起POST請求:

curl -X "POST" "http://localhost:8080/actuator/shutdown"

返回信息:

{
    "message": "Shutting down, bye..."
}

然后應用程序被關閉。類似停服的操作還有很多,比如restart、pause等。可根據具體版本進行配置。

由於開放關閉應用的操作本身是一件非常危險的事,所以真正在線上使用的時候,我們需要對其加入一定的保護機制,

比如:定制Actuator的端點路徑、整合Spring Security進行安全校驗等。(不是特別必要的話,這個端點不用開)。

定制Actuator的端點路徑和端口:

  • management.endpoints.web.base-path 自定義shutdown的請求路徑;

  • management.server.address 設置為本地ip,防止遠程訪問該連接進行關閉服務;

  • management.server.port 自定義shutdown請求路徑的端口號;

調整后的配置文件如下:

management:
  endpoint:
    shutdown:
      enabled: true
  endpoints:
    web:
      exposure:
        include: '*'
    jmx:
      exposure:
        include: '*'
  server:
    # 自定義端口
    port: 8888
    # 不允許遠程管理連接,安全性考慮
    address: 127.0.0.1

 

七、自定義Endpoint

默認的端點雖然可以滿足大多數的需求,但一些特殊的需求還是需要能夠支持自定義端點的。

自定義 Endpoint 端點,只需要在我們的新建Bean上使用 @Endpoint 注解即可, Bean 中的方法就可以通過 JMX 或者 HTTP 公開。

除此之外,還可以使用 @JmxEndpoint 或 @WebEndpoint 編寫 EndPoint。但這些 EndPoint 僅限於各自的公開方式。例如,@WebEndpoint 僅通過HTTP公開,而不通過JMX公開。

那么是不是類中所有的方法都支持對外公開呢?

很明顯不是的。Actuator提供了三個用於方法上的注解,只有加三個注解的方法才支持對外公開,並且每個注解都有支持它的HTTP method。

  • @ReadOperation對應HTTP的GET請求
  • @WriteOperation對應HTTP的POST請求
  • @DeleteOperation對應HTTP的DELETE請求

來看一個簡單的使用實例:

@Component
@Endpoint(id = "my")
public class EndpointCustom {

   @ReadOperation
   public String endpointCustomRead(String content) {
      return "請求的內容: " + content;
   }

   @WriteOperation
   public String endpointCustomWrite(String content) {
      return "寫的內容: " + content;
   }

   @DeleteOperation
   public String endpointCustomDelete(String content) {
      return "刪除的內容: " + content;
   }

}

對應GET請求:

curl -X GET http://localhost:8080/actuator/my?content=endpointGet

執行之后,會返回信息“請求的內容: endpointGet”。

同樣的POST請求為:

curl -X POST http://localhost:8080/actuator/my?content=endpointPost

DELETE請求為:

curl -X DELETE http://localhost:8080/actuator/my?content=endpointDELETE

上面只是簡單自定義實例,根據具體的業務場景,可以定義更加豐富的端點實現。

 
 
引用:


免責聲明!

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



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