目录
一、JMX前置知识
二、datax的运行时监控
三、运行时常用的MXBean大全
官方文档: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有个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);
}
可以看到对应的调用姿势也不一样,我们的主要关注点也聚焦到第一个场景,第一个常见打印出来的日志如下:
我们不关注里面的指标数据到底有没有问题,我们就关注下整个执行逻辑。
首先看到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内存区域列表相关信息,主要获取了每个内存空间的名称、初始空间以及最大空间。
参考文档(主要是java.lang.management包下):https://tool.oschina.net/uploads/apidocs/jdk-zh/java/lang/management/package-use.html