讀古今文學網 > Spring Boot實戰 > 7.1 揭秘Actuator的端點 >

7.1 揭秘Actuator的端點

Spring Boot Actuator的關鍵特性是在應用程序裡提供眾多Web端點,通過它們瞭解應用程序運行時的內部狀況。有了Actuator,你可以知道Bean在Spring應用程序上下文裡是如何組裝在一起的,掌握應用程序可以獲取的環境屬性信息,獲取運行時度量信息的快照……

Actuator提供了13個端點,具體如表7-1所示。

表7-1 Actuator的端點

HTTP方法

路徑

描述

GET

/autoconfig

提供了一份自動配置報告,記錄哪些自動配置條件通過了,哪些沒通過

GET

/configprops

描述配置屬性(包含默認值)如何注入Bean

GET

/beans

描述應用程序上下文裡全部的Bean,以及它們的關係

GET

/dump

獲取線程活動的快照

GET

/env

獲取全部環境屬性

GET

/env/{name}

根據名稱獲取特定的環境屬性值

GET

/health

報告應用程序的健康指標,這些值由HealthIndicator的實現類提供

GET

/info

獲取應用程序的定制信息,這些信息由info打頭的屬性提供

GET

/mappings

描述全部的URI路徑,以及它們和控制器(包含Actuator端點)的映射關係

GET

/metrics

報告各種應用程序度量信息,比如內存用量和HTTP請求計數

GET

/metrics/{name}

報告指定名稱的應用程序度量值

POST

/shutdown

關閉應用程序,要求endpoints.shutdown.enabled設置為true

GET

/trace

提供基本的HTTP請求跟蹤信息(時間戳、HTTP頭等)

要啟用Actuator的端點,只需在項目中引入Actuator的起步依賴即可。在Gradle構建說明文件裡,這個依賴是這樣的:

compile 'org.springframework.boot:spring-boot-starter-actuator'

  

對於Maven項目,引入的依賴是這樣的:

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

  

亦或你使用Spring Boot CLI,可以使用如下@Grab註解:

@Grab('spring-boot-starter-actuator')

  

無論Actuator是如何添加的,在應用程序運行時自動配置都會生效。Actuator會開啟。

表7-1中的端點可以分為三大類:配置端點、度量端點和其他端點。讓我們分別瞭解一下這些端點,從提供應用程序配置信息的端點看起。

7.1.1 查看配置明細

關於Spring組件掃瞄和自動織入,最常遭人抱怨的問題之一就是很難看到應用程序中的組件是如何裝配起來的。Spring Boot自動配置讓這個問題變得更嚴重,因為Spring的配置更少了。在有顯式配置的情況下,你至少還能看到XML文件或者配置類,對Spring應用程序上下文裡的Bean關係有個大概的瞭解。

我個人從不擔心這個問題。也許是因為我意識到,在Spring出現之前,根本就沒有應用程序組件的映射關係。

但是,如果你擔心自動配置隱藏了Spring應用程序上下文中Bean的裝配細節,那麼我要告訴你一個好消息!Actuator有一些端點不僅可以顯示組件映射關係,還可以告訴你自動配置在配置Spring應用程序上下文時做了哪些決策。

1. 獲得Bean裝配報告

要瞭解應用程序中Spring上下文的情況,最重要的端點就是/beans。它會返回一個JSON文檔,描述上下文裡每個Bean的情況,包括其Java類型以及注入的其他Bean。向/beans(在本地運行時是http://localhost:8080/beans)發起GET請求後,你會看到與代碼清單7-1示例類似的信息。

代碼清單7-1 /beans端點提供的Spring應用程序上下文Bean信息

[
  {
    "beans": [
      {
        "bean": "application",      ←---Bean ID
        "dependencies": ,
        "resource": "null",
        "scope": "singleton",       ←---資源文件
        "type": "readinglist.Application$$EnhancerBySpringCGLIB$$f363c202"
      },
      {
        "bean": "amazonProperties",
        "dependencies": ,
        "resource": "URL [jar:file:/../readinglist-0.0.1-SNAPSHOT.jar!
                                      /readinglist/AmazonProperties.class]",  ←---依賴
        "scope": "singleton",
        "type": "readinglist.AmazonProperties"
      },
      {
        "bean": "readingListController",
        "dependencies": [         ←---Bean作用域
          "readingListRepository",
          "amazonProperties"
        ],
        "resource": "URL [jar:file:/../readinglist-0.0.1-SNAPSHOT.jar!
                               /readinglist/ReadingListController.class]",
        "scope": "singleton",
        "type": "readinglist.ReadingListController"
      },
      {
        "bean": "readerRepository",
        "dependencies": [
          "(inner bean)#219df4f5",
          "(inner bean)#2c0e7419",
          "(inner bean)#7d86037b",
          "jpaMappingContext"
        ],
        "resource": "null",
        "scope": "singleton",
        "type": "readinglist.ReaderRepository"     ←---Java類型
      },
      {
        "bean": "readingListRepository",
        "dependencies": [
          "(inner bean)#98ce66",
          "(inner bean)#1fd7add0",
          "(inner bean)#59faabb2",
          "jpaMappingContext"
        ],
        "resource": "null",
        "scope": "singleton",
        "type": "readinglist.ReadingListRepository"
      },
      ...
    ],
    "context": "application",
    "parent": null
  }
]

  

代碼清單7-1是閱讀列表應用程序Bean信息的一個片段。如你所見,所有的Bean條目都有五類信息。

  • bean:Spring應用程序上下文中的Bean名稱或ID。

  • resource:.class文件的物理位置,通常是一個URL,指向構建出的JAR文件。這會隨著應用程序的構建和運行方式發生變化。

  • dependencies:當前Bean注入的Bean ID列表。

  • scope:Bean的作用域(通常是單例,這也是默認作用域)。

  • type:Bean的Java類型。

雖然Bean報告不用具體繪圖告訴你Bean是如何裝配的(例如,通過屬性或構造方法),但它幫你直觀地瞭解了應用程序上下文中Bean的關係。實際上,寫出一個工具,把Bean報告處理一下,用圖形化的方式來展現Bean關係,這並不難。請注意,完整的Bean報告會包含很多Bean,還有很多自動配置的Bean,畫出來的圖會非常複雜。

2. 詳解自動配置

/beans端點產生的報告能告訴你Spring應用程序上下文裡都有哪些Bean。/autoconfig端點能告訴你為什麼會有這個Bean,或者為什麼沒有這個Bean。

正如第2章裡說的,Spring Boot自動配置構建於Spring的條件化配置之上。它提供了眾多帶有@Conditional註解的配置類,根據條件決定是否要自動配置這些Bean。/autoconfig端點提供了一個報告,列出了計算過的所有條件,根據條件是否通過進行分組。

代碼清單7-2是閱讀列表應用程序自動配置報告裡的一個片段,裡面有一個通過的條件,還有一個沒通過的條件。

代碼清單7-2 閱讀列表應用程序的自動配置報告

{
  "positiveMatches": {      ←---成功條件
  ...
  "DataSourceAutoConfiguration.JdbcTemplateConfiguration
                                                  #jdbcTemplate": [
    {
      "condition": "OnBeanCondition",
      "message": "@ConditionalOnMissingBean (types:
          org.springframework.jdbc.core.JdbcOperations;
          SearchStrategy: all) found no beans"
    }
  ],
  ...
  },
  "negativeMatches": {      ←---失敗條件
  "ActiveMQAutoConfiguration": [
    {
      "condition": "OnClassCondition",
      "message": "required @ConditionalOnClass classes not found:
         javax.jms.ConnectionFactory,org.apache.activemq
         .ActiveMQConnectionFactory"
    }
  ],
  ...
  }
}

  

positiveMatches裡,你會看到一個條件,決定Spring Boot是否自動配置JdbcTemplate Bean。匹配到的名字是DataSourceAutoConfiguration.JdbcTemplateConfiguration#jdbcTemplate,這是運用了條件的具體配置類。條件類型是OnBeanCondition,意味著條件的輸出是由某個Bean的存在與否來決定的。在本例中,message屬性已經清晰地表明了該條件是檢查是否有JdbcOperations類型(JbdcTemplate實現了該接口)的Bean存在。如果沒有配置這種Bean,則條件成立,創建一個JdbcTemplate Bean。

與之類似,在negativeMatches裡,有一個條件決定了是否要配置ActiveMQ。這是一個OnClassCondition,會檢查Classpath裡是否存在ActiveMQConnectionFactory。因為Classpath裡沒有這個類,條件不成立,所以不會自動配置ActiveMQ。

3. 查看配置屬性

除了要知道應用程序的Bean是如何裝配的,你可能還對能獲取哪些環境屬性,哪些配置屬性注入了Bean裡感興趣。

/env端點會生成應用程序可用的所有環境屬性的列表,無論這些屬性是否用到。這其中包括環境變量、JVM屬性、命令行參數,以及applicaition.properties或application.yml文件提供的屬性。

代碼清單7-3的示例代碼是/env端點獲取信息的一個片段。

代碼清單7-3 /env端點會報告所有可用的屬性

{
  "applicationConfig: [classpath:/application.yml]": {    ←---應用屬性
    "amazon.associate_id": "habuma-20",
    "error.whitelabel.enabled": false,
    "logging.level.root": "INFO"
  },
  "profiles": ,
  "servletContextInitParams": {},
  "systemEnvironment": {          ←---環境變量
    "BOOK_HOME": "/Users/habuma/Projects/BookProjects/walls6",
    "GRADLE_HOME": "/Users/habuma/.sdkman/gradle/current",
    "GRAILS_HOME": "/Users/habuma/.sdkman/grails/current",
    "GROOVY_HOME": "/Users/habuma/.sdkman/groovy/current",
    ...
  },
  "systemProperties": {      ←---JVM系統屬性
    "PID": "682",
    "file.encoding": "UTF-8",
    "file.encoding.pkg": "sun.io",
    "file.separator": "/",
    ...
  }
}

  

基本上,任何能給Spring Boot應用程序提供屬性的屬性源都會列在/env的結果裡,同時會顯示具體的屬性。

代碼清單7-3中的屬性來源有很多,包括應用程序配置(application.yml)、Spring Profile、Servlet上下文初始化參數、系統環境變量和JVM系統屬性。(本例中沒有Profile和Servlet上下文初始化參數。)

屬性常用來提供諸如數據庫或API密碼之類的敏感信息。為了避免此類信息暴露到/env裡,所有名為password、secret、key(或者名字中最後一段是這些)的屬性在/env裡都會加上「*」。舉個例子,如果有一個屬性名字是database.password,那麼它在/env中的顯示效果是這樣的:

"database.password":"******"

  

/env端點還能用來獲取單個屬性的值,只需要在請求時在/env後加上屬性名即可。舉例來說,對閱讀列表應用程序發起/env/amazon.associate_id請求,獲得的結果是habuma-20(純文本形式)。

回想第3章,這些環境屬性可以通過@ConfigurationProperties註解很方便地使用。這些環境屬性會注入帶有@ConfigurationProperties註解的Bean的實例屬性。/configprops端點會生成一個報告,說明如何進行設置(注入或其他方式)。代碼清單7-4是閱讀列表應用程序的配置屬性報告片段。

代碼清單7-4 配置屬性報告

{
  "amazonProperties": {      ←---Amazon配置
    "prefix": "amazon",
    "properties": {
      "associateId": "habuma-20"
    }
  },
  ...
  "serverProperties": {      ←---服務器配置
    "prefix": "server",
    "properties": {
      "address": null,
      "contextPath": null,
      "port": null,
      "servletPath": "/",
      "sessionTimeout": null,
      "ssl": null,
      "tomcat": {
        "accessLogEnabled": false,
        "accessLogPattern": null,
        "backgroundProcessorDelay": 30,
        "basedir": null,
        "compressableMimeTypes": "text/html,text/xml,text/plain",
        "compression": "off",
        "maxHttpHeaderSize": 0,
        "maxThreads": 0,
        "portHeader": null,
        "protocolHeader": null,
        "remoteIpHeader": null,
        "uriEncoding": null
      },
      ...
    }
  },
  ...
}

  

片段中的第一個內容是我們在第3章裡創建的amazonProperties Bean。報告顯示它添加了@ConfigurationProperties註解,前綴為amazonassociateId屬性設置為habuma-20。這是因為在application.yml裡,我們把amazon.associateId屬性設置成了habuma-20。

你還會看到一個serverProperties條目(前綴是server),還有一些屬性。它們都有默認值,你也可以通過設置server前綴的屬性來改變這些值。舉例來說,你可以通過設置server.port屬性來修改服務器監聽的端口。

除了展現運行中應用程序的配置屬性如何設置,這個報告也能作為一個快速參考指南,告訴你有哪些屬性可以設置。例如,如果你不清楚怎麼設置嵌入式Tomcat服務器的最大線程數,可以看一下配置屬性報告,裡面會有一條server.tomcat.maxThreads,這就是你要找的屬性。

4. 生成端點到控制器的映射

在應用程序相對較小的時候,很容易搞清楚控制器都映射到了哪些端點上。如果Web界面的控制器和請求處理方法數量多,那最好能有一個列表,羅列出應用程序發佈的全部端點。

/mappings端點就提供了這麼一個列表。代碼清單7-5是閱讀列表應用程序的映射報告片段。

代碼清單7-5 閱讀列表應用程序的控制器/端點映射

{
  ...

  "{[/],methods=[GET],params=,headers=,consumes=,produces=,    ←---ReadingListController映射
                                                       custom=}": {
    "bean": "requestMappingHandlerMapping",
    "method": "public java.lang.String readinglist.ReadingListController.
              readersBooks(readinglist.Reader,org.springframework.ui.Model)"
  },
  "{[/],methods=[POST],params=,headers=,consumes=,produces=,
                                                       custom=}": {
    "bean": "requestMappingHandlerMapping",
    "method": "public java.lang.String readinglist.ReadingListController
                            .addToReadingList(readinglist.Reader,readinglist.
     Book)"
  },
  "{[/autoconfig],methods=[GET],params=,headers=,consumes=   ←---自動配置報告的映射
                                          ,produces=,custom=}": {
    "bean": "endpointHandlerMapping",
    "method": "public java.lang.Object org.springframework.boot
                   .actuate.endpoint.mvc.EndpointMvcAdapter.invoke"
  },
  ...
}

  

這裡我們可以看到不少端點的映射。每個映射的鍵都是一個字符串,其內容就是Spring MVC的@RequestMapping註解上設置的屬性。實際上,這個字符串能讓你清晰地瞭解控制器是如何映射的,哪怕不看源代碼。每個映射的值都有兩個屬性:beanmethodbean屬性標識了Spring Bean的名字,映射源自這個Bean。method屬性是映射對應方法的全限定方法簽名。

頭兩個映射關乎應用程序中ReadingListController的請求如何處理。第一個表明readersBooks方法處理根路徑(/)的HTTP GET請求。第二個表明POST請求映射到addToReadingList方法上。

接下來的映射是Actuator提供的端點。/autoconfig端點的HTTP GET請求由Spring Boot的EndpointMvcAdapter類的invoke方法來處理。當然,還有很多其他Actuator的端點沒有列在代碼清單7-5里,這種省略完全是為了簡化代碼示例。

Actuator的配置端點能很方便地讓你瞭解應用程序是如何配置的。能看到應用程序在運行時究竟發生了什麼,這很有趣、很實用。度量端點能展示應用程序運行時內部狀況的快照。

7.1.2 運行時度量

你到醫生那裡體檢時,會做一系列檢查來瞭解身體狀況。有一些重要的項目永遠不會變,比如血型。這類測試能讓醫生瞭解你身體的一貫情況。其他測試讓醫生掌握你接受檢查時的身體狀況。你的心律、血壓和膽固醇水平有助於醫生評估你的健康。這些指標都是臨時的,很可能隨時間發生變化,但它們同樣是很有幫助的運行時指標。

與之類似,對運行時度量情況做一個快照,這對評估應用程序的健康情況很有幫助。Actuator提供了一系列端點,讓你能在運行時快速檢查應用程序。讓我們來瞭解一下這些端點,從/metrics開始。

1. 查看應用程序的度量值

關於運行中的應用程序,有很多有趣而且有用的信息。舉個例子,瞭解應用程序的內存情況(可用或空閒)有助於決定給JVM分配多少內存。對Web應用程序而言,不用查看Web服務器日誌,如果請求失敗或者是耗時太長,就可以大概知道內存的情況了。

運行中的應用程序有諸多計數器和度量器,/metrics端點提供了這些東西的快照。代碼清單7-6是/metrics端點輸出內容的示例。

代碼清單7-6 /metrics端點提供了很多有用的運行時數據

{
  mem: 198144,
  mem.free: 144029,
  processors: 8,
  uptime: 1887794,
  instance.uptime: 1871237,
  systemload.average: 1.33251953125,
  heap.committed: 198144,
  heap.init: 131072,
  heap.used: 54114,
  heap: 1864192,
  threads.peak: 21,
  threads.daemon: 19,
  threads: 21,
  classes: 9749,
  classes.loaded: 9749,
  classes.unloaded: 0,
  gc.ps_scavenge.count: 22,
  gc.ps_scavenge.time: 122,
  gc.ps_marksweep.count: 2,
  gc.ps_marksweep.time: 156,
  httpsessions.max: -1,
  httpsessions.active: 1,
  datasource.primary.active: 0,
  datasource.primary.usage: 0,
  counter.status.200.beans: 1,
  counter.status.200.env: 1,
  counter.status.200.login: 3,
  counter.status.200.metrics: 2,
  counter.status.200.root: 6,
  counter.status.200.star-star: 9,
  counter.status.302.login: 3,
  counter.status.302.logout: 1,
  counter.status.302.root: 5,
  gauge.response.beans: 169,
  gauge.response.env: 165,
  gauge.response.login: 3,
  gauge.response.logout: 0,
  gauge.response.metrics: 2,
  gauge.response.root: 11,
  gauge.response.star-star: 2
}

 

如你所見,/metrics端點提供了很多信息,逐行查看這些度量值太麻煩。表7-2根據所提供信息的類型對它們做了個分類。

表7-2 /metrics端點報告的度量值和計數器

分類

前綴

報告內容

垃圾收集器

gc.*

已經發生過的垃圾收集次數,以及垃圾收集所耗費的時間,適用於標記-清理垃圾收集器和並行垃圾收集器(數據源自java.lang.management.GarbageCollectorMXBean

內存

mem.*

分配給應用程序的內存數量和空閒的內存數量(數據源自java.lang.Runtime

heap.*

當前內存用量(數據源自java.lang.management.MemoryUsage

類加載器

classes.*

JVM類加載器加載與卸載的類的數量(數據源自java.lang.management.ClassLoadingMXBean

系統

processorsuptime instance.uptimesystemload.average

系統信息,例如處理器數量(數據源自java.lang.Runtime)、運行時間(數據源自java.lang.management.RuntimeMXBean)、平均負載(數據源自java.lang.management.OperatingSystemMXBean

線程池

threads.*

線程、守護線程的數量,以及JVM啟動後的線程數量峰值(數據源自java.lang .management.ThreadMXBean

數據源

datasource.*

數據源連接的數量(源自數據源的元數據,僅當Spring應用程序上下文裡存在DataSource Bean的時候才會有這個信息)

Tomcat會話

httpsessions.*

Tomcat的活躍會話數和最大會話數(數據源自嵌入式Tomcat的Bean,僅在使用嵌入式Tomcat服務器運行應用程序時才有這個信息)

HTTP

counter.status.*gauge.response.*

多種應用程序服務HTTP請求的度量值與計數器

請注意,這裡的一些度量值,比如數據源和Tomcat會話,僅在應用程序中運行特定組件時才有數據。你還可以註冊自己的度量信息,7.4.3節裡會提到這一點。

HTTP的計數器和度量值需要做一點說明。counter.status後的值是HTTP狀態碼,隨後是所請求的路徑。舉個例子,counter.status.200.metrics表明/metrics端點返回200(OK)狀態碼的次數。

HTTP的度量信息在結構上也差不多,卻在報告另一類信息。它們全部以gauge.response開頭,表明這是HTTP響應的度量信息。前綴後是對應的路徑。度量值是以毫秒為單位的時間,反映了最近處理該路徑請求的耗時。舉個例子,代碼清單7-6里的gauge.response.beans說明上一次請求耗時169毫秒。

這裡還有幾個特殊的值需要注意。root路徑指向的是根路徑或/。star-star代表了那些Spring認為是靜態資源的路徑,包括圖片、JavaScript和樣式表,其中還包含了那些找不到的資源。這就是為什麼你經常會看到counter.status.404.star-star,這是返回了HTTP 404 (NOT FOUND) 狀態的請求數。

/metrics端點會返回所有的可用度量值,但你也可能只對某個值感興趣。要獲取單個值,請求時可以在URL後加上對應的鍵名。例如,要查看空閒內存大小,可以向/metrics/mem.free發一個GET請求:

$ curl localhost:8080/metrics/mem.free
144029

  

要知道,雖然響應裡的Content-Type頭設置為application/json;charset=UTF-8,但實際/metrics/{name}的結果是文本格式的。因此,如果需要的話,你也可以把它視為JSON來處理。

2. 追蹤Web請求

儘管/metrics端點提供了一些針對Web請求的基本計數器和計時器,但那些度量值缺少詳細信息。知道所處理請求的更多信息是很有幫助的,尤其是在調試時,所以就有了/trace這個端點。

/trace端點能報告所有Web請求的詳細信息,包括請求方法、路徑、時間戳以及請求和響應的頭信息。代碼清單7-7是/trace輸出的一個片段,其中包含了整個請求跟蹤項。

代碼清單7-7 /trace端點會記錄下Web請求的細節

[
  ...
  {
    "timestamp": 1426378239775,
    "info": {
      "method": "GET",
      "path": "/metrics",
      "headers": {
        "request": {
          "accept": "*/*",
          "host": "localhost:8080",
          "user-agent": "curl/7.37.1"
        },
        "response": {
          "X-Content-Type-Options": "nosniff",
          "X-XSS-Protection": "1; mode=block",
          "Cache-Control":
                    "no-cache, no-store, max-age=0, must-revalidate",
          "Pragma": "no-cache",
          "Expires": "0",
          "X-Frame-Options": "DENY",
          "X-Application-Context": "application",
          "Content-Type": "application/json;charset=UTF-8",
          "Transfer-Encoding": "chunked",
          "Date": "Sun, 15 Mar 2015 00:10:39 GMT",
          "status": "200"
        }
      }
    }
  }
]

  

正如methodpath屬性所示,你可以看到這個跟蹤項是一個針對/metrics的請求。timestamp屬性(以及響應中的Date頭)告訴了你請求的處理時間。headers屬性的內容是請求和響應中所攜帶的頭信息。

雖然代碼清單7-7里只顯示了一條跟蹤項,但/trace端點實際能顯示最近100個請求的信息,包含對/trace自己的請求。它在內存裡維護了一個跟蹤庫。稍後在7.4.4節裡,你會看到如何創建一個自定義的跟蹤庫實現,以便將請求的跟蹤持久化。

3. 導出線程活動

在確認應用程序運行情況時,除了跟蹤請求,瞭解線程活動也會很有幫助。/dump端點會生成當前線程活動的快照。

完整的線程導出報告裡會包含應用程序的每個線程。為了節省空間,代碼清單7-8里只放了一個線程的內容片段。如你所見,其中包含很多線程的特定信息,還有線程相關的阻塞和鎖狀態。本例中,還有一個跟蹤棧(stack trace),表明這是一個Tomcat容器線程。

代碼清單7-8 /dump端點提供了應用程序線程的快照

[
  {
    "threadName": "container-0",
    "threadId": 19,
    "blockedTime": -1,
    "blockedCount": 0,
    "waitedTime": -1,
    "waitedCount": 64,
    "lockName": null,
    "lockOwnerId": -1,
    "lockOwnerName": null,
    "inNative": false,
    "suspended": false,
    "threadState": "TIMED_WAITING",
    "stackTrace": [
      {
        "className": "java.lang.Thread",
        "fileName": "Thread.java",
        "lineNumber": -2,
        "methodName": "sleep",
        "nativeMethod": true
      },
      {
        "className": "org.springframework.boot.context.embedded.
                            tomcat.TomcatEmbeddedServletContainer$1",
        "fileName": "TomcatEmbeddedServletContainer.java",
        "lineNumber": 139,
        "methodName": "run",
        "nativeMethod": false
      }
    ],
    "lockedMonitors": ,
    "lockedSynchronizers": ,
    "lockInfo": null
  },
  ...
]

  

4. 監控應用程序健康情況

如果你想知道自己的應用程序是否在運行,可以直接訪問/health端點。在最簡單的情況下,該端點會顯示一個簡單的JSON,內容如下:

{"status":"UP"}

  

status屬性顯示了應用程序在運行中。當然,它的確在運行,此處的響應無關緊要,任何輸出都說明這個應用程序在運行。但/health端點可以輸出的信息遠遠不止簡單的UP狀態。

/health端點輸出的某些信息可能涉及內容,因此對未經授權的請求只能提供簡單的健康狀態。如果經過身份驗證(比如你已經登錄了),則可以提供更多信息。下面是閱讀列表應用程序一些健康信息的示例:

{
  "status":"UP",
  "diskSpace": {
    "status":"UP",
    "free":377423302656,
    "threshold":10485760
  },
  "db":{
    "status":"UP",
    "database":"H2",
    "hello":1
  }
}

  

除了基本的健康狀態,可用的磁盤空間以及應用程序正在使用的數據庫狀態也可以看到。

/health端點所提供的所有信息都是由一個或多個健康指示器提供的。表7-3列出了Spring Boot自帶的健康指示器。

表7-3 Spring Boot自帶的健康指示器

健康指示器

報告內容

ApplicationHealthIndicator

none

永遠為UP

DataSourceHealthIndicator

db

如果數據庫能連上,則內容是UP和數據庫類型;否則為DOWN

DiskSpaceHealthIndicator

diskSpace

如果可用空間大於閾值,則內容為UP和可用磁盤空間;如果空間不足則為DOWN

JmsHealthIndicator

jms

如果能連上消息代理,則內容為UP和JMS提供方的名稱;否則為DOWN

MailHealthIndicator

mail

如果能連上郵件服務器,則內容為UP和郵件服務器主機和端口;否則為DOWN

MongoHealthIndicator

mongo

如果能連上MongoDB服務器,則內容為UP和MongoDB服務器版本;否則為DOWN

RabbitHealthIndicator

rabbit

如果能連上RabbitMQ服務器,則內容為UP和版本號;否則為DOWN

RedisHealthIndicator

redis

如果能連上服務器,則內容為UP和Redis服務器版本;否則為DOWN

SolrHealthIndicator

solr

如果能連上Solr服務器,則內容為UP;否則為DOWN

這些健康指示器會按需自動配置。舉例來說,如果Classpath裡有javax.sql.DataSource,則會自動配置DataSourceHealthIndicatorApplicationHealthIndicatorDiskSpaceHealthIndicator則會一直配置著。

除了這些自帶的健康指示器,你還會在7.4.5節裡看到如何創建自定義健康指示器。

7.1.3 關閉應用程序

假設你要關閉運行中的應用程序。比方說,在微服務架構中,你有多個微服務應用的實例運行在雲上,其中某個實例有問題了,你決定關閉該實例並讓雲服務提供商為你重啟這個有問題的應用程序。在這個場景中,Actuator的/shutdown端點就很有用了。

為了關閉應用程序,你要往/shutdown發送一個POST請求。例如,可以用命令行工具curl來關閉應用程序:

$ curl -X POST http://localhost:8080/shutdown

  

很顯然,關閉運行中的應用程序是件危險的事情,因此這個端點默認是關閉的。如果沒有顯式地開啟這個功能,那麼POST請求的結果是這樣的:

{"message":"This endpoint is disabled"}

  

要開啟該端點,可以將endpoints.shutdown.enabled設置為true。舉例來說,可以把如下內容加入application.yml,借此開啟/shutdown端點:

endpoints:
  shutdown:
    enabled: true

  

打開/shutdown端點後,你要確保並非任何人都能關閉應用程序。這時應該保護/shutdown端點,只有經過授權的用戶能關閉應用程序。在7.5節裡你將看到如何保護Actuator端點。

7.1.4 獲取應用信息

Spring Boot Actuator還有一個有用的端點。/info端點能展示各種你希望發佈的應用信息。針對該端點的GET請求的默認響應是這樣的:

{}

  

很顯然,一個空的JSON對像沒什麼用。但你可以通過配置帶有info前綴的屬性向/info端點的響應添加內容。例如,你希望在響應中添加聯繫郵箱。可以在application.yml裡設置名為info.contactEmail的屬性:

info:
  contactEmail: [email protected]

  

現在再訪問/info端點,就能得到如下響應:

{
  "contactEmail":"[email protected]"
}

  

這裡的屬性也可以是嵌套的。例如,假設你希望提供聯繫郵箱和電話。在application.yml裡可以配置如下屬性:

info:
  contact:
    email: [email protected]
    phone: 1-888-555-1971

  

/info端點返回的JSON會包含一個contact屬性,其中有emailphone屬性:

{
  "contact":{
    "email":"[email protected]",
    "phone":"1-888-555-1971"
  }
}

  

向/info端點添加屬性只是定制Actuator行為的眾多方式之一。稍後在7.4節裡,我們還會看到其他配置與擴展Actuator的方式。但現在,先讓我們來看看如何保護Actuator的端點。