@[TOC]
一、认识Actuator
1、回顾Actuator
Actuator是Springboot提供运行时数据交互的规范。 它覆盖应用内心戏、环境配置、度量指标、敏感操作。 交互方式为Http Web或者JMX。
Spring Boot Actuator ------健康检查神器
2、Actuator重要端点
二、源码分析
1、Endpoint自动装配
(1)自动配置入口
(2)普通Endpoint自动装配
java
@AutoConfiguration
@ConditionalOnAvailableEndpoint(endpoint = EnvironmentEndpoint.class) // EnvironmentEndpoint可用
@EnableConfigurationProperties(EnvironmentEndpointProperties.class)// 构建属性配置文件
public class EnvironmentEndpointAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public EnvironmentEndpoint environmentEndpoint(Environment environment, EnvironmentEndpointProperties properties,
ObjectProvider<SanitizingFunction> sanitizingFunctions) {
EnvironmentEndpoint endpoint = new EnvironmentEndpoint(environment,
sanitizingFunctions.orderedStream().collect(Collectors.toList()));
String[] keysToSanitize = properties.getKeysToSanitize();
if (keysToSanitize != null) {
endpoint.setKeysToSanitize(keysToSanitize);
}
String[] additionalKeysToSanitize = properties.getAdditionalKeysToSanitize();
if (additionalKeysToSanitize != null) {
endpoint.keysToSanitize(additionalKeysToSanitize);
}
return endpoint;
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(EnvironmentEndpoint.class)
@ConditionalOnAvailableEndpoint(exposure = { EndpointExposure.WEB, EndpointExposure.CLOUD_FOUNDRY })
public EnvironmentEndpointWebExtension environmentEndpointWebExtension(EnvironmentEndpoint environmentEndpoint) {
return new EnvironmentEndpointWebExtension(environmentEndpoint);
}
}
(3)配置Web - Endpoint
通过自动配置类WebEndpointAutoConfiguration
进行自动装配。
java
// org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration#webEndpointDiscoverer
@Bean
@ConditionalOnMissingBean(WebEndpointsSupplier.class)
public WebEndpointDiscoverer webEndpointDiscoverer(ParameterValueMapper parameterValueMapper,
EndpointMediaTypes endpointMediaTypes, ObjectProvider<PathMapper> endpointPathMappers,
ObjectProvider<OperationInvokerAdvisor> invokerAdvisors,
ObjectProvider<EndpointFilter<ExposableWebEndpoint>> filters) {
// 把所有的Web - Endpoint都搜集到
return new WebEndpointDiscoverer(this.applicationContext, parameterValueMapper, endpointMediaTypes,
endpointPathMappers.orderedStream().collect(Collectors.toList()),
invokerAdvisors.orderedStream().collect(Collectors.toList()),
filters.orderedStream().collect(Collectors.toList()));
}
(4)注册Endpoint为Mvc映射
通过自动配置类WebMvcEndpointManagementContextConfiguration
注册Endpoint为Mvc映射。
通过各种方式定义的Endpoint,创建为WebMvcEndpointHandlerMapping,进行Web映射。
java
// org.springframework.boot.actuate.autoconfigure.endpoint.web.servlet.WebMvcEndpointManagementContextConfiguration#webEndpointServletHandlerMapping
@Bean
@ConditionalOnMissingBean
public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier,
ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier,
EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties,
WebEndpointProperties webEndpointProperties, Environment environment) {
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
allEndpoints.addAll(webEndpoints);
allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
String basePath = webEndpointProperties.getBasePath();
EndpointMapping endpointMapping = new EndpointMapping(basePath);
boolean shouldRegisterLinksMapping = shouldRegisterLinksMapping(webEndpointProperties, environment, basePath);
return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes,
corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath),
shouldRegisterLinksMapping, WebMvcAutoConfiguration.pathPatternParser);
}
2、BeansEndpoint自动装配原理
(1)自动装配类
java
@AutoConfiguration
@ConditionalOnAvailableEndpoint(endpoint = BeansEndpoint.class)
public class BeansEndpointAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public BeansEndpoint beansEndpoint(ConfigurableApplicationContext applicationContext) {
// 创建一个BeansEndpoint
return new BeansEndpoint(applicationContext);
}
}
(2)BeansEndpoint
java
// id就是可以访问的web路径
@Endpoint(id = "beans")
public class BeansEndpoint {
java
// 读操作
@ReadOperation
public ApplicationBeans beans() {
Map<String, ContextBeans> contexts = new HashMap<>();
// 将所有容器都拿出来
ConfigurableApplicationContext context = this.context;
while (context != null) {
// 将Bean都拿出来,封装成一个ContextBeans
contexts.put(context.getId(), ContextBeans.describing(context));
context = getConfigurableParent(context);
}
// 创建一个ApplicationBeans
// 返回的信息就会json格式化到响应
return new ApplicationBeans(contexts);
}
java
// 返回的对象
public static final class ApplicationBeans {
private final Map<String, ContextBeans> contexts;
private ApplicationBeans(Map<String, ContextBeans> contexts) {
this.contexts = contexts;
}
public Map<String, ContextBeans> getContexts() {
return this.contexts;
}
}
(3)执行结果
3、MappingsEndpoint自动装配原理
(1)自动装配类
java
@AutoConfiguration
@ConditionalOnAvailableEndpoint(endpoint = MappingsEndpoint.class)
public class MappingsEndpointAutoConfiguration {
// 配置Mapping
@Bean
public MappingsEndpoint mappingsEndpoint(ApplicationContext applicationContext,
ObjectProvider<MappingDescriptionProvider> descriptionProviders) {
return new MappingsEndpoint(descriptionProviders.orderedStream().collect(Collectors.toList()),
applicationContext);
}
// 后面还有关于Servlet的相关配置,此处就先不看
(2)MappingsEndpoint
java
// web访问路径
@Endpoint(id = "mappings")
public class MappingsEndpoint {
java
// org.springframework.boot.actuate.web.mappings.MappingsEndpoint#mappings
@ReadOperation
public ApplicationMappings mappings() {
ApplicationContext target = this.context;
Map<String, ContextMappings> contextMappings = new HashMap<>();
while (target != null) {
// 查找所有的Mapping
contextMappings.put(target.getId(), mappingsForContext(target));
target = target.getParent();
}
return new ApplicationMappings(contextMappings);// 返回的信息就会json格式化到响应
}
// org.springframework.boot.actuate.web.mappings.MappingsEndpoint#mappingsForContext
private ContextMappings mappingsForContext(ApplicationContext applicationContext) {
Map<String, Object> mappings = new HashMap<>();
this.descriptionProviders.forEach(
(provider) -> mappings.put(provider.getMappingName(), provider.describeMappings(applicationContext)));
return new ContextMappings(mappings,
(applicationContext.getParent() != null) ? applicationContext.getId() : null);
}
(3)执行结果
4、ShutdownEndpoint自动装配原理
(1)自动装配类
java
@AutoConfiguration
@ConditionalOnAvailableEndpoint(endpoint = ShutdownEndpoint.class)
public class ShutdownEndpointAutoConfiguration {
@Bean(destroyMethod = "")
@ConditionalOnMissingBean
public ShutdownEndpoint shutdownEndpoint() {
return new ShutdownEndpoint();
}
}
(2)ShutdownEndpoint
java
// 默认是不开启的,因为安全性要求极高
@Endpoint(id = "shutdown", enableByDefault = false)
public class ShutdownEndpoint implements ApplicationContextAware {
private static final Map<String, String> NO_CONTEXT_MESSAGE = Collections
.unmodifiableMap(Collections.singletonMap("message", "No context to shutdown."));
private static final Map<String, String> SHUTDOWN_MESSAGE = Collections
.unmodifiableMap(Collections.singletonMap("message", "Shutting down, bye..."));
private ConfigurableApplicationContext context;
// 写操作
@WriteOperation
public Map<String, String> shutdown() {
if (this.context == null) {
return NO_CONTEXT_MESSAGE; // 返回的信息就会json格式化到响应
}
try {
return SHUTDOWN_MESSAGE;
}
finally {
// 另起一个线程进行shutdown操作,目的是优雅关机。
Thread thread = new Thread(this::performShutdown);
thread.setContextClassLoader(getClass().getClassLoader());
thread.start();
}
}
private void performShutdown() {
try {
// 暂停500毫秒
Thread.sleep(500L);
}
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
// 执行Spring容器关闭操作
this.context.close();
}
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
if (context instanceof ConfigurableApplicationContext) {
this.context = (ConfigurableApplicationContext) context;
}
}
}