使用JMX监控TOMCAT

一、激活Tomcat的JMX远程配置

 

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

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

1 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  
2 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

 

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

1 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  
2 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 chenfeng
     controlRole chenfeng

 

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

需要修改jmxremote.password文件的访问权限,只有运行Tomcat的用户才能拥有访问权限 :
      Windows的NTFS文件系统下,选中文件,点右键 -->“属性”-->“安全”--> 点“高级”--> 点“更改权限”--> 去掉“从父项继承....”--> 弹出窗口中选“删除”,这样就删除了所有访问权限。再选“添加”--> “高级”--> “立即查找”,选中你的用户(或用户组,如果选用户不行那就选用户组),例administrator,点“确定",“确定"。来到权限项目窗口,勾选“完全控制”,点“确定”,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示例代码

 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 // 端口最好是动态取得  
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));  

 

 

三、完整的示例代码文件

  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 }

 

posted @ 2021-03-10 17:18  Vanilla香草阿  阅读(375)  评论(0编辑  收藏  举报