zoukankan      html  css  js  c++  java
  • 利用JMX统计远程JAVA进程的CPU和Memory

    http://songzi0206.iteye.com/blog/1541636

    ********************

          从JAVA 5开始,JDK提供了一些JVM检测的API,这就是有名的java.lang.management 包,包里提供了许多MXBean的接口类,可以很方便的获取到JVM的内存、GC、线程、锁、class、甚至操作系统层面的各种信息,本文就简单的介绍一种利用JMX对JAVA进程进行CPU、堆内存使用的监控。可能有人会觉得没必要这样做,因为用jconsole之类的工具都能做到,而且会比本文的例子更详细。但是有些时候将console不一定能监控到作为系统服务的java进程,我最近就不得不自己编码去获取远程java进程的监控数据。希望能起到抛砖引玉的作用吧。

          首先,简要介绍下JMX(Java Management Extensions),即JAVA管理扩展,用来监视和管理JVM以及其运行的操作系统。目前java平台主要提供了下图所示的9个MXBean, 各个MXBean的作用根据类名大概能猜出几分,具体可查API。


            java.lang.management包中的mxbean提供了基本的功能,在sum.com.management中对某些功能有所增强,当然我们也可以根据JMX规范提供自己的MXBean。

           下面我主要使用java.lang.management.MemoryMXBean和sun.com.management.OperatingSystemMXBean分别对远程JAVA进行内存和cpu的监控。根据需求5秒钟读取一次数据,内存主要是已使用的Heap Memory,CPU主要就是使用率了。

           在使用OperatingSystemMXBean以及MemoryMXBean之前,首先必须得到JMXConnector并创建MBeanServerConnnection,有了这个connection我们就可以利用ManagementFactory创建需要的MXBean了,类依赖图如下:



            示例代码:

    Java代码  收藏代码
    1. /* 
    2. * host: 远程机器的ip地址 
    3. * port: 远程java进程运行的jmxremote端口 
    4. */  
    5. JMXServiceURL serviceURL = new JMXServiceURL( host,port );  
    6. JMXConnector conn = JMXConnectorFactory.connect(serviceURL);  
    7. MBeanServerConnection mbs=conn.getMBeanServerConnection();  
    8.   
    9. //获取远程memorymxbean  
    10. MemoryMXBean memBean=ManagementFactory.newPlatformMXBeanProxy  
    11. (mbs,ManagementFactory.MEMORY_MXBEAN_NAME, MemoryMXBean.class);  
    12. //获取远程opretingsystemmxbean  
    13. com.sun.management.OperatingSystemMXBean opMXbean =   
    14. ManagementFactory.newPlatformMXBeanProxy(mbs,                 
    15. ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class);  

           然后,采集memory的数据就比较简单了,直接调用API获取:

    Java代码  收藏代码
    1. /**    Collect data every 5 seconds      */  
    2. try {  
    3.     TimeUnit.SECONDS.sleep(5);  
    4. catch (InterruptedException e) {  
    5.     logger.error("InterruptedException occurred while MemoryCollector sleeping...");  
    6. }  
    7.   
    8. MemoryUsage heap = memBean  
    9. etHeapMemoryUsage();  
    10. MemoryUsage nonHeap = memBean  
    11. etNonHeapMemoryUsage();  
    12. long heapSizeUsed = heap.getUsed();//堆使用的大小  
    13. long nonHeapSizeUsed = nonHeap.getUsed();  
    14. long heapCommitedSize = heap.getCommitted();  
    15. long nonHeapCommitedSize = nonHeap.getCommitted();  
    16.                   

          采集CPU利用率需要自己计算一下,因为API只提供了获取cpu的使用时间,我得在两次系统时间间隔内获取两次CPU的使用时间,得到在该时间间隔内cpu使用的时间,相除即得到CPU的使用率,当然误差肯定存在。

    计算cpu使用率代码  收藏代码
    1.         Long start = System.currentTimeMillis();  
    2.         long startT = opMXbean.getProcessCpuTime();  
    3.         /**    Collect data every 5 seconds      */  
    4.         try {  
    5.             TimeUnit.SECONDS.sleep(5);  
    6.         } catch (InterruptedException e) {  
    7.             logger.error("InterruptedException occurred while MemoryCollector sleeping...");  
    8.         }  
    9.         Long end = System.currentTimeMillis();  
    10.         long endT = opMXbean.getProcessCpuTime();  
    11. //end - start 即为当前采集的时间单元,单位ms  
    12. //endT - startT 为当前时间单元内cpu使用的时间,单位为ns  
    13. //所以:double ratio = (entT-startT)/1000000.0/(end-start)/opMXbean.getAvailableProcessors()  
     

          核心代码就是这些了,当然,具体使用的话应该用单独的线程分别取cpu、memory数据,读取的数据需要写文件或者画图,监控时间长的话还要定时的将这些数据刷到磁盘文件或数据库中,等,这些都是题外话了。这边我写到excel中,然后在excel中图形展示,远程监控的程序不方便展示,仅仅来监控一段模拟cpu正弦曲线的程序 ,来看看我监控到的数据(图形)是否和预期一致,并与jconsole采到的有何差异:

    被测程序,模拟cpu正弦曲线代码  收藏代码
    1. public class SinCpu {  
    2.   
    3.     public static final double TIME = 1000;  
    4.   
    5.     /**  
    6.      * @param args the command line arguments  
    7.      */  
    8.     public static void main(String[] args) throws InterruptedException {  
    9.             new Thread(new SinTask()).start();  
    10.     }  
    11.   
    12.       
    13.       
    14.    static class SinTask implements Runnable{  
    15.   
    16.         @Override  
    17.         public void run() {  
    18.             double x = 0;  
    19.             double y = 0;  
    20.   
    21.             while (true) {  
    22.                 y = (Math.sin(x) + 1) * TIME / 2;  
    23.                 doSomeSimpleWork(y);  
    24.                 x += 0.1;  
    25.                 try {  
    26.                     Thread.sleep((long) (TIME - y));  
    27.                 } catch (InterruptedException e) {  
    28.                     e.printStackTrace();  
    29.                 }  
    30.             }  
    31.         }  
    32.         private void doSomeSimpleWork(double y) {  
    33.             long startTime = System.currentTimeMillis();  
    34.             while ((System.currentTimeMillis() - startTime) < y) {  
    35.             }  
    36.         }  
    37.     }  
    38. }  

           监控结果基本和预期一样,CPU数据图呈现预期的正弦曲线:


            上图中,第一个图是从jconsole监控图中截过来的,而下图是我利用opMXBean计算获得,两个图基本吻合,数据基本波动在0-25%是因为我测试机器是四核的cpu,两个图像之间有位移是因为,我手动打开jconsole没有我程序监控来的快,所以大概图像平移下基本吻合。

            内存的测试应该比CPU还要准一些,这里就不贴了。Note: 如果监控的程序线程数量很大,cpu会有较明显误差,而且采的频率不够高的话可能有些点漏采。

    最后:被测程序必须开放JMXREMOTE端口,具体使用参数:

    -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=[开放的端口]
    -Dcom.sun.management.jmxremote.authenticate=false
    -Dcom.sun.management.jmxremote.ssl=false

     
  • 相关阅读:
    cmanformat
    mysql-sql语言参考
    jQuery 判断多个 input checkbox 中至少有一个勾选
    Java实现 蓝桥杯 算法提高 计算行列式
    Java实现 蓝桥杯 数独游戏
    Java实现 蓝桥杯 数独游戏
    Java实现 蓝桥杯 数独游戏
    Java实现 蓝桥杯 算法提高 成绩排序2
    Java实现 蓝桥杯 算法提高 成绩排序2
    Java实现 蓝桥杯 算法提高 成绩排序2
  • 原文地址:https://www.cnblogs.com/zhao1949/p/6306430.html
Copyright © 2011-2022 走看看