《Spring Boot Actuator詳解與深刻應用》預計包括三篇,第一篇重點講Spring Boot Actuator 1.x的應用與定製端點;第二篇將會對比Spring Boot Actuator 2.x 與1.x的區別,以及應用和定製2.x的端點;第三篇將會介紹Actuator metric指標與Prometheus和Grafana的使用結合。這部份內容很經常使用,且較爲入門,歡迎你們的關注。html
本文系《Spring Boot Actuator詳解與深刻應用》中的第二篇。在上一篇文章:Spring Boot Actuator詳解與深刻應用(一):Actuator 1.x主要講了Spring Boot Actuator 1.x的應用與定製端點。Spring Boot2.0的正式版已經發布有一段時間了,目前已經到了2.1.0.RELEASE
。關於Spring Boot2.x的特性,在此不詳細敘述了,可是其流行的趨勢是顯而易見的。java
本文將會對比Spring Boot Actuator 2.x 與1.x的區別,以及應用和定製2.x的端點。重點介紹最新的2.x版本的Actuator。react
Actuator 2.x繼續保持其基本功能,但簡化其模型,擴展其功能幷包含合適的默認值。首先,這個版本變得與特定框架解耦;此外,它經過將其與應用程序合併來簡化其安全模型;最後,在各類變化中,有些變化是巨大的,這包括HTTP請求/響應以及提供的Java API。此外,最新版本支持CRUD模型,而不是舊的RW(讀/寫)模型。git
在Actuator 1.x中,它與Spring MVC綁定,所以與Servlet API相關聯。而在2.x中,Actuator定義了它的模型可插拔且可擴展,而不依賴於MVC。所以,經過這個新模型,咱們能夠像MVC同樣使用WebFlux做爲底層Web技術。此外,之後的框架能夠經過實現特定的適配器來增長到這個模型中。在沒有任何額外的代碼的狀況下,JMX仍然支持暴露端點。github
引入以下的依賴:web
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
複製代碼
和使用的Spring Boot Actuator 1.x並無太大的區別。redis
不一樣於以前的Actuator 1.x,Actuator 2.x 的大多數端點默認被禁掉。 Actuator 2.x 中的默認端點增長了/actuator前綴。spring
默認暴露的兩個端點爲/actuator/health 和 /actuator/info。咱們能夠經過設置以下的屬性:數據庫
management.endpoints.web.exposure.include=*
複製代碼
可使得全部的端點暴露出來。此外,咱們也能夠列出須要暴露的端點或者排除某些端點。如:json
management.endpoints.web.exposure.exclude=env,beans
複製代碼
下面咱們看一下可用的端點,他們大部分在1.x中已經存在。儘管如此,有些端點新增,有些被刪除,有些被重構。
@ConfigurationProperties
的bean對象Actuator端點是敏感的,必須防止未經受權的訪問。 若是應用程序中存在Spring Security,則默認狀況下使用基於表單的HTTP基自己份驗證來保護端點。使用Spring Security保護Actuator的端點訪問。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
複製代碼
爲了應用Actuator的安全規則,咱們增長以下的配置:
@Bean
public SecurityWebFilterChain securityWebFilterChain( ServerHttpSecurity http) {
return http.authorizeExchange()
.pathMatchers("/actuator/**").permitAll()
.anyExchange().authenticated()
.and().build();
}
複製代碼
如上的配置使得全部訪問/actuator開頭的URL都必須是登陸的狀態。咱們還可使用更加細化的配置:
@Configuration
public class ActuatorSecurityConfig extends WebSecurityConfigurerAdapter {
@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();
}
}
複製代碼
如上的配置主要實現了:
爲了可以使用HTTP基自己份驗證測試上述配置,能夠添加默認的spring安全性用戶:
spring:
security:
user:
name: actuator
password: actuator
roles: ACTUATOR_ADMIN
複製代碼
與之前的版本同樣,咱們能夠輕鬆添加自定義指標。建立自定義健康端點的抽象保持不變。與Spring Boot 1.x不一樣,endpoints.<id> .sensitive
屬性已被刪除。/health端點公開的運行情況信息取決於:
management.endpoint.health.show-details
複製代碼
該屬性可使用如下值之一進行配置:
management.endpoint.health.roles
配置。/health端點有不少自動配置的健康指示器:如redis、rabbitmq等組件。
management.health.mongo.enabled: false
複製代碼
或者禁用全部自動配置的健康指示器:
management.health.defaults.enabled: false
複製代碼
除此以外,還添加了新的接口ReactiveHealthIndicator
以實現響應式運行情況檢查。
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</dependency>
複製代碼
@Component
public class DownstreamServiceHealthIndicator implements ReactiveHealthIndicator {
@Override
public Mono<Health> health() {
return checkDownstreamServiceHealth().onErrorResume(
ex -> Mono.just(new Health.Builder().down(ex).build())
);
}
private Mono<Health> checkDownstreamServiceHealth() {
// we could use WebClient to check health reactively
return Mono.just(new Health.Builder().up().build());
}
}
複製代碼
健康指標的一個便利功能是咱們能夠將它們聚合爲層次結構的一部分。 所以,按照上面的示例,咱們能夠將全部下游服務分組到下游服務類別下。只要每一個嵌套服務均可以訪問,這次訪問就是健康的。
在Spring Boot 2.0中,有一個bean類型爲MeterRegistry
將會被自動配置,而且MeterRegistry
已經包含在Actuator的依賴中。以下爲咱們得到的/metrics端點信息。
{
"names": [
"jvm.gc.pause",
"jvm.buffer.memory.used",
"jvm.memory.used",
"jvm.buffer.count",
// ...
]
}
複製代碼
能夠看到,不一樣於1.x,咱們已經看不到具體的指標信息,只是展現了一個指標列表。爲了獲取到某個指標的詳細信息,咱們能夠請求具體的指標信息,如/actuator/metrics/jvm.gc.pause
{
"name": "jvm.gc.pause",
"description": "Time spent in GC pause",
"baseUnit": "seconds",
"measurements": [{
"statistic": "COUNT",
"value": 2.0
}, {
"statistic": "TOTAL_TIME",
"value": 0.07300000000000001
}, {
"statistic": "MAX",
"value": 0.0
}],
"availableTags": [{
"tag": "cause",
"values": ["Metadata GC Threshold"]
}, {
"tag": "action",
"values": ["end of minor GC", "end of major GC"]
}]
}
複製代碼
咱們能夠看到,如今的指標要詳細得多。不只包括不一樣的值,還包括一些相關的元數據。
/info端點沒有什麼變化,咱們能夠經過maven或者gradle引入依賴,增長git的詳細信息。
<dependency>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
</dependency>
複製代碼
一樣的,咱們可使用maven和gradle的插件,獲取到構建的name,group和version(須要類路徑下存在META-INF/build-info.properties文件)。
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
複製代碼
咱們能夠自定義端點,Spring Boot 2已經更新了自定義端點的方法,下面咱們定義一個能夠查詢、開啓或者關閉features標誌位的端點。
@Component
@Endpoint(id = "features")
public class FeaturesEndpoint {
private Map<String, Feature> features = new ConcurrentHashMap<>();
@ReadOperation
public Map<String, Feature> features() {
return features;
}
@ReadOperation
public Feature feature(@Selector String name) {
return features.get(name);
}
@WriteOperation
public void configureFeature(@Selector String name, Feature feature) {
features.put(name, feature);
}
@DeleteOperation
public void deleteFeature(@Selector String name) {
features.remove(name);
}
public static class Feature {
private Boolean enabled;
//...
}
}
複製代碼
定義的端點路徑由@Endpoint
中的id屬性決定,在如上的例子中,請求的端點地址爲/actuator/features
。並用以下的方法註解來定義操做:
啓動應用,能夠看到控制檯多了以下的日誌輸出:
[...].WebFluxEndpointHandlerMapping: Mapped "{[/actuator/features/{name}], methods=[GET], produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
[...].WebFluxEndpointHandlerMapping : Mapped "{[/actuator/features], methods=[GET], produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
[...].WebFluxEndpointHandlerMapping : Mapped "{[/actuator/features/{name}], methods=[POST], consumes=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
[...].WebFluxEndpointHandlerMapping : Mapped "{[/actuator/features/{name}], methods=[DELETE]}"[...]
複製代碼
如上的日誌展現了Webflux如何暴露咱們的端點,至於切換到Spring MVC,咱們只須要引入依賴便可,並不須要更改任何代碼。
以前方法上的元數據信息(sensitive, enabled)都不在使用了,開啓或禁用端點,使用@Endpoint(id = 「features」, enableByDefault = false)
。相比於舊的讀寫模型,咱們可使用@DeleteOperation
定義DELETE操做。
咱們還能夠經過註解@EndpointExtension
擴展事先定義好的端點,更精確的註解爲:@EndpointWebExtension
,@EndpointJmxExtension
。
@Component
@EndpointWebExtension(endpoint = InfoEndpoint.class)
public class InfoWebEndpointExtension {
private InfoEndpoint delegate;
@Autowired
public InfoWebEndpointExtension(InfoEndpoint delegate) {
this.delegate = delegate;
}
@ReadOperation
public WebEndpointResponse<Map> info() {
Map<String, Object> info = this.delegate.info();
Integer status = getStatus(info);
return new WebEndpointResponse<>(info, status);
}
private Integer getStatus(Map<String, Object> info) {
// return 5xx if this is a snapshot
return 200;
}
}
複製代碼
本文主要講了Actuator 2.x相關特性和使用,對比了與Actuator 1.x 在使用上的區別。Actuator 2.x不依賴於某個框架組件(如Spring MVC),作到了易於插拔和擴展。當咱們想要切換到Webflux時,經過Actuator 2.x中的適配器,不須要更改任何代碼便可實現。 本文源碼:github.com/keets2012/S…