• SpringBoot Actuator监控组件笔记


    目录

    自定义EndPoint

    /beans

    /health

    /loggers 

    /info

    /threaddump 


    Actuator模块可以采集应用内部运行信息暴露给外部,帮助我们监控和管理Spring Boot 应用,功能例如健康检查,运行指标收集,HTTP 跟踪,日志级别等

    1. #开放所有端点
    2. management.endpoints.web.exposure.include=*
    3. #开放指定端点
    4. management.endpoints.web.exposure.include=beans
    5. 或者
    6. management.endpoint.beans.enabled=true
    7. #开放所有  &&  关闭某个
    8. management.endpoints.web.exposure.exclude=beans
    9. management.endpoints.web.exposure.include=*
    10. 默认情况下所有端点都暴露在“/actuator”路径下,可以自定义
    11. #/actuator/xxx路徑,都变成/manage/xxx
    12. management.endpoints.web.base-path=/manage
    13. #管理端口调整
    14. 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

    如下代码

    @Endpoint注解 定义一个监控端点类,id就是路径(/actuator/myendpoint)

    @Component 扫描并交给容器管理

    @ReadOperation 代表GET请求处理方法 ,@WriteOperation代表POST请求处理方法

    1. @Endpoint(id = "myendpoint")
    2. @Component
    3. public class MyEndPoint implements ApplicationContextAware {
    4. private ApplicationContext app;
    5. @Override
    6. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    7. this.app = applicationContext;
    8. }
    9. @ReadOperation
    10. public Map invokeGet() {
    11. Map ret = new HashMap<>();
    12. // 自定义监控逻辑
    13. ret.put("type", "get");
    14. ret.put("status", "okk");
    15. ret.put("details", "nothing to do");
    16. return ret;
    17. }
    18. @WriteOperation
    19. public Map invokePost() {
    20. Map ret = new HashMap<>();
    21. // 自定义监控逻辑
    22. ret.put("type", "post");
    23. ret.put("status", "okk");
    24. ret.put("details", "nothing to do");
    25. return ret;
    26. }
    27. }

    加载所有EndPoint并由DispatcherServlet路由的源码位置:org.springframework.boot.actuate.autoconfigure.endpoint.web.servlet.WebMvcEndpointManagementContextConfiguration#webEndpointServletHandlerMapping

    1. @Bean
    2. @ConditionalOnMissingBean
    3. public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier,
    4. ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier,
    5. EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties,
    6. WebEndpointProperties webEndpointProperties, Environment environment) {
    7. List> allEndpoints = new ArrayList<>();
    8. // 这里查询bean容器中所有注解了@Endpoint的类
    9. Collection webEndpoints = webEndpointsSupplier.getEndpoints();
    10. allEndpoints.addAll(webEndpoints);
    11. allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
    12. allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
    13. String basePath = webEndpointProperties.getBasePath();
    14. EndpointMapping endpointMapping = new EndpointMapping(basePath);
    15. boolean shouldRegisterLinksMapping = StringUtils.hasText(basePath)
    16. || ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT);
    17. // WebMvcEndpointHandlerMapping继承了AbstractHandlerMethodMapping
    18. // 将每个Endpoint和其中的get/post方法封装为handlermethod,由springmvc在请求时路由
    19. return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes,
    20. corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath),
    21. shouldRegisterLinksMapping);
    22. }

    /beans

    返回当前应用所有父子容器中的bean信息,如下图

    源码实现类为 org.springframework.boot.actuate.beans.BeansEndpoint,比较简单就是从ApplicationContext挨个取出BeanDefinition,把部分信息封装到Map返回

    1. @Endpoint(id = "beans")
    2. public class BeansEndpoint {
    3. private final ConfigurableApplicationContext context;
    4. public BeansEndpoint(ConfigurableApplicationContext context) {
    5. this.context = context;
    6. }
    7. @ReadOperation
    8. public ApplicationBeans beans() {
    9. // 循环把父子容器的bean信息放到map中返回
    10. Map contexts = new HashMap<>();
    11. ConfigurableApplicationContext context = this.context;
    12. while (context != null) {
    13. contexts.put(context.getId(), ContextBeans.describing(context));
    14. context = getConfigurableParent(context);
    15. }
    16. return new ApplicationBeans(contexts);
    17. }
    18. private static Map describeBeans(ConfigurableListableBeanFactory beanFactory) {
    19. Map beans = new HashMap<>();
    20. for (String beanName : beanFactory.getBeanDefinitionNames()) {
    21. BeanDefinition definition = beanFactory.getBeanDefinition(beanName);
    22. if (isBeanEligible(beanName, definition, beanFactory)) {
    23. beans.put(beanName, describeBean(beanName, definition, beanFactory));
    24. }
    25. }
    26. return beans;
    27. }
    28. }

     

    /health

    各个组件的运行状况

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

     也可以自定义实现其他组件的健康检测类

    1. @Component
    2. public class RocketMQHealthIndicator extends AbstractHealthIndicator {
    3. @Override
    4. protected void doHealthCheck(Health.Builder builder) throws Exception {
    5. // 自定义逻辑
    6. // 展示信息
    7. builder.status(Status.UP);
    8. builder.withDetail("aaaa", "aaaa");
    9. builder.withDetail("bbbb", "bbbb");
    10. builder.withDetail("cccc", "cccc");
    11. }
    12. }

    /loggers 

    查看当前应用日志级别情况,可以动态改变

    如下应用层代码:

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

     

    执行输出test111方法如图:

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

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

     

    /info

    自定义显示程序信息,有两种方式定制 info 信息

    一种就是在application.properties配置文件中配置如下:

    访问端点返回如下

     

    另一种代码形式,实现InfoContributor接口

     

    /threaddump 

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

     

  • 相关阅读:
    P4 开发实践 — NG-SDN Tutorial — Exercise 4: Enabling ONOS Built-in Services
    8-6选择排序-简单选择排序
    tiobe的内容项怎么回事?
    最新版本 Stable Diffusion 开源 AI 绘画工具之图生图进阶篇
    Rust中使用Rocket框架返回html网页,返回一个基于 Handlebars (HBS) 模板的响应
    kubernetes学习(二) --------docker的基本命令,namespace和cgroups
    Linux:详细介绍如何挂载?及其命令
    一个成功项目的诞生:RocketMQ项目初期的设计思考
    【JAVA并发】二、JAVA是如何解决并发问题的
    141.环形链表
  • 原文地址:https://blog.csdn.net/xyjy11/article/details/126392857