文章目录
一、认识Actuator
1、回顾Actuator
Actuator是Springboot提供运行时数据交互的规范。
它覆盖应用内心戏、环境配置、度量指标、敏感操作。
交互方式为Http Web或者JMX。
Spring Boot Actuator ——健康检查神器
2、Actuator重要端点
二、源码分析
1、Endpoint自动装配
(1)自动配置入口
(2)普通Endpoint自动装配
@AutoConfiguration
@ConditionalOnAvailableEndpoint(endpoint = EnvironmentEndpoint.class) // EnvironmentEndpoint可用
@EnableConfigurationProperties(EnvironmentEndpointProperties.class)// 构建属性配置文件
public class EnvironmentEndpointAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic 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
进行自动装配。
// 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映射。
// 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)自动装配类
@AutoConfiguration
@ConditionalOnAvailableEndpoint(endpoint = BeansEndpoint.class)
public class BeansEndpointAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic BeansEndpoint beansEndpoint(ConfigurableApplicationContext applicationContext) {// 创建一个BeansEndpointreturn new BeansEndpoint(applicationContext);}}
(2)BeansEndpoint
// id就是可以访问的web路径
@Endpoint(id = "beans")
public class BeansEndpoint {
// 读操作
@ReadOperation
public ApplicationBeans beans() {Map<String, ContextBeans> contexts = new HashMap<>();// 将所有容器都拿出来ConfigurableApplicationContext context = this.context;while (context != null) {// 将Bean都拿出来,封装成一个ContextBeanscontexts.put(context.getId(), ContextBeans.describing(context));context = getConfigurableParent(context);}// 创建一个ApplicationBeans// 返回的信息就会json格式化到响应return new ApplicationBeans(contexts);
}
// 返回的对象
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)自动装配类
@AutoConfiguration
@ConditionalOnAvailableEndpoint(endpoint = MappingsEndpoint.class)
public class MappingsEndpointAutoConfiguration {// 配置Mapping@Beanpublic MappingsEndpoint mappingsEndpoint(ApplicationContext applicationContext,ObjectProvider<MappingDescriptionProvider> descriptionProviders) {return new MappingsEndpoint(descriptionProviders.orderedStream().collect(Collectors.toList()),applicationContext);}// 后面还有关于Servlet的相关配置,此处就先不看
(2)MappingsEndpoint
// web访问路径
@Endpoint(id = "mappings")
public class MappingsEndpoint {
// 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) {// 查找所有的MappingcontextMappings.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)自动装配类
@AutoConfiguration
@ConditionalOnAvailableEndpoint(endpoint = ShutdownEndpoint.class)
public class ShutdownEndpointAutoConfiguration {@Bean(destroyMethod = "")@ConditionalOnMissingBeanpublic ShutdownEndpoint shutdownEndpoint() {return new ShutdownEndpoint();}}
(2)ShutdownEndpoint
// 默认是不开启的,因为安全性要求极高
@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;// 写操作@WriteOperationpublic 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();}@Overridepublic void setApplicationContext(ApplicationContext context) throws BeansException {if (context instanceof ConfigurableApplicationContext) {this.context = (ConfigurableApplicationContext) context;}}}