zoukankan      html  css  js  c++  java
  • 监控应用服务器使用JMX监控Tomcat (推荐)


    前言:做了一个监控应用服务器的项目(支持Tocmat、WebSphere、WebLogic各版本), 过程也算是磕磕绊绊,由于网上缺少相关资料,或者深陷于知识的海洋难以寻觅到有效的资料,因而走过不少弯路,遇过不少困难。为了留下点印记,给后来人留下 点经验之谈,助之少走弯路,故将这些经验整理出来,与大家分享。水平有限,难免疏漏,还望指正。如有疑问,欢迎留言,或者加入Q群参与讨 论:35526521。

    一、激活Tomcat的JMX远程配置

    要通过JMX远程监控Tomcat,首先需要激活Tomcat的JMX远程配置。

    ① 先修改Tomcat的启动脚本,windows下为bin/catalina.bat(linux下为catalina.sh),添加以下内容,8999是jmxremote使用的端口号,第二个false表示不需要鉴权:
    Xml代码 

    set JMX_REMOTE_CONFIG=-Dcom.sun.management.jmxremote 
      -Dcom.sun.management.jmxremote.port=8999
      -Dcom.sun.management.jmxremote.ssl=false
      -Dcom.sun.management.jmxremote.authenticate=false set CATALINA_OPTS=%CATALINA_OPTS% %JMX_REMOTE_CONFIG%

    要注意以上语句的位置不能太后面,可以加在【if "%OS%" == "Windows_NT" setlocal】一句后的大段的注释后面。

    参考官方说明:
    http://tomcat.apache.org/tomcat-6.0-doc/monitoring.html#Enabling_JMX_Remote


    ② 上面的配置是不需要鉴权的,如果需要鉴权则添加的内容为:
    Xml代码 

    set JMX_REMOTE_CONFIG=-Dcom.sun.management.jmxremote 
    -Dcom.sun.management.jmxremote.port=8999
    -Dcom.sun.management.jmxremote.ssl=false
    -Dcom.sun.management.jmxremote.authenticate=true
    -Dcom.sun.management.jmxremote.password.file=../conf/jmxremote.password
    -Dcom.sun.management.jmxremote.access.file=../conf/jmxremote.access set CATALINA_OPTS=%CATALINA_OPTS% %JMX_REMOTE_CONFIG%


    ③ 然后复制并修改授权文件
    $JAVA_HOME/jre/lib/management下有jmxremote.access和jmxremote.password的模板文件,将两个文件复制到$CATALINA_BASE/conf目录下
    ◆ 修改$CATALINA_BASE/conf/jmxremote.access 添加内容:

         monitorRole readonly
         controlRole readwrite 


    ◆ 修改$CATALINA_BASE/conf/jmxremote.password 添加内容:

         monitorRole tomcat
         controlRole tomcat


    注意: 如果进行了以上步骤导致Tomcat启动不了,那么很可能是密码文件的权限问题

    需要修改jmxremote.password文件的访问权限,只有文件的owner所有者才能拥有访问权限 (并且文件的所有者必须与tomcat的所有者是同一用户):
          Windows的NTFS文件系统下,选中文件,点右键 -->“属性”-->“安全”--> 点“高级”--> 点“更改权限”--> 去掉“从父项继承....”--> 弹出窗口中选“删除”,这样就删除了所有访问权限。再选“添加”--> “高级”--> “立即查找”,选中你的用户(或用户组,如果选用户不行那就选用户组),点“确定",“确定"。来到权限项目窗口,勾选 “完全控制”,点“确定”,OK了。

    官方的提示:
          The password file should be read-only and only accessible by the operating system user Tomcat is running as.

    ④ 重新启动Tomcat,在Windows命令行输入“netstat -a”查看配置的端口号是否已打开,如果打开,说明上面的配置成功了。

    ⑤ 使用jconsole测试JMX。
    运行$JAVA_HOME/bin目录下的jconsole.exe,打开J2SE监视和管理控制台,然后建立连接,如果是本地的Tomcat则 直接选择然后点击连接,如果是远程的,则进入远程选项卡,填写地址、端口号、用户名、口令即可连接。。Mbean属性页中给出了相应的数 据,Catalina中是tomcat的,java.lang是jvm的。对于加粗的黑体属性值,需双击一下才可看内容。


    二、使用JMX监控Tomcat示例代码
    Java代码 

     1 String jmxURL = "service:jmx:rmi:///jndi/rmi://192.168.10.93:8999/jmxrmi"; 
     2 JMXServiceURL serviceURL = new JMXServiceURL(jmxURL); 
     3  
     4 Map map = new HashMap(); 
     5 // 用户名密码,在jmxremote.password文件中查看 
     6 String[] credentials = new String[] { "monitorRole", "tomcat" }; 
     7 map.put("jmx.remote.credentials", credentials); 
     8 JMXConnector connector = JMXConnectorFactory.connect(serviceURL, map); 
     9 MBeanServerConnection mbsc = connector.getMBeanServerConnection(); 
    10  
    11 // 端口最好是动态取得 name对应的是ThreadPool 的名称,会有变化,根据自己的设置修改
    12 ObjectName threadObjName = new ObjectName("Catalina:type=ThreadPool,name=http-8080"); 
    13 MBeanInfo mbInfo = mbsc.getMBeanInfo(threadObjName); 
    14  
    15 // tomcat的线程数对应的属性值 
    16 String attrName = "currentThreadCount"; 
    17 MBeanAttributeInfo[] mbAttributes = mbInfo.getAttributes(); 
    18 System.out.println("currentThreadCount:" + mbsc.getAttribute(threadObjName, attrName)); 


    三、完整的示例代码文件
    Java代码 

      1 import java.lang.management.MemoryUsage; 
      2 import java.text.SimpleDateFormat; 
      3 import java.util.Date; 
      4 import java.util.Formatter; 
      5 import java.util.HashMap; 
      6 import java.util.Iterator; 
      7 import java.util.Map; 
      8 import java.util.Set; 
      9  
     10 import javax.management.MBeanAttributeInfo; 
     11 import javax.management.MBeanInfo; 
     12 import javax.management.MBeanServerConnection; 
     13 import javax.management.ObjectInstance; 
     14 import javax.management.ObjectName; 
     15 import javax.management.openmbean.CompositeDataSupport; 
     16 import javax.management.remote.JMXConnector; 
     17 import javax.management.remote.JMXConnectorFactory; 
     18 import javax.management.remote.JMXServiceURL; 
     19  
     20 public class JMXTest { 
     21  
     22     /**
     23      * @param args
     24      */ 
     25     public static void main(String[] args) { 
     26         try { 
     27  
     28             String jmxURL = "service:jmx:rmi:///jndi/rmi://127.0.0.1:8999/jmxrmi"; 
     29  
     30             JMXServiceURL serviceURL = new JMXServiceURL(jmxURL); 
     31  
     32             Map map = new HashMap(); 
     33             String[] credentials = new String[] { "monitorRole", "tomcat" }; 
     34             map.put("jmx.remote.credentials", credentials); 
     35             JMXConnector connector = JMXConnectorFactory.connect(serviceURL, 
     36                     map); 
     37             MBeanServerConnection mbsc = connector.getMBeanServerConnection(); 
     38  
     39             // 端口最好是动态取得 
     40             ObjectName threadObjName = new ObjectName( 
     41                     "Catalina:type=ThreadPool,name=http-8080"); 
     42             MBeanInfo mbInfo = mbsc.getMBeanInfo(threadObjName); 
     43  
     44             String attrName = "currentThreadCount";// tomcat的线程数对应的属性值 
     45             MBeanAttributeInfo[] mbAttributes = mbInfo.getAttributes(); 
     46             System.out.println("currentThreadCount:" 
     47                     + mbsc.getAttribute(threadObjName, attrName)); 
     48  
     49             // heap 
     50             for (int j = 0; j < mbsc.getDomains().length; j++) { 
     51                 System.out.println("###########" + mbsc.getDomains()[j]); 
     52             } 
     53             Set MBeanset = mbsc.queryMBeans(null, null); 
     54             System.out.println("MBeanset.size() : " + MBeanset.size()); 
     55             Iterator MBeansetIterator = MBeanset.iterator(); 
     56             while (MBeansetIterator.hasNext()) { 
     57                 ObjectInstance objectInstance = (ObjectInstance) MBeansetIterator 
     58                         .next(); 
     59                 ObjectName objectName = objectInstance.getObjectName(); 
     60                 String canonicalName = objectName.getCanonicalName(); 
     61                 System.out.println("canonicalName : " + canonicalName); 
     62                 if (canonicalName 
     63                         .equals("Catalina:host=localhost,type=Cluster")) { 
     64                     // Get details of cluster MBeans 
     65                     System.out.println("Cluster MBeans Details:"); 
     66                     System.out 
     67                             .println("========================================="); 
     68                     // getMBeansDetails(canonicalName); 
     69                     String canonicalKeyPropList = objectName 
     70                             .getCanonicalKeyPropertyListString(); 
     71                 } 
     72             } 
     73             // ------------------------- system ---------------------- 
     74             ObjectName runtimeObjName = new ObjectName("java.lang:type=Runtime"); 
     75             System.out.println("厂商:" 
     76                     + (String) mbsc.getAttribute(runtimeObjName, "VmVendor")); 
     77             System.out.println("程序:" 
     78                     + (String) mbsc.getAttribute(runtimeObjName, "VmName")); 
     79             System.out.println("版本:" 
     80                     + (String) mbsc.getAttribute(runtimeObjName, "VmVersion")); 
     81             Date starttime = new Date((Long) mbsc.getAttribute(runtimeObjName, 
     82                     "StartTime")); 
     83             SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
     84             System.out.println("启动时间:" + df.format(starttime)); 
     85  
     86             Long timespan = (Long) mbsc.getAttribute(runtimeObjName, "Uptime"); 
     87             System.out.println("连续工作时间:" + JMXTest.formatTimeSpan(timespan)); 
     88             // ------------------------ JVM ------------------------- 
     89             // 堆使用率 
     90             ObjectName heapObjName = new ObjectName("java.lang:type=Memory"); 
     91             MemoryUsage heapMemoryUsage = MemoryUsage 
     92                     .from((CompositeDataSupport) mbsc.getAttribute(heapObjName, 
     93                             "HeapMemoryUsage")); 
     94             long maxMemory = heapMemoryUsage.getMax();// 堆最大 
     95             long commitMemory = heapMemoryUsage.getCommitted();// 堆当前分配 
     96             long usedMemory = heapMemoryUsage.getUsed(); 
     97             System.out.println("heap:" + (double) usedMemory * 100 
     98                     / commitMemory + "%");// 堆使用率 
     99  
    100             MemoryUsage nonheapMemoryUsage = MemoryUsage 
    101                     .from((CompositeDataSupport) mbsc.getAttribute(heapObjName, 
    102                             "NonHeapMemoryUsage")); 
    103             long noncommitMemory = nonheapMemoryUsage.getCommitted(); 
    104             long nonusedMemory = heapMemoryUsage.getUsed(); 
    105             System.out.println("nonheap:" + (double) nonusedMemory * 100 
    106                     / noncommitMemory + "%"); 
    107  
    108             ObjectName permObjName = new ObjectName( 
    109                     "java.lang:type=MemoryPool,name=Perm Gen"); 
    110             MemoryUsage permGenUsage = MemoryUsage 
    111                     .from((CompositeDataSupport) mbsc.getAttribute(permObjName, 
    112                             "Usage")); 
    113             long committed = permGenUsage.getCommitted();// 持久堆大小 
    114             long used = heapMemoryUsage.getUsed();// 
    115             System.out.println("perm gen:" + (double) used * 100 / committed 
    116                     + "%");// 持久堆使用率 
    117  
    118             // -------------------- Session --------------- 
    119             ObjectName managerObjName = new ObjectName( 
    120                     "Catalina:type=Manager,*"); 
    121             Set<ObjectName> s = mbsc.queryNames(managerObjName, null); 
    122             for (ObjectName obj : s) { 
    123                 System.out.println("应用名:" + obj.getKeyProperty("path")); 
    124                 ObjectName objname = new ObjectName(obj.getCanonicalName()); 
    125                 System.out.println("最大会话数:" 
    126                         + mbsc.getAttribute(objname, "maxActiveSessions")); 
    127                 System.out.println("会话数:" 
    128                         + mbsc.getAttribute(objname, "activeSessions")); 
    129                 System.out.println("活动会话数:" 
    130                         + mbsc.getAttribute(objname, "sessionCounter")); 
    131             } 
    132  
    133             // ----------------- Thread Pool ---------------- 
    134             ObjectName threadpoolObjName = new ObjectName( 
    135                     "Catalina:type=ThreadPool,*"); 
    136             Set<ObjectName> s2 = mbsc.queryNames(threadpoolObjName, null); 
    137             for (ObjectName obj : s2) { 
    138                 System.out.println("端口名:" + obj.getKeyProperty("name")); 
    139                 ObjectName objname = new ObjectName(obj.getCanonicalName()); 
    140                 System.out.println("最大线程数:" 
    141                         + mbsc.getAttribute(objname, "maxThreads")); 
    142                 System.out.println("当前线程数:" 
    143                         + mbsc.getAttribute(objname, "currentThreadCount")); 
    144                 System.out.println("繁忙线程数:" 
    145                         + mbsc.getAttribute(objname, "currentThreadsBusy")); 
    146             } 
    147  
    148         } catch (Exception e) { 
    149             e.printStackTrace(); 
    150         } 
    151     } 
    152  
    153     public static String formatTimeSpan(long span) { 
    154         long minseconds = span % 1000; 
    155  
    156         span = span / 1000; 
    157         long seconds = span % 60; 
    158  
    159         span = span / 60; 
    160         long mins = span % 60; 
    161  
    162         span = span / 60; 
    163         long hours = span % 24; 
    164  
    165         span = span / 24; 
    166         long days = span; 
    167         return (new Formatter()).format("%1$d天 %2$02d:%3$02d:%4$02d.%5$03d", 
    168                 days, hours, mins, seconds, minseconds).toString(); 
    169     } 
    170 } 

     实例2:

      1 public ConcurrentHashMap<String, Object> parseJMS(String tempid, ConcurrentHashMap<String, Object> paraMap) {
      2         MBeanServerConnection mbsc = null;
      3         try {
      4             mbsc = connector.getMBeanServerConnection();
      5             // ------------------------- system ----------------------
      6             ObjectName runtimeObjName = new ObjectName("java.lang:type=Runtime");
      7             TabularDataSupport system = (TabularDataSupport) mbsc.getAttribute(runtimeObjName, "SystemProperties");
      8             //JVM版本
      9             paraMap.put(tempid + "_JVMVERSION", mbsc.getAttribute(runtimeObjName, "VmVersion"));
     10             //JVM厂商
     11             paraMap.put(tempid + "_JVMMANUFACTURER", mbsc.getAttribute(runtimeObjName, "VmVendor"));
     12             //系统结构
     13             paraMap.put(tempid + "_SYSTEMSTRUCTURE", system.get(new Object[] {"os.arch"}).get("value"));
     14             //操作系统
     15             paraMap.put(tempid + "_OPERATIONSYSTEM", system.get(new Object[] {"os.name"}).get("value"));
     16             //操作系统版本
     17             paraMap.put(tempid + "_OPERATIONSYSTEMVERSION", system.get(new Object[] {"os.version"}).get("value"));
     18             //Tomcat版本
     19             String t_version = (String) system.get(new Object[] {"org.apache.catalina.startup.TldConfig.jarsToSkip"}).get("value");
     20             paraMap.put(tempid + "_TOMCATVERSION", t_version == null ? "" : t_version.substring(0, t_version.indexOf("-")));
     21             //链接Tomcat服务器的响应时间 -------------
     22              
     23              
     24             ObjectName heapObjName = new ObjectName("java.lang:type=Memory");
     25             MemoryUsage heapMemoryUsage =  MemoryUsage.from((CompositeDataSupport)mbsc.getAttribute(heapObjName, "HeapMemoryUsage"));
     26             //JVM已用内存
     27             paraMap.put(tempid + "_JVMUSERDMEMORY", heapMemoryUsage.getUsed());
     28             //JVM可用内存
     29             paraMap.put(tempid + "_JVMAVAILABLEMEMORY", heapMemoryUsage.getCommitted() - heapMemoryUsage.getUsed());
     30             //JVM内存总数
     31             paraMap.put(tempid + "_JVMTOTALMEMORY", heapMemoryUsage.getCommitted());
     32               
     33           //----------------- GlobalRequestProcessor ----------------
     34            ObjectName requestProcessor = new ObjectName("Catalina:type=GlobalRequestProcessor,*");
     35            Set<ObjectName> s2 = mbsc.queryNames(requestProcessor, null);
     36            long bytesSents = 0;
     37            long bytesReceiveds = 0;
     38            Integer errorCounts = 0;
     39            Integer requestCounts = 0;
     40            long processingTimes = 0;
     41            long maxTimes = 0;
     42            for (ObjectName obj : s2) {
     43                ObjectName objname = new ObjectName(obj.getCanonicalName());
     44                long bytesSent = (long) mbsc.getAttribute( objname, "bytesSent");
     45                long bytesReceived = (long) mbsc.getAttribute( objname, "bytesReceived");
     46                Integer errorCount = (Integer) mbsc.getAttribute( objname, "errorCount");
     47                Integer requestCount = (Integer) mbsc.getAttribute( objname, "requestCount");
     48                long processingTime = (long) mbsc.getAttribute( objname, "processingTime");
     49                long maxTime = (long) mbsc.getAttribute( objname, "maxTime");
     50                bytesSents += bytesSent;
     51                bytesReceiveds += bytesReceived;
     52                errorCounts += errorCount;
     53                requestCounts += requestCount;
     54                processingTimes += processingTime;
     55                maxTimes += maxTime;
     56            }
     57            //发送字节
     58            paraMap.put(tempid + "_SENDBYTE", bytesSents);
     59            //接收字节
     60            paraMap.put(tempid + "_RECIEVEDBYTE", bytesReceiveds);
     61            //错误个数
     62            paraMap.put(tempid + "_ERRORNUMBER", errorCounts);
     63            //请求个数
     64            paraMap.put(tempid + "_REQUESTNUMBER", requestCounts);
     65            //处理时间
     66            paraMap.put(tempid + "_TREATMENTTIME", processingTimes);
     67            //最大处理时间
     68            paraMap.put(tempid + "_MAXTREATMENTTIME", maxTimes);
     69            
     70            //----------------- Thread Pool ----------------
     71            ObjectName threadpoolObjName = new ObjectName("Catalina:type=ThreadPool,*");
     72            Set<ObjectName> tp = mbsc.queryNames(threadpoolObjName, null);
     73            int currentThreadsBusys = 0;
     74            int maxThreadss = 0;
     75            for (ObjectName obj : tp) {
     76                ObjectName objname = new ObjectName(obj.getCanonicalName());
     77                int currentThreadsBusy = (int) mbsc.getAttribute( objname, "currentThreadsBusy");
     78                int maxThreads = (int) mbsc.getAttribute( objname, "maxThreads");
     79                currentThreadsBusys += currentThreadsBusy;
     80                maxThreadss += maxThreads;
     81            }
     82            //当前忙碌线程数
     83            paraMap.put(tempid + "_CURRENTBUSYTHREADSNUMBER", currentThreadsBusys);
     84            //最大线程数
     85            paraMap.put(tempid + "_MAXTHREADSNUMBER", maxThreadss);
     86             
     87            //----------------- RequestProcessor ----------------
     88            ObjectName requestProcessor1 = new ObjectName("Catalina:type=RequestProcessor,*");
     89            Set<ObjectName> rp = mbsc.queryNames(requestProcessor1, null);
     90            long requestProcessingTimes = 0;
     91            int portCount = 0;
     92            for (ObjectName obj : rp) {
     93                portCount++;
     94                ObjectName objname = new ObjectName(obj.getCanonicalName());
     95                long requestProcessingTime = (long) mbsc.getAttribute(objname, "requestProcessingTime");
     96                requestProcessingTimes += requestProcessingTime;
     97            }
     98            //端口平均响应时间
     99            paraMap.put(tempid + "_AVERAGERESPONSETIME", portCount == 0 ? requestProcessingTimes : Math.round(requestProcessingTimes/portCount));
    100             
    101             
    102             
    103         } catch (IOException e) {
    104             e.printStackTrace();
    105         } catch (MalformedObjectNameException e) {
    106             e.printStackTrace();
    107         } catch (AttributeNotFoundException e) {
    108             e.printStackTrace();
    109         } catch (InstanceNotFoundException e) {
    110             e.printStackTrace();
    111         } catch (MBeanException e) {
    112             e.printStackTrace();
    113         } catch (ReflectionException e) {
    114             e.printStackTrace();
    115         } catch (SecurityException e) {
    116             e.printStackTrace();
    117         } catch (IllegalArgumentException e) {
    118             e.printStackTrace();
    119         } 
    120         return paraMap;
    121     }
    122   
    123     public static void main(String[] args) {
    124         DoJob job = new DoJob();
    125         String tempid = "MW_WS_TOMCAT_AGENT";
    126         job.connector = TomcatUtil.getJMXOfTomcat("service:jmx:rmi:///jndi/rmi://191.168.2.31:8999/jmxrmi", "", "");
    127         ConcurrentHashMap<String, Object> paraMap = new ConcurrentHashMap<String, Object>();
    128         paraMap = job.parseJMS(tempid, paraMap);
    129         Iterator<String> it = paraMap.keySet().iterator();
    130         while(it.hasNext()) {
    131             String key = it.next();
    132             System.out.println(key + " : " + paraMap.get(key));
    133         }
    134     }



  • 相关阅读:
    终于干掉了默认的输入法, 关于ctfmon.exe文件
    新工作一周的一些记录
    派送Maxthon 2.0 社区预览版本邀请.
    终于决定要跳槽了.
    当QA推出免责条款, 你会怎么看?
    Post by Word 2007, Test. 用word2007来发表一篇随笔.
    一个好的点菜系统
    再见2006
    昨天的实况以及忽悠姐妹花
    在公司我最近都只喝矿泉水
  • 原文地址:https://www.cnblogs.com/zhengah/p/4898444.html
Copyright © 2011-2022 走看看