zoukankan      html  css  js  c++  java
  • springboot04_springboot特性之Actuator

    4.1.8.springboot特性之Actuator【上】

    时长:23min

    4.3.Actuator是干啥的?

      它也是以starter组件方式,进行引入的。

    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>

    当添加这个组件之后,再去启动当前应用,就会看到当前项目的健康状态,一些相关信息。

    是通过Endpoints窗口进行信息展示,如下所示:

     4.3.1.通过官方文档分析actuator有哪些endpoints端点

    https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready-endpoints

     可以看到,springboot-actuator中提供了很多的端点,如:health,beans,mappings,...

    http://localhost:8080/actuator/info,本地启动后,访问端点,默认情况,只放开info,health,其它访问

    会提示错误。

      我们可以通过配置,访问更多端点,配置如下:

    management.endpoints.web.exposure.include=*

    再次运行项目,就可以访问更多端点了。如:env,beans,...

    http://localhost:8080/actuator/env

    4.3.1.1.查看health端点详情

    http://localhost:8080/actuator/health

      设置多端点可访问之后,启动springboot项目,查看到的结果是:

     只能看到status值。如果想要看到更详细的信息,应该怎么办呢?

    配置如下的属性:

    该配置,默认值为never,现在修改为always.然后重启项目,访问health,结果如下:

     这时,展示的健康状态,不仅包含应用本身的状态,还包含全局配置中其它连接,如:redis连接的状态。

    注意:

      我们如果自己定义一个redis连接组件,然后进行配置是不会监控它的状态的。它只监控spring默认支持配置

    的健康状态。

      下面来看下redis监控代码实现:

     通过继承AbstractReactiveHealthIndicator抽象类,并对连接进行监控,up表示连接成功,down表示连接失败。

    4.3.1.2.查看metrics端点详情

    http://localhost:8080/actuator/metrics

    监控对象:

      》jvm【垃圾收集器、内存、堆】

      》系统层面【运行时间,平均负载。。】

      》线程池的状态

      》容器【如tomcat】状态

    1.具体key的详细信息查看

      以"process.start.time"为例。只需要访问:

    http://localhost:8080/actuator/metrics/process.start.time

    结果如下所示:

     

    4.1.9.springboot特性之Actuator【下】

    时长:1h6min

    metrics,主要是系统运行的状态值进行监控。

      》pheuthous/grafana【图标展示】

    4.3.1.3.loggers监控

      http://localhost:8080/actuator/loggers

      主要用来展示不同包路径设置的日志级别,它的作用有:

    如果在线上想去排查问题,要查看日志的详细信息,提供一种方式可以修改,可以

    对特定节点的日志级别进行修改。

      比如说,要修改ROOT节点的日志级别。默认级别是info,现在准备修改为debug.

    1.日志级别修改

    修改方法如下:

    使用postman发起一个POST请求:http://localhost:8080/actuator/loggers/ROOT,并在

    body中传参json数据:{"configuredLevel": "DEBUG"},如下所示:

    然后,查看日志级别,已经修改为DEBUB,如下所示:

    再看项目后台输出日志级别,也变成为DEBUG,如下所示:

     同理,也可以改回INFO级别。

    4.3.1.4.查看项目的一些info信息

      需要进行配置,如:info.app.name = @project.name@

      然后,重启项目。访问info,即http://localhost:8080/actuator/info,如下所示:

     4.3.2自已开发endpoint端点

    4.3.2.1.注解方式定义一个Indicator

    代码如下所示:

    package com.wf.demo.springbootdemo.endpoint;
    
    import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
    import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
    
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @ClassName CustomerMetricsIndicator
     * @Description 自定义,用户状态监控器
     * @Author wf
     * @Date 2020/7/9 10:23
     * @Version 1.0
     */
    @Endpoint(id = "customer")
    public class CustomerMetricsIndicator {
        @ReadOperation
        public Map<String,Object> time(){
            Map<String,Object> map = new HashMap<String, Object>();
            Date time = new Date();
            map.put("当前时间",time);
            return map;
        }
    }
    4.3.2.2.定义endpoint配置类注入bean
    package com.wf.demo.springbootdemo.endpoint;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * @ClassName EndpointConfiguration
     * @Description 注入endpoint bean的配置类
     * @Author wf
     * @Date 2020/7/9 10:30
     * @Version 1.0
     */
    @Configuration
    public class EndpointConfiguration {
        @Bean
        public CustomerMetricsIndicator customerMetricsIndicator(){
            return new CustomerMetricsIndicator();
        }
    }

    然后,重启项目, 访问端点:http://localhost:8080/actuator/customer,结果如下:

     说明: 

      自定义endpoint就成功完成了。

     4.4.actuator的两种监控状态

    分别是:

    》http【web】

    》jmx

    4.4.1.JMX

    所谓JMX,是Java Management Extensions(Java管理扩展)的缩写,是一个为应用程序植入管理功能的框架。

    用户可以在任何Java应用程序中使用这些代理和服务实现管理。

      使用jmx可以做一些监控。

    4.4.1.1.springboot项目jmx监控使用
    1.需要配置jmx使能
    management.endpoints.jmx.exposure.include=*
    spring.jmx.enabled=true

    然后重启项目,使用jdk提供jconsole工具连接jmx监控端点。

    2.jconsole连接
    》jconsle打开

     window下在命令搜索框【win+R打开】中,输入jconsole,按下enter,打开图形界面,如下所示:

     

     》连接某个java进程

      选择本地启动项目,所在java进程,然后点击,连接,如下所示:

    如果出现如下所示,连接报错。点击不安全连接,即可。

     连接成功后,进入如下界面:

    3.查看endpoint信息 

    在MBean下可以查看到,相关的endpoint信息,如下所示:

     这些监控信息有什么用呢?应该如何应用它?

      我们在做监控系统时,会涉及到当前应用的服务信息上报,总不能从监控平台手动去抓取吧!

      因为监控平台要做这样一些信息抓取功能,在设计上是很困难的。比如,要抓取哪些信息,是否有用,

    还要做数据清洗等,很麻烦。

      一般来说,监控信息更多的是上报,在程序中加埋点,加监控的api,通过report去上报。java里面要把这

    些信息上报的话,就可以使用jmx这样来做。

     4.4.1.2.通过示例代码来说明jmx的作用
    1.开发一个接口
    package com.wf.demo.springbootdemo;
    
    /**
     * @ClassName SystemInfoMBean
     * @Description 系统信息接口
     * @Author wf
     * @Date 2020/7/9 11:07
     * @Version 1.0
     */
    public interface SystemInfoMBean {
        //获得当前cpu核心数
        int getCpuCore();
        //内存是多大
        long getTotalMemory();
    
        //关闭
        void shutdown();
    }

    说明:

      定义一个接口,暴露一些要监控的信息,接口命名格式必须固定,如:*MBean【后缀固定】

    2.定义接口实现类
    package com.wf.demo.springbootdemo;
    
    /**
     * @ClassName SystemInfo
     * @Description 实现类,命名和接口严格相关
     * @Author wf
     * @Date 2020/7/9 11:12
     * @Version 1.0
     */
    public class SystemInfo implements SystemInfoMBean {
        @Override
        public int getCpuCore() {
            return Runtime.getRuntime().availableProcessors();
        }
    
        @Override
        public long getTotalMemory() {
            return Runtime.getRuntime().totalMemory();
        }
    
        @Override
        public void shutdown() {
            System.exit(0);
        }
    }

    注意:

      实现类命名,必须遵照规范。即接口名去掉MBean后缀。

    3.发布信息
    package com.wf.demo.springbootdemo;
    
    import javax.management.*;
    import java.io.IOException;
    import java.lang.management.ManagementFactory;
    
    /**
     * @ClassName JMXMain
     * @Description 发布信息
     * @Author wf
     * @Date 2020/7/9 11:32
     * @Version 1.0
     */
    public class JMXMain {
        public static void main(String[] args) throws MalformedObjectNameException, NotCompliantMBeanException, InstanceAlreadyExistsException, MBeanRegistrationException, IOException {
            MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
            ObjectName objectName = new ObjectName("com.wf.demo.springbootdemo:type=SystemInfo");
            //把信息发布出去
            SystemInfo systemInfo = new SystemInfo();
            mBeanServer.registerMBean(systemInfo,objectName);
    
            //避免main方法结束,阻塞在这里
            System.in.read();
        }
    }

    然后,运行这个main程序。然后重新打开jconsole查看,是否有监控到自定义内容。

     

     可以看到,jmx监控就完成了。

      在这个监控信息中,有属性和操作两个类别,它是如何归属的呢?

      它和接口定义的方法有关系,如:是getXX方法,就归类为属性,否则归类为操作。

    思考:

      现在,我们是通过main方法进行发布监控信息的。那么,springboot是如何做到这个发布功能的呢?

      在前面我们定义的Indicator类,使用了@Endpoint注解,springboot通过扫描这个注解,并自动通过

    web和jmx两种形式的发布。

      

      下面举例说明,springboot是如何发布信息的。

    在springApplication中有属性和操作两种分类,它们分别是怎么注册的?

      如果是jmx发布,必然是有一个MBeanServer去完成一个发布。通过搜索springboot的代码,有

    SpringApplicationAdminMXBean接口,定义bean信息。如下所示:

     

     根据JMX的规范,上面的接口必然有一相关的实现类SpringApplicationAdmin,但是,这里是一个内部类

    如下所示:

     是在SpringApplicationAdminMXBeanRegistrar中定义的内部类,这个类是提供注册功能的类。

    它的注入,是通过配置类自动装配的,配置类为SpringApplicationAdminJmxAutoConfiguration

     

     4.4.1.3.SpringApplicationAdminMXBeanRegistrar如何实现jmx发布功能原理分析

      该bean实现多个接口功能,如下所示:

    public class SpringApplicationAdminMXBeanRegistrar implements ApplicationContextAware, GenericApplicationListener, EnvironmentAware, InitializingBean, DisposableBean {
        private static final Log logger = LogFactory.getLog(SpringApplicationAdminMXBeanRegistrar.SpringApplicationAdmin.class);
        private ConfigurableApplicationContext applicationContext;
        private Environment environment = new StandardEnvironment();
        private final ObjectName objectName;
        private boolean ready = false;
        private boolean embeddedWebApplication = false;
    1.ApplicationContextAware接口

      获得读取上下文能力。在Spring容器中一个bean如果实现了该方法则就可以获取上下文对象。

    public interface ApplicationContextAware extends Aware {
        void setApplicationContext(ApplicationContext var1) throws BeansException;
    }

    说明:

      该接口继承自Aware,定义setApplicationContext,通过set方法,实现bean注入springIOC容器

      实现类中处理,就是一个set注入,如下:

     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            Assert.state(applicationContext instanceof ConfigurableApplicationContext, "ApplicationContext does not implement ConfigurableApplicationContext");
            this.applicationContext = (ConfigurableApplicationContext)applicationContext;  //set注入
        }
    2. 实现GenericApplicationListener接口

      获取处理事件的能力,同样在Spring中只要实现该接口,就获取了事件监听的能力,

    不过具体监听什么事件要自己去判断。大家可以根据例子来理解。接口定义 如下:

    public interface GenericApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
        boolean supportsEventType(ResolvableType var1);
    
        default boolean supportsSourceType(@Nullable Class<?> sourceType) {
            return true;
        }
    
        default int getOrder() {
            return 2147483647;
        }
    }
    public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
    void onApplicationEvent(E var1);
    }
     

    下面看下子类实现:

    public boolean supportsEventType(ResolvableType eventType) {
            Class<?> type = eventType.getRawClass();
            if (type == null) {
                return false;
            } else {  //根据事件泛型类型,判断是否进行事件处理,ApplicationReadyEvent或WebServerInitializedEvent类型就处理
                return ApplicationReadyEvent.class.isAssignableFrom(type) || WebServerInitializedEvent.class.isAssignableFrom(type);
            }
        }
    
        public boolean supportsSourceType(Class<?> sourceType) {
            return true;
        }
    
        public void onApplicationEvent(ApplicationEvent event) {
            if (event instanceof ApplicationReadyEvent) {
                this.onApplicationReadyEvent((ApplicationReadyEvent)event);
            }
    
            if (event instanceof WebServerInitializedEvent) {
                this.onWebServerInitializedEvent((WebServerInitializedEvent)event);
            }
    
        }
    
        public int getOrder() {
            return -2147483648;
        }
      //spring已经准备好了,设置ready=true
        void onApplicationReadyEvent(ApplicationReadyEvent event) {
            if (this.applicationContext.equals(event.getApplicationContext())) {
                this.ready = true;
            }
    
        }
      //web应用,这里处理
        void onWebServerInitializedEvent(WebServerInitializedEvent event) {
            if (this.applicationContext.equals(event.getApplicationContext())) {
                this.embeddedWebApplication = true;
            }
    
        }
    3. 实现EnvironmentAware接口

      获取应用配置环境信息, 和上面一样实现了Aware结尾的接口,都能获取对应的Spring内容的对象实例,

    然后我们就可以根据该实例,来进行功能扩展。接口定义如下:

    public interface EnvironmentAware extends Aware {
        void setEnvironment(Environment var1);
    }

      实现类中处理逻辑:

    public void setEnvironment(Environment environment) {
            this.environment = environment;  //set注入
        }
    4. 实现InitializingBean接口

      这里就要着重看了,在初始化时候将MBean注册到JMX上。

    当然我们可以通过 @PostConstruct注解来声明初始化方法。接口定义如下:

    package org.springframework.beans.factory;
    
    public interface InitializingBean {
        void afterPropertiesSet() throws Exception;
    }

      子类实现逻辑:

    public void afterPropertiesSet() throws Exception {
            MBeanServer server = ManagementFactory.getPlatformMBeanServer();  //用来发布JMX,SpringApplicationAdmin是要发布接口实现类
            server.registerMBean(new SpringApplicationAdminMXBeanRegistrar.SpringApplicationAdmin(), this.objectName);
            if (logger.isDebugEnabled()) {
                logger.debug("Application Admin MBean registered with name '" + this.objectName + "'");
            }
    
        }

    注意:

      this.objectName是如何设置的?

      private final ObjectName objectName;  //通过构造器传参,是从哪里从过来的呢?
        private boolean ready = false;
        private boolean embeddedWebApplication = false;
    
        public SpringApplicationAdminMXBeanRegistrar(String name) throws MalformedObjectNameException {
            this.objectName = new ObjectName(name);
        }

     构造器是在配置类中自动装配时,设置的,如下所示:

    public class SpringApplicationAdminJmxAutoConfiguration {
        private static final String JMX_NAME_PROPERTY = "spring.application.admin.jmx-name";
        private static final String DEFAULT_JMX_NAME = "org.springframework.boot:type=Admin,name=SpringApplication";//固定格式
    
        public SpringApplicationAdminJmxAutoConfiguration() {
        }
    
        @Bean
        @ConditionalOnMissingBean
        public SpringApplicationAdminMXBeanRegistrar springApplicationAdminRegistrar(ObjectProvider<MBeanExporter> mbeanExporters, Environment environment) throws MalformedObjectNameException {
            String jmxName = environment.getProperty("spring.application.admin.jmx-name", "org.springframework.boot:type=Admin,name=SpringApplication");
            if (mbeanExporters != null) {
                Iterator var4 = mbeanExporters.iterator();
    
                while(var4.hasNext()) {
                    MBeanExporter mbeanExporter = (MBeanExporter)var4.next();
                    mbeanExporter.addExcludedBean(jmxName);
                }
            }
    
            return new SpringApplicationAdminMXBeanRegistrar(jmxName);  //这里设置jmx监控的包路径及类名
        }
    }
    5. 实现DisposableBean接口

      应用销毁时候,取消注册。同样我们也可以用@PreDestroy注解来实现。

      public void destroy() throws Exception {
            ManagementFactory.getPlatformMBeanServer().unregisterMBean(this.objectName);//取消注册
        }

      如果我们自己想要去注入这样一个注册bean,可以使用@Component进行注入。

     4.5.大盘展示系统应用监控信息

    4.5.1.springboot监控信息可发布到prometheus + grafana

    4.5.1.1.安装prometheus 组件

      它是一个开源监控系统。它有几个核心模块组成:

    》数据爬虫,可以根据配置实现定期抓取数据,基于http抓取一些metrics数据,即进行数据采集

    》时序数据库存储,存储metrics数据

    》可视化,但它的可视化并不好用,所以,才结合grafana组件来可视化展示。

    1.如何安装

      去github上搜索,下载安装包,选择prometheus-2.19.2.linux-amd64.tar.gz版本进行下载。

    https://github.com/prometheus/prometheus/releases/tag/v2.19.2

      如果是使用xshell连接服务器,使用wget进行下载,可复制出安装包路径。

    https://github.com/prometheus/prometheus/releases/download/v2.19.2/prometheus-2.19.2.linux-amd64.tar.gz

    [root@localhost ~]# wget https://github.com/prometheus/prometheus/releases/download/v2.19.2/prometheus-2.19.2.linux-amd64.tar.gz
    -bash: wget: command not found  //没有wget命令,先安装
    [root@localhost ~]# yum install -y wget

    由于是从github地址进行下载,虽然只有61M大小,速度还是比较慢。

    wget -c https://github.com/prometheus/prometheus/releases/download/v2.19.2/prometheus-2.19.2.linux-amd64.tar.gz  //支持断点续传

      

    2.springboot项目集成prometheus组件

    pom.xml添加依赖包:

     <dependency>
                <groupId>io.micrometer</groupId>
                <artifactId>micrometer-registry-prometheus</artifactId>
            </dependency>//版本由springboot管理

     然后,重启springboot项目,访问:http://localhost:8080/actuator/prometheus

  • 相关阅读:
    团队站立会议09
    团队站立会议08
    团队绩效
    团队站立会议07
    团队站立会议06
    团队站立会议05
    团队站立会议04
    团队站立会议03
    团队站立会议02
    反转链表
  • 原文地址:https://www.cnblogs.com/wfdespace/p/13268598.html
Copyright © 2011-2022 走看看