SpringBoot:定製 Actuator
雖然
Actuator
提供了很多執行中
Spring Boot
應用程式的內部工作細節,但難免和你的需求有所偏差。也許你並不需要它提供的所有功能,想要關閉一些也說不定。或者,你需要對
Actuator
稍作擴充套件,增加一些自定義的度量資訊,以滿足你對應用程式的需求。
實際上,
Actuator
有多種定製方式,包括以下五項。
- 重新命名端點。
- 啟用和禁用端點。
- 自定義度量資訊。
- 建立自定義倉庫來儲存跟蹤資料。
- 插入自定義的健康指示器。
接下來,我們會了解如何定製
Actuator
,以滿足我們的需要。先來看一個最簡單的定製:重新命名
Actuator
端點。
一、修改端點 ID
每個
Actuator
端點都有一個ID用來決定端點的路徑,比方說,
/beans
端點的預設ID就是
beans
。
如果端點的路徑是由ID決定的,那麼可以透過修改ID來改變端點的路徑。你要做的就是設定一個屬性,屬性名是
endpoints.endpoint-id.id
。
我們用
/shutdown
端點來做個演示,它會響應發往
/shutdown
的
POST
請求。假設你想讓它處理發往
/kill
的POST請求,可以透過如下
YAML
為
/shutdown
賦予一個新的ID,也就是新的路徑:
endpoints:
shutdown:
id: kill
重新命名端點、修改其路徑的理由很多。最明顯的理由就是,端點的命名要和團隊的術語保持一致。你也可能想重新命名端點,讓那些熟悉預設名稱的人找不到它,藉此增加一些安全感。
遺憾的是,重新命名端點並不能真的起到保護作用,頂多是讓駭客慢點找到它們。現在先讓我們來看看如何禁用某個(或全部)不希望別人訪問的端點。
二、啟用和禁用端點
雖然
Actuator
的端點都很有用,但你不一定需要全部這些端點。預設情況下,所有端點(除了
/shutdown
)都啟用。這裡就不詳細介紹如何設定
endpoints.shutdown.enabled
為true,以此開啟
/shutdown
端點。用同樣的方式,你可以禁用其他的端點,將
endpoints. endpoint-id.enabled
設定為false。
例如,要禁用
/metrics
端點,你要做的就是將
endpoints.metrics.enabled
屬性設定為false。在
application.yml
裡做如下設定:
endpoints:
metrics:
enabled: false
如果你只想開啟一兩個端點,那就先禁用全部端點,然後啟用那幾個你要的,這樣更方便。例如,考慮如下
application.yml
片段:
endpoints:
enabled: false
metrics:
enabled: true
正如以上片段所示,
endpoints.enabled
設定為false就能禁用
Actuator
的全部端點,然後將
endpoints.metrics.enabled
設定為true重新啟用
/metrics
端點。
三、新增自定義度量資訊
你可能還想定義自己的度量,用來捕獲應用程式中的特定資訊。
比方說,我們想要知道使用者往閱讀列表裡儲存了多少次圖書,最簡單的方法就是在每次呼叫
ReadingListController的addToReadingList()
方法時增加計數器值。計數器很容易實現,但這個不斷變化的總計值如何同
/metrics
端點發布的度量資訊一起釋出出來呢?
再假設我們想要獲得最後儲存圖書的時間戳。時間戳可以透過呼叫
System.currentTime-Millis()
來獲取,但如何在
/metrics
端點裡報告該時間戳呢?
實際上,自動配置允許
Actuator
建立
CounterService
的例項,並將其註冊為
Spring
的應用程式上下文中的
Bean
。
CounterService
這個介面裡定義了三個方法,分別用來增加、減少或重置 特定名稱的度量值,程式碼如下:
package org.springframework.boot.actuate.metrics;
public interface CounterService {
void increment(String metricName);
void decrement(String metricName);
void reset(String metricName);
}
Actuator
的自動配置還會配置一個
GaugeService
型別的
Bean
。該介面與
CounterService
類似,能將某個值記錄到特定名稱的度量值裡。
GaugeService
看起來是這樣的:
package org.springframework.boot.actuate.metrics;
public interface GaugeService {
void submit(String metricName, double value);
}
你無需實現這些介面。
Spring Boot
已經提供了兩者的實現。我們所要做的就是把它們的例項注入所需的
Bean
,在適當的時候呼叫其中的方法,更新想要的度量值。
針對上文提到的需求,我們需要把
CounterService
和
GaugeService Bean
注入
Reading-ListController
,然後在
addToReadingList()
方法裡呼叫其中的方法。
使用注入的
CounterService
和
GaugeService
@Controller
@RequestMapping("/")
@ConfigurationProperties("amazon")
public class ReadingListController {
...
private CounterService counterService;
@Autowired
public ReadingListController(
ReadingListRepository readingListRepository,
AmazonProperties amazonProperties,
CounterService counterService,
GaugeService gaugeService) {
this.readingListRepository = readingListRepository;
this.amazonProperties = amazonProperties;
this.counterService = counterService;
this.gaugeService = gaugeService;
}
...
@RequestMapping(method=RequestMethod.POST)
public String addToReadingList(Reader reader, Book book) {
book.setReader(reader);
readingListRepository.save(book);
counterService.increment("books.saved");
gaugeService.submit(
"books.last.saved", System.currentTimeMillis());
return "redirect:/";
}
}
修改後的
ReadingListController
使用了自動織入機制,透過控制器的構造方法注入
CounterService
和
GaugeService
,隨後把它們儲存在例項變數裡。此後,
addToReading-List()
方法每次處理請求時都會呼叫
counterService.increment ("books.saved")
和
gaugeService.submit("books. last.saved")
來調整度量值。
儘管
CounterService
和
GaugeService
用起來很簡單,但還是有一些度量值很難透過增加計數器或記錄指標值來捕獲。對於那些情況,我們可以實現
PublicMetrics
介面,提供自己需要的度量資訊。該介面定義了一個
metrics()
方法,返回一個
Metric
物件的集合:
package org.springframework.boot.actuate.endpoint;
public interface PublicMetrics {
Collection<Metric<?>> metrics();
}
為了解
PublicMetrics
的使用方法,這裡假設我們想報告一些源自
Spring
應用程式上下文的度量值——應用程式上下文啟動的時間、Bean及Bean定義的數量,這些都包含進來會很有意思。 順便再報告一下新增了
@Controller
註解的
Bean
的數量。
釋出自定義度量資訊
package readinglist;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.PublicMetrics;
import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
@Component
public class ApplicationContextMetrics implements PublicMetrics {
private ApplicationContext context;
@Autowired
public ApplicationContextMetrics(ApplicationContext context) {
this.context = context;
}
@Override
public Collection<Metric<?>> metrics() {
List<Metric<?>> metrics = new ArrayList<Metric<?>>();
metrics.add(new Metric<Long>("spring.context.startup-date",
context.getStartupDate()));
metrics.add(new Metric<Integer>("spring.beans.definitions",
context.getBeanDefinitionCount()));
metrics.add(new Metric<Integer>("spring.beans",
context.getBeanNamesForType(Object.class).length));
metrics.add(new Metric<Integer>("spring.controllers",
context.getBeanNamesForAnnotation(Controller.class).length));
return metrics;
}
}
Actuator
會呼叫
metrics()
方法,收集
ApplicationContextMetrics
提供的度量資訊。該方法呼叫了所注入的
ApplicationContext
上的方法,獲取我們想要報告為度量的數量。每個度量值都會建立一個
Metrics
例項,指定度量的名稱和值,將其加入要返回的列表。
建立
ApplicationContextMetrics
,並在
ReadingListController
裡使用
Counter-Service
和
GaugeService
之後,我們可以在
/metrics
端點的響應中找到如下條目:
{
...
spring.context.startup-date: 1429398980443,
spring.beans.definitions: 261,
spring.beans: 272,
spring.controllers: 2,
books.count: 1,
gauge.books.save.time: 1429399793260,
...
}
當然,這些度量的實際值會根據新增了多少書、何時啟動應用程式及何時儲存最後一本書而發生變化。在這個例子裡,你一定會好奇為什麼
spring.controllers
是2。因為這裡算上了
ReadingListController
以及
Spring Boot
提供的
BasicErrorController
。
四、建立自定義跟蹤倉庫
預設情況下,
/trace
端點報告的跟蹤資訊都儲存在記憶體倉庫裡,100個條目封頂。一旦倉庫滿了,就開始移除老的條目,給新的條目騰出空間。在開發階段這沒什麼問題,但在生產環境中,大流量會造成跟蹤資訊還沒來得及看就被丟棄。
為了避免這個問題,你可以宣告自己的
InMemoryTraceRepository Bean
,將它的容量調整至100以上。如下配置類可以將容量調整至1000個條目:
package readinglist;
import org.springframework.boot.actuate.trace.InMemoryTraceRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ActuatorConfig {
@Bean
public InMemoryTraceRepository traceRepository() {
InMemoryTraceRepository traceRepo = new InMemoryTraceRepository();
traceRepo.setCapacity(1000);
return traceRepo;
}
}
倉庫容量翻了10倍,跟蹤資訊的儲存時間應該會更久。不過,繁忙到一定程度,應用程式還是可能在你檢視這些資訊前將其丟棄。這是一個記憶體儲存的倉庫,還要避免容量增長太多,影響應用程式的記憶體使用。
除了上述方法,我們還可以將那些跟蹤條目儲存在其他地方——既不消耗記憶體,又能長久儲存的地方。只需實現
Spring Boot
的
TraceRepository
介面即可:
package org.springframework.boot.actuate.trace;
import java.util.List;
import java.util.Map;
public interface TraceRepository {
List<Trace> findAll();
void add(Map<String, Object> traceInfo);
}
如你所見,
TraceRepository
只要求我們實現兩個方法:一個方法查詢所有儲存的
Trace
物件,另一個儲存了一個
Trace
,包含跟蹤資訊的
Map
物件。
作為演示,假設我們建立了一個使用
MongoDB
資料庫儲存跟蹤資訊的
TraceRepository
例項。
往
MongoDB
儲存跟蹤資料
package readinglist; import java.util.Date;
import java.util.List; import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.trace.Trace;
import org.springframework.boot.actuate.trace.TraceRepository;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.stereotype.Service;
@Service
public class MongoTraceRepository implements TraceRepository {
private MongoOperations mongoOps;
@Autowired
public MongoTraceRepository(MongoOperations mongoOps) {
this.mongoOps = mongoOps;
}
@Override
public List<Trace> findAll() {
return mongoOps.findAll(Trace.class);
}
@Override
public void add(Map<String, Object> traceInfo) {
mongoOps.save(new Trace(new Date(), traceInfo));
} }
findAll()
方法很直白,用注入的
MongoOperations
來查詢全部
Trace
物件。
add()
方法稍微有趣一點,用當前時間和含有跟蹤資訊的
Map
建立了一個
Trace
物件,然後透過
MongoOperations.save()
將其儲存下來。唯一的問題是,
MongoOperations
是哪裡來的?
為了使用
MongoTraceRepository
,我們需要保證
Spring
應用程式上下文裡先有一個
MongoOperations Bean
。得益於
Spring Boot
的起步依賴和自動配置,做到這一點只需新增
MongoDB
起步依賴即可。你需要如下
Gradle
依賴:
compile("org.springframework.boot:spring-boot-starter-data-mongodb")
如果你用的是
Maven
,則需要如下依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency>
新增了這個起步依賴後,
Spring Data MongoDB
和所依賴的庫會新增到應用程式的
Classpath
裡。
Spring Boot
會自動配置所需的
Bean
,以便使用
MongoDB
資料庫。這些
Bean
裡就包括
MongoOperations
。另外,你需要確保和
MongoOperations
通訊的
MongoDB
伺服器正常執行。
參考資料:《SpringBoot實戰筆記》
需要這份筆記的朋友可以加助理VX:C18173184271,免費獲取!
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69964492/viewspace-2764905/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- SpringBoot Actuator — 埋點和監控Spring Boot
- 使用SpringBoot Actuator監控應用Spring Boot
- SpringBoot整合Actuator進行健康監控Spring Boot
- SpringBoot 教程之 banner 定製Spring Boot
- SpringBoot如何利用Actuator來監控應用?Spring Boot
- 【web】springboot應用增加actuator管理端點WebSpring Boot
- springboot 07 Spring Boot Actuator: Production-ready featuresSpring Boot
- springboot中圖示的定製Spring Boot
- SpringBoot彩蛋之定製啟動畫面Spring Boot動畫
- 聊聊springboot專案如何實現自定義actuator端點Spring Boot
- SpringBoot第二十二篇:應用監控之ActuatorSpring Boot
- Camera Actuator bringup
- spring-boot-actuatorSpringboot
- SpringBoot物件複製Spring Boot物件
- Spring Boot Actuator詳解與深入應用(二):Actuator 2.xSpring Boot
- Spring Boot Actuator詳解與深入應用(一):Actuator 1.xSpring Boot
- 括展actuator health check
- Spring Boot Actuator 整合 PrometheusSpring BootPrometheus
- actuator 學習筆記筆記
- Springboot mini - Solon詳解(八)- Solon的快取框架使用和定製Spring Boot快取框架
- 給你的SpringBoot專案定製一個牛年專屬banner吧Spring Boot
- SpringBoot定時任務Spring Boot
- springboot:定時任務Spring Boot
- 定製Tinycore
- springMVC中增加spring-boot-actuatorSpringMVCboot
- Springboot mini - Solon詳解(六)- Solon的校驗框架使用、定製與擴充套件Spring Boot框架套件
- springboot設定UTF-8Spring Boot
- springboot定時任務之旅Spring Boot
- springboot定時任務@ScheduledSpring Boot
- SpringBoot 定時任務ScheduledSpring Boot
- springboot(九):定時任務Spring Boot
- Dockerfile定製映象Docker
- SpringBoot整合Quartz定時任務Spring Bootquartz
- Drawable圖形定製
- 禮品茶葉定製
- Swift iOS : 定製CellSwiftiOS
- 使用 Dockerfile 定製映象Docker
- springcloud學習筆記(五)Spring Cloud ActuatorSpringGCCloud筆記