目录
Actuator模块可以采集应用内部运行信息暴露给外部,帮助我们监控和管理Spring Boot 应用,功能例如健康检查,运行指标收集,HTTP 跟踪,日志级别等
-
- #开放所有端点
-
- management.endpoints.web.exposure.include=*
-
-
- #开放指定端点
-
- management.endpoints.web.exposure.include=beans
-
- 或者
-
- management.endpoint.beans.enabled=true
-
-
-
- #开放所有 && 关闭某个
-
- management.endpoints.web.exposure.exclude=beans
-
- management.endpoints.web.exposure.include=*
-
-
-
- 默认情况下所有端点都暴露在“/actuator”路径下,可以自定义
-
- #/actuator/xxx路徑,都变成/manage/xxx
-
- management.endpoints.web.base-path=/manage
-
-
- #管理端口调整
-
- management.server.port=9999
今天记录我涉及的常用EndPoint,以后有用到其他的随时再记
| GET | /actuator | 查看有哪些 Actuator endpoint 是开放的,和对应的路径 |
| GET | /actuator/beans | 查看容器中的 bean |
| GET | /actuator/health | 查看当前应用指标情况,实现HealthIndicator可以自定义指标项 |
| GET | /actuator/loggers | 查看当前应用日志级别情况,可以运行时调整 |
| GET | /actuator/info | 应用信息展示 |
| GET | /actuator/threaddump | 当前应用线程栈dump,同 jstack |
如下代码
@Endpoint注解 定义一个监控端点类,id就是路径(/actuator/myendpoint)
@Component 扫描并交给容器管理
@ReadOperation 代表GET请求处理方法 ,@WriteOperation代表POST请求处理方法
- @Endpoint(id = "myendpoint")
- @Component
- public class MyEndPoint implements ApplicationContextAware {
-
- private ApplicationContext app;
-
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- this.app = applicationContext;
- }
-
- @ReadOperation
- public Map
invokeGet() { - Map
ret = new HashMap<>(); -
- // 自定义监控逻辑
- ret.put("type", "get");
- ret.put("status", "okk");
- ret.put("details", "nothing to do");
- return ret;
- }
-
- @WriteOperation
- public Map
invokePost() { - Map
ret = new HashMap<>(); -
- // 自定义监控逻辑
- ret.put("type", "post");
- ret.put("status", "okk");
- ret.put("details", "nothing to do");
- return ret;
- }
- }


加载所有EndPoint并由DispatcherServlet路由的源码位置: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
> allEndpoints = new ArrayList<>(); -
- // 这里查询bean容器中所有注解了@Endpoint的类
- Collection
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 = StringUtils.hasText(basePath)
- || ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT);
-
- // WebMvcEndpointHandlerMapping继承了AbstractHandlerMethodMapping
- // 将每个Endpoint和其中的get/post方法封装为handlermethod,由springmvc在请求时路由
- return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes,
- corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath),
- shouldRegisterLinksMapping);
- }
返回当前应用所有父子容器中的bean信息,如下图

源码实现类为 org.springframework.boot.actuate.beans.BeansEndpoint,比较简单就是从ApplicationContext挨个取出BeanDefinition,把部分信息封装到Map返回
- @Endpoint(id = "beans")
- public class BeansEndpoint {
-
- private final ConfigurableApplicationContext context;
-
- public BeansEndpoint(ConfigurableApplicationContext context) {
- this.context = context;
- }
-
- @ReadOperation
- public ApplicationBeans beans() {
- // 循环把父子容器的bean信息放到map中返回
- Map
contexts = new HashMap<>(); - ConfigurableApplicationContext context = this.context;
- while (context != null) {
- contexts.put(context.getId(), ContextBeans.describing(context));
- context = getConfigurableParent(context);
- }
- return new ApplicationBeans(contexts);
- }
-
- private static Map
describeBeans(ConfigurableListableBeanFactory beanFactory) { - Map
beans = new HashMap<>(); - for (String beanName : beanFactory.getBeanDefinitionNames()) {
- BeanDefinition definition = beanFactory.getBeanDefinition(beanName);
- if (isBeanEligible(beanName, definition, beanFactory)) {
- beans.put(beanName, describeBean(beanName, definition, beanFactory));
- }
- }
- return beans;
- }
- }
各个组件的运行状况

内置了很多组件的检测器如下,

也可以自定义实现其他组件的健康检测类
- @Component
- public class RocketMQHealthIndicator extends AbstractHealthIndicator {
-
- @Override
- protected void doHealthCheck(Health.Builder builder) throws Exception {
- // 自定义逻辑
-
- // 展示信息
- builder.status(Status.UP);
- builder.withDetail("aaaa", "aaaa");
- builder.withDetail("bbbb", "bbbb");
- builder.withDetail("cccc", "cccc");
- }
- }
查看当前应用日志级别情况,可以动态改变

如下应用层代码:


首先访问/actuator/loggers路径,可以得到如下结果,目前日志级别是INFO

执行输出test111方法如图:

访问POST请求如下,可以动态改变日志级别,改为DEBUG级别

访问后再次执行test111方法如图:无需重启应用,非常方便生产环境使用

自定义显示程序信息,有两种方式定制 info 信息
一种就是在application.properties配置文件中配置如下:

访问端点返回如下
另一种代码形式,实现InfoContributor接口


与jstack工具一样,展示当前应用所有线程堆栈
