欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

datax(七)源码阅读之运行时监控MXBean

程序员文章站 2023-10-28 13:38:04
目录一、JMX前置知识二、datax的运行时监控三、运行时常用的MXBean大全一、JMX前置知识官方文档:https://docs.oracle.com/javase/tutorial/jmx/index.html网上比较不错的文章:http://www.tianshouzhi.com/api/tutorials/jmx/28简单的说就是,JMX可以通过MBean的注册来实现运行时监控,而MXBean是一种可以支持复杂变量类型的MBean,具体的细节大家可以参考下上面两篇....

目录

 

一、JMX前置知识

二、datax的运行时监控

三、运行时常用的MXBean大全


一、JMX前置知识

官方文档:https://docs.oracle.com/javase/tutorial/jmx/index.html

网上比较不错的文章:http://www.tianshouzhi.com/api/tutorials/jmx/28

简单的说就是,JMX可以通过MBean的注册来实现运行时监控,而MXBean是一种可以支持复杂变量类型的MBean,具体的细节大家可以参考下上面两篇文章

注:一般我们自己在开发springboot项目去实现自定义的监控指标的时候,不会直接去使用jmx,而是更倾向于使用流行的监控框架去实现,比如micrometer + promethues + grafana (micrometer可以用来收集应用的指标,可以是应用的自定义指标或JMX的指标;而promethues作为中心化的指标大盘可以对接各个应用的监控指标,并提供监控告警和对指标进行sql查询的能力;grafana则是对接promethues提供了可视化的能力)

 

二、datax的运行时监控

datax有个VMInfo类,用来运行时获取jvm的各种指标信息并进行打印,包括操作系统相关信息、垃圾收集器相关信息、jvm内存区域相关信息

VMInfo在datax源码中主要有三个场景进行使用(代码中省略了其他杂七杂八的业务逻辑)

1、datax Exgine调用start方法前

VMInfo vmInfo = VMInfo.getVmInfo();
if (vmInfo != null) {
  LOG.info(vmInfo.toString());
}

2、整个job结束之后

VMInfo vmInfo = VMInfo.getVmInfo();
if (vmInfo != null) {
  vmInfo.getDelta(false);
  LOG.info(vmInfo.totalString());
}

3、jobScheduler运行过程中每个汇报周期调用一次进行汇报

VMInfo vmInfo = VMInfo.getVmInfo();
if (vmInfo != null) {
  vmInfo.getDelta(true);
}

可以看到对应的调用姿势也不一样,我们的主要关注点也聚焦到第一个场景,第一个常见打印出来的日志如下:

datax(七)源码阅读之运行时监控MXBean

我们不关注里面的指标数据到底有没有问题,我们就关注下整个执行逻辑。

首先看到getVMInfo这个方法。

private static VMInfo vmInfo;

     /**
     * @return null or vmInfo. null is something error, job no care it.
     */
    public static VMInfo getVmInfo() {
        if (vmInfo == null) {
            synchronized (lock) {
                if (vmInfo == null) {
                    try {
                        vmInfo = new VMInfo();
                    } catch (Exception e) {
                        LOG.warn("no need care, the fail is ignored : vmInfo init failed " + e.getMessage(), e);
                    }
                }
            }

        }
        return vmInfo;
    }

可以看到就是一个简单的单例来进行VMInfo对象的实例化

 

再看到VMInfo的构造方法::

private VMInfo() {
        //初始化静态信息
        osMXBean = java.lang.management.ManagementFactory.getOperatingSystemMXBean();
        runtimeMXBean = java.lang.management.ManagementFactory.getRuntimeMXBean();
        garbageCollectorMXBeanList = java.lang.management.ManagementFactory.getGarbageCollectorMXBeans();
        memoryPoolMXBeanList = java.lang.management.ManagementFactory.getMemoryPoolMXBeans();

        osInfo = runtimeMXBean.getVmVendor() + " " + runtimeMXBean.getSpecVersion() + " " + runtimeMXBean.getVmVersion();
        jvmInfo = osMXBean.getName() + " " + osMXBean.getArch() + " " + osMXBean.getVersion();
        totalProcessorCount = osMXBean.getAvailableProcessors();

        //构建startPhyOSStatus
        startPhyOSStatus = new PhyOSStatus();
        LOG.info("VMInfo# operatingSystem class => " + osMXBean.getClass().getName());
        if (VMInfo.isSunOsMBean(osMXBean)) {
            {
                startPhyOSStatus.totalPhysicalMemory = VMInfo.getLongFromOperatingSystem(osMXBean, "getTotalPhysicalMemorySize");
                startPhyOSStatus.freePhysicalMemory = VMInfo.getLongFromOperatingSystem(osMXBean, "getFreePhysicalMemorySize");
                startPhyOSStatus.maxFileDescriptorCount = VMInfo.getLongFromOperatingSystem(osMXBean, "getMaxFileDescriptorCount");
                startPhyOSStatus.currentOpenFileDescriptorCount = VMInfo.getLongFromOperatingSystem(osMXBean, "getOpenFileDescriptorCount");
            }
        }

        //初始化processGCStatus;
        for (GarbageCollectorMXBean garbage : garbageCollectorMXBeanList) {
            GCStatus gcStatus = new GCStatus();
            gcStatus.name = garbage.getName();
            processGCStatus.gcStatusMap.put(garbage.getName(), gcStatus);
        }

        //初始化processMemoryStatus
        if (memoryPoolMXBeanList != null && !memoryPoolMXBeanList.isEmpty()) {
            for (MemoryPoolMXBean pool : memoryPoolMXBeanList) {
                MemoryStatus memoryStatus = new MemoryStatus();
                memoryStatus.name = pool.getName();
                memoryStatus.initSize = pool.getUsage().getInit();
                memoryStatus.maxSize = pool.getUsage().getMax();
                processMomoryStatus.memoryStatusMap.put(pool.getName(), memoryStatus);
            }
        }
    }

vmInfo.toString()方法:

public String toString() {
        return "the machine info  => \n\n"
                + "\tosInfo:\t" + osInfo + "\n"
                + "\tjvmInfo:\t" + jvmInfo + "\n"
                + "\tcpu num:\t" + totalProcessorCount + "\n\n"
                + startPhyOSStatus.toString() + "\n"
                + processGCStatus.toString() + "\n"
                + processMomoryStatus.toString() + "\n";
    }

大体的逻辑就是使用下列的MXBean获取信息:

1、OperatingSystemMXBean获取操作系统相关信息,主要获取了操作系统名称、操作系统的架构、操作系统的版本。如果是unix操作系统的话,也进行总物理内存、已释放的物理内存、最大文件描述符以及已经打开的文件描述符

2、RuntimeMXBean获取java虚拟机相关信息,主要获取了Java 虚拟机实现供应商、Java 虚拟机规范版本、Java 虚拟机实现版本

3、GarbageCollectorMXBean列表获取垃圾收集器相关信息,主要获取了垃圾收集器的名称

4、MemoryPoolMXBean获取jvm内存区域列表相关信息,主要获取了每个内存空间的名称、初始空间以及最大空间。

 

 

三、运行时常用的MXBean大全

参考文档(主要是java.lang.management包下):https://tool.oschina.net/uploads/apidocs/jdk-zh/java/lang/management/package-use.html

本文地址:https://blog.csdn.net/qq_31957747/article/details/112097501