Spring Boot Actuator集成,難的是靈活運用!
本文轉載自微信公眾號「程序新視界」,作者丑胖俠二師兄。轉載本文請聯系程序新視界公眾號。
前言
曾經看到Spring Boot Actuator這個框架時,一直在想,它到底有什么作用呢?雖然知道它提供了很多端點,有助于應用程序的監控和管理,但如果沒有直接的實踐案例,還是很難有說服力的。
直到上篇文章《微服務架構:Nacos本地緩存 PK 微服務優雅下線》中講到可以利用其中Actuator定義的端點來達到微服務的優雅下線效果,才發現Actuator是真的很有用。
那么本文便基于Spring Boot系統如何集成Actuator,如何使用,以及如何自定義一個端點(Endpoint)來展開。
Spring Boot Actuator簡介
Spring Boot Actuator是Spring Boot提供用于對應用系統進行自省和監控的功能模塊,基于此開發人員可以方便地對應用系統某些監控指標進行查看、統計、審計、指標收集等。Actuator提供了基于Http端點或JMX來管理和監視應用程序。
剛接觸Actuator朋友通常會有一個疑惑,Actuator可以通過Http端點進行訪問,那么它與Spring Web提供的@Controller的對外服務有什么區別呢?它們都可以通過Http的方式讓外部來訪問應用程序,但功能的定義邊界不同。就像上面說的Actuator通常用于應用程序本身運行情況的監控和操作,而@Controller更多的是業務層面運用。通過與@Controller這么一對照,你可能更容易理解Actuator的作用了。
Actuator默認功能
Actuator提供了一些默認的REST接口,基于這些接口我們可以很方便的了解應用程序的運行狀況。其中某些端口比較敏感,需要在指定的權限下才能進行訪問。
通過Actuator可以監控應用程序的Health健康信息、Info應用信息、HTTP Request跟蹤信息、Metrics信息、@RequestMapping的路徑信息、應用程序的各種配置信息、程序請求的次數時間等各種信息。
這里暫且不做具體端點的解釋,因為不同的版本還是有所出入的。先來看一下將所有的端點打開,然后訪問http://localhost:8080/actuator 能夠看到的端點信息。
至于你所使用的版本包含哪些端點,也采用同樣的方法來進行查看。
Spring Boot的集成
將Spring Boot Actuator集成到Spring Boot項目中是非常方便的,只需在pom文件中添加對應的依賴即可:
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-actuator</artifactId>
- </dependency>
這里采用的是Spring Boot 2.2.2.RELEASE版本。啟動項目,訪問http://localhost:8080/actuator 就可以看到目前可訪問的端口列表信息了:
- {
- "_links": {
- "self": {
- "href": "http://localhost:8080/actuator",
- "templated": false
- },
- "health-path": {
- "href": "http://localhost:8080/actuator/health/{*path}",
- "templated": true
- },
- "health": {
- "href": "http://localhost:8080/actuator/health",
- "templated": false
- },
- "info": {
- "href": "http://localhost:8080/actuator/info",
- "templated": false
- }
- }
- }
可以看出,當前版本默認支持self、health-path、health和info端點信息的訪問,其他信息是未對外開放的。
此時,如果需要查看像前面提到的全部的端點,可在application配置文件中進行如下配置:
- management:
- endpoints:
- web:
- exposure:
- include: '*'
- jmx:
- exposure:
- include: '*'
這樣便可以看到所有的端點了。此種方式是針對Spring Boot 2.0以后的版本才起效。需要注意的是配置中的*是需要添加單引號或雙引號的。
另外,這種形式的配置也是不推薦的。這樣會將所有的端點對外暴露,而沒有進行權限驗證。建議的模式是,使用到哪些端點,直接在include中明確指出。同時,敏感操作還需要進行認證。
指定配置的形式如下:
- management:
- endpoints:
- web:
- exposure:
- include: health,info
- jmx:
- exposure:
- include: health,info
不同的端點通過英文逗號分隔即可。
Endpoint的數據結構
其實最開始我們已經看了/actuator返回的數據結構了,這便是端點self的信息。在/actuator的返回信息中還可以看到其他可訪問的端點的地址,比如這里訪問http://localhost:8080/actuator/health ,結構如下:
- {
- "status": "UP"
- }
端點返回的結果為JSON格式,上面返回了status為UP的狀態,也就是說系統處于健康運行當中。當然,針對其他端點的訪問,返回結果基本一致,這里就不逐一展示了。
停服操作
在上面的端點中,你會發現并沒有關閉服務的端點。是的,默認情況下,即使include設置為“*”,依舊沒有開啟shutdown這類影響服務的操作。
針對這類操作,我們先要設置其可用:
- management:
- endpoint:
- shutdown:
- enabled: true
- endpoints:
- web:
- exposure:
- include: '*'
- jmx:
- exposure:
- include: '*'
此時,再訪問/actuator就可以看到/shutdown端點對應的路徑了http://localhost:8080/actuator/shutdown 。
通過curl命令或postman等發送一個post請求到該端點:
- curl -X "POST" "http://localhost:8080/actuator/shutdown"
執行之后,發現服務被關停了。類似停服的操作還有很多,比如restart、pause、restart等。可根據具體版本進行配置,目前版本只發現有shutdown端點,未restart、pause、restart等端點的配置項。
通過上述方式,SpringBoot應用可以優雅的關閉,但是存在很大的安全隱患,如果知道了ip、端口號后就可以模擬該請求停止服務了,因此需要增加一些安全限制。
- 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: 8080
- # 不允許遠程管理連接,安全性考慮
- address: 127.0.0.1
當然,如果此種方式并不適合你,還可以考慮引入spring-boot-starter-security,通過Spring Security來保證Actuator Endpoints的安全,此時再訪問時就需要用戶名和密碼的驗證了。關于Spring Security在本篇文章就不再拓展。
自定義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
上面只是簡單自定義實例,根據具體的業務場景,可以定義更加豐富的端點實現。
小結
通過本篇我們了解了Spring Boot集成 Actuator的基本操作。集成起來非常簡單,因為Spring Boot已經幫我們做了大多數的事情,我們只需要有針對性的進行配置即可。對于預定義端點無法滿足業務需求的情況,還可以通過自定義的形式來實現特殊化處理。學習Actuator最重要的點在于知道它的運用場景。
本文完整源碼地址:https://github.com/secbr/springboot-all/tree/master/springboot-actuator