监控Tomcat方案调研(监控应用服务器系列文章一)

Java 服务接入「东方通(tongweb)」 调研东方通(tongweb)中间件,将 Authing 核心 Java 服务接入东方通(tongweb)替换 springboot tomcat 阅读详情
 

监控Tomcat方案调研(监控应用服务器系列文章一)

前言:最近在做一个监控应用服务器(Tocmat、WebSphere、WebLogic)的项目,目前已小有规模,回头看看,一路走来,也算是磕磕绊绊,遇到过种种问题,走过不少弯路,不过程序员最不怕的就是遇到问题——有什么问题就解决什么问题。为了留下点印记,为后来人留下点经验之谈,助之少走弯路,特意把这些经验整理出来,与大家分享。水平有限,如有疏漏,还望指正  

 

这是对监控Tomcat的前期方案调研,共有两种方案,首先比较如下

两种方案优劣比较

 

使用Tomcat提供的manager应用

使用JMX接口开发监控程序

可以使用现有的成熟代码,减少工作量

全部代码需要从零开始

支持各不同版本时无差别

支持各不同版本比较麻烦,每个版本用的JAR包不一样,实现机制也不一样

 

 

可能存在特殊需求而manager不能满足的情况

可支配性强

注意:只支持5.x及以上版本!

 

方案一、使用Tomcat提供的manager应用

Applications Manager就是通过这种方式实现的。

使用这种方式,必须运行manager应用。缺省情况下,该应用总是运行在服务器中。

 

增加manager角色用户

此外,访问服务器的用户的角色权限必须是 manager.

要为任何用户(如 tomcat、role1 或两者)添加“manager”角色,需要修改位于 <TOMCAT-HOME>/conf 目录中的 tomcat-users.xml 文件。

 

例如:

Tomcat 服务器的 tomcat-users.xml 中的默认配置。

 

Xml代码
  1. <tomcat-users>  
  2. <user name="tomcat" password="tomcat" roles="tomcat" />  
  3. <user name="role1" password="tomcat" roles="role1" />  
  4. <user name="both" password="tomcat" roles="tomcat,role1" />  
  5. </tomcat-users>  
<tomcat-users><user name="tomcat" password="tomcat" roles="tomcat" /><user name="role1" password="tomcat" roles="role1" /><user name="both" password="tomcat" roles="tomcat,role1" /></tomcat-users>

 

 

添加“tomcat”用户的角色后,修改的条目如下:

Xml代码
  1. <tomcat-users>  
  2. <user name="tomcat" password="tomcat" roles="tomcat,manager" />  
  3. <user name="role1" password="tomcat" roles="role1" />  
  4. <user name="both" password="tomcat" roles="tomcat,role1" />  
  5. </tomcat-users>  
<tomcat-users><user name="tomcat" password="tomcat" roles="tomcat,manager" /><user name="role1" password="tomcat" roles="role1" /><user name="both" password="tomcat" roles="tomcat,role1" /></tomcat-users>

 

修改配置后,需要重新启动 Tomcat 服务器。

连接manager时将用户名/密码指定为 tomcat/tomcat

 

通过浏览器访问JMX Proxy Servlet

详见官方说明文档:

http://tomcat.apache.org/tomcat-6.0-doc/manager-howto.html#Using_the_JMX_Proxy_Servlet

 

What is JMX Proxy Servlet

The JMX Proxy Servlet is a lightweight proxy to get and set the tomcat internals. (Or any class that has been exposed via an MBean) Its usage is not very user friendly but the UI is extremely help for integrating command line scripts for monitoring and changing the internals of tomcat. You can do two things with the proxy: get information and set information. For you to really understand the JMX Proxy Servlet, you should have a general understanding of JMX. If you don't know what JMX is, then prepare to be confused.

 

 

JMX Query command

This takes the form:

http://webserver/manager/jmxproxy/?qry=STUFF

Where STUFF is the JMX query you wish to perform. For example, here are some queries you might wish to run:

·         qry=*%3Atype%3DRequestProcessor%2C* --> type=RequestProcessorwhich will locate all workers which can process requests and report their state.

·         qry=*%3Aj2eeType=Servlet%2c* --> j2eeType=Servletwhich return all loaded servlets.

·         qry=Catalina%3Atype%3DEnvironment%2Cresourcetype%3DGlobal%2Cname%3DsimpleValue --> Catalina:type=Environment,resourcetype=Global,name=simpleValuewhich look for a specific MBean by the given name.

You'll need to experiment with this to really understand its capabilites. If you provide no qry parameter, then all of the MBeans will be displayed. We really recommend looking at the tomcat source code and understand the JMX spec to get a better understanding of all the queries you may run.

 

访问 http://localhost:8080/manager/jmxproxy ,输入用户名密码,然后就可以看到返回了所有的监控信息

 

添加查询参数,则返回特定的监控信息:

例如 http://localhost:8080/manager/jmxproxy?qry=*%3Atype%3DRequestProcessor%2C*

其中 *%3Atype%3DRequestProcessor%2C* 其实就是 *:type=RequestProcessor,*

又如 http://localhost:8080/manager/jmxproxy?qry=*%3Aj2eeType%3DWebModule%2Cname%3D//localhost/ajaxrpc%2C*

 

 

在代码中访问JMX Proxy Servlet

通过浏览器访问需要输入用户名密码,所以访问JMX Proxy Servlet的URL也需要授权访问:

Java代码
  1. URL url = new URL("http://localhost:8080/manager/jmxproxy?qry=*%3Atype%3DManager%2C*");   
  2. URLConnection conn = (URLConnection) url.openConnection();   
  3.   
  4. // URL授权访问 -- Begin   
  5. String password = "tomcat:tomcat"; // manager角色的用户   
  6. String encodedPassword = new BASE64Encoder().encode(password.getBytes());   
  7. conn.setRequestProperty("Authorization", "Basic " + encodedPassword);   
  8. // URL授权访问 -- End   
  9.   
  10. InputStream is = conn.getInputStream();   
  11. BufferedReader bufreader = new BufferedReader(new InputStreamReader(is));   
  12. String line = null;   
  13. while ((line = bufreader.readLine()) != null) {   
  14.     System.out.println(line);   
  15. }  
URL url = new URL("http://localhost:8080/manager/jmxproxy?qry=*%3Atype%3DManager%2C*");URLConnection conn = (URLConnection) url.openConnection();// URL授权访问 -- BeginString password = "tomcat:tomcat"; // manager角色的用户String encodedPassword = new BASE64Encoder().encode(password.getBytes());conn.setRequestProperty("Authorization", "Basic " + encodedPassword);// URL授权访问 -- EndInputStream is = conn.getInputStream();BufferedReader bufreader = new BufferedReader(new InputStreamReader(is));String line = null;while ((line = bufreader.readLine()) != null) {	System.out.println(line);}

  

 

方案二、使用JMX接口开发监控程序

Tomcat激活JMX远程配置

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

 

Xml代码
  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%  
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=falseset 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.         上面的配置是不需要鉴权的,如果需要鉴权则添加的内容为:

Xml代码
  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%  
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.accessset CATALINA_OPTS=%CATALINA_OPTS% %JMX_REMOTE_CONFIG%

 

 

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

l         修改$CATALINA_BASE/conf/jmxremote.access 添加内容:

 

monitorRole readonly

controlRole readwrite

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

 

monitorRole tomcat

controlRole tomcat

 

注意:如果只做第一步没有问题,进行了第二步Tomcat就启动不了,那么很可能是密码文件的权限问题

Xml代码
  1. 需要修改jmxremote.password文件的权限,只有运行Tomcat的用户有访问权限   
  2.   
  3. Windows的NTFS文件系统下,选中文件,点右键 -->“属性”-->“安全”--> 点“高级”--> 点“更改权限”--> 去掉“从父项继承....”--> 弹出窗口中选“删除”,这样就删除了所有访问权限。再选“添加”--> “高级”--> “立即查找”,选中你的用户,例administrator,点“确定",“确定"。来到权限项目窗口,勾选“完全控制”,点“确定”,OK了。   
  4. 官方的提示:   
  5. The password file should be read-only and only accessible by the operating system user Tomcat is running as.   
需要修改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. 

 

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

2.         测试JMX。运行$JAVA_HOME/bin目录下的jconsole.exe,打开J2SE监视和管理控制台,然后建立连接,如果是本地的Tomcat则直接选择然后点击连接,如果是远程的,则进入远程选项卡,填写地址、端口号、用户名、口令即可连接。

3.         关于数据。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. // 端口最好是动态取得   
  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));  
String jmxURL = "service:jmx:rmi:///jndi/rmi://192.168.10.93:8999/jmxrmi";JMXServiceURL serviceURL = new JMXServiceURL(jmxURL);Map map = new HashMap();// 用户名密码,在jmxremote.password文件中查看String[] credentials = new String[] { "monitorRole", "tomcat" };map.put("jmx.remote.credentials", credentials);JMXConnector connector = JMXConnectorFactory.connect(serviceURL, map);MBeanServerConnection mbsc = connector.getMBeanServerConnection();// 端口最好是动态取得ObjectName threadObjName = new ObjectName("Catalina:type=ThreadPool,name=http-8080");MBeanInfo mbInfo = mbsc.getMBeanInfo(threadObjName);// tomcat的线程数对应的属性值String attrName = "currentThreadCount";MBeanAttributeInfo[] mbAttributes = mbInfo.getAttributes();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. }  
import java.lang.management.MemoryUsage;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Formatter;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Set;import javax.management.MBeanAttributeInfo;import javax.management.MBeanInfo;import javax.management.MBeanServerConnection;import javax.management.ObjectInstance;import javax.management.ObjectName;import javax.management.openmbean.CompositeDataSupport;import javax.management.remote.JMXConnector;import javax.management.remote.JMXConnectorFactory;import javax.management.remote.JMXServiceURL;public class JMXTest {	/**	 * @param args	 */	public static void main(String[] args) {		try {			String jmxURL = "service:jmx:rmi:///jndi/rmi://127.0.0.1:8999/jmxrmi";			JMXServiceURL serviceURL = new JMXServiceURL(jmxURL);			Map map = new HashMap();			String[] credentials = new String[] { "monitorRole", "tomcat" };			map.put("jmx.remote.credentials", credentials);			JMXConnector connector = JMXConnectorFactory.connect(serviceURL,					map);			MBeanServerConnection mbsc = connector.getMBeanServerConnection();			// 端口最好是动态取得			ObjectName threadObjName = new ObjectName(					"Catalina:type=ThreadPool,name=http-8080");			MBeanInfo mbInfo = mbsc.getMBeanInfo(threadObjName);			String attrName = "currentThreadCount";// tomcat的线程数对应的属性值			MBeanAttributeInfo[] mbAttributes = mbInfo.getAttributes();			System.out.println("currentThreadCount:"					+ mbsc.getAttribute(threadObjName, attrName));			// heap			for (int j = 0; j < mbsc.getDomains().length; j++) {				System.out.println("###########" + mbsc.getDomains()[j]);			}			Set MBeanset = mbsc.queryMBeans(null, null);			System.out.println("MBeanset.size() : " + MBeanset.size());			Iterator MBeansetIterator = MBeanset.iterator();			while (MBeansetIterator.hasNext()) {				ObjectInstance objectInstance = (ObjectInstance) MBeansetIterator						.next();				ObjectName objectName = objectInstance.getObjectName();				String canonicalName = objectName.getCanonicalName();				System.out.println("canonicalName : " + canonicalName);				if (canonicalName						.equals("Catalina:host=localhost,type=Cluster")) {					// Get details of cluster MBeans					System.out.println("Cluster MBeans Details:");					System.out							.println("=========================================");					// getMBeansDetails(canonicalName);					String canonicalKeyPropList = objectName							.getCanonicalKeyPropertyListString();				}			}			// ------------------------- system ----------------------			ObjectName runtimeObjName = new ObjectName("java.lang:type=Runtime");			System.out.println("厂商:"					+ (String) mbsc.getAttribute(runtimeObjName, "VmVendor"));			System.out.println("程序:"					+ (String) mbsc.getAttribute(runtimeObjName, "VmName"));			System.out.println("版本:"					+ (String) mbsc.getAttribute(runtimeObjName, "VmVersion"));			Date starttime = new Date((Long) mbsc.getAttribute(runtimeObjName,					"StartTime"));			SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");			System.out.println("启动时间:" + df.format(starttime));			Long timespan = (Long) mbsc.getAttribute(runtimeObjName, "Uptime");			System.out.println("连续工作时间:" + JMXTest.formatTimeSpan(timespan));			// ------------------------ JVM -------------------------			// 堆使用率			ObjectName heapObjName = new ObjectName("java.lang:type=Memory");			MemoryUsage heapMemoryUsage = MemoryUsage					.from((CompositeDataSupport) mbsc.getAttribute(heapObjName,							"HeapMemoryUsage"));			long maxMemory = heapMemoryUsage.getMax();// 堆最大			long commitMemory = heapMemoryUsage.getCommitted();// 堆当前分配			long usedMemory = heapMemoryUsage.getUsed();			System.out.println("heap:" + (double) usedMemory * 100					/ commitMemory + "%");// 堆使用率			MemoryUsage nonheapMemoryUsage = MemoryUsage					.from((CompositeDataSupport) mbsc.getAttribute(heapObjName,							"NonHeapMemoryUsage"));			long noncommitMemory = nonheapMemoryUsage.getCommitted();			long nonusedMemory = heapMemoryUsage.getUsed();			System.out.println("nonheap:" + (double) nonusedMemory * 100					/ noncommitMemory + "%");			ObjectName permObjName = new ObjectName(					"java.lang:type=MemoryPool,name=Perm Gen");			MemoryUsage permGenUsage = MemoryUsage					.from((CompositeDataSupport) mbsc.getAttribute(permObjName,							"Usage"));			long committed = permGenUsage.getCommitted();// 持久堆大小			long used = heapMemoryUsage.getUsed();//			System.out.println("perm gen:" + (double) used * 100 / committed					+ "%");// 持久堆使用率			// -------------------- Session ---------------			ObjectName managerObjName = new ObjectName(					"Catalina:type=Manager,*");			Set<ObjectName> s = mbsc.queryNames(managerObjName, null);			for (ObjectName obj : s) {				System.out.println("应用名:" + obj.getKeyProperty("path"));				ObjectName objname = new ObjectName(obj.getCanonicalName());				System.out.println("最大会话数:"						+ mbsc.getAttribute(objname, "maxActiveSessions"));				System.out.println("会话数:"						+ mbsc.getAttribute(objname, "activeSessions"));				System.out.println("活动会话数:"						+ mbsc.getAttribute(objname, "sessionCounter"));			}			// ----------------- Thread Pool ----------------			ObjectName threadpoolObjName = new ObjectName(					"Catalina:type=ThreadPool,*");			Set<ObjectName> s2 = mbsc.queryNames(threadpoolObjName, null);			for (ObjectName obj : s2) {				System.out.println("端口名:" + obj.getKeyProperty("name"));				ObjectName objname = new ObjectName(obj.getCanonicalName());				System.out.println("最大线程数:"						+ mbsc.getAttribute(objname, "maxThreads"));				System.out.println("当前线程数:"						+ mbsc.getAttribute(objname, "currentThreadCount"));				System.out.println("繁忙线程数:"						+ mbsc.getAttribute(objname, "currentThreadsBusy"));			}		} catch (Exception e) {			e.printStackTrace();		}	}	public static String formatTimeSpan(long span) {		long minseconds = span % 1000;		span = span / 1000;		long seconds = span % 60;		span = span / 60;		long mins = span % 60;		span = span / 60;		long hours = span % 24;		span = span / 24;		long days = span;		return (new Formatter()).format("%1$d天 %2$02d:%3$02d:%4$02d.%5$03d",				days, hours, mins, seconds, minseconds).toString();	}}

  

 

如何实现高校科技成果转化的高效对接?.docx 科易网基于40亿+科创知识图谱数据库,深度探索AI技术在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,研究科技创新领域的AI+数智化解决方案,推动科技创新与产业创新智能化发展。 立即下载

相关推荐

TinyML边缘智能振动诊断实战-ESP32完整工程-v1.0.zip

无硬件可完整体验:固件内置信号合成模拟器(严格复现训练物理模型),串口发 S0~S3 切换 4 种机器故障 算子级正确性:用 inspect_model_ops.py 从 tflite 解析出实际算子(EXPAND_DIMS/CONV_2D/RESHAPE/MEAN/FC/SOFTMAX),固件注册逐对应——规避了 TFLite Micro 最常见的 "Op type not found" 坑 诚实标注:文档中明确区分“合成演示数据 / 工程近似 / 实测值”,并给出接入真实数据的完整流程

Stagemonitor:Java Web应用程序的性能监视

stagemonitor是用于Java应用程序性能监视(也称为APM –应用程序性能监视)的开源解决方案,它为开发人员提供了许多工具。 stagemonitor可用于开发以及监视Java Web应用程序的性能。 借助用于分布式系统的Open Tracing API,该工具集还可以处理集群或微服务体系结构。 这样,不仅可以访问实时数据,而且还可以追溯访问历史数据池。 舞台监听功能 在开发应用...

953

基于SpringBoot+Vue校园失物招领系统的设计与实现

校园失物招领系统的设计与实现前端采用了Vue框架,并结合ElementUI来实现界面的设计与布局。后端采用了SpringBoot框架进行开发设计,并结合了Java语言和MySQL数据库来实现。在功能上分为了前端用户模块和管理员模块。前端用户模块主要实现了招领物品信息的发布、查询与管理,失物信息的发布、管理以及自动匹配招领物品,查看校园相关通知公告。管理员模块主要实现了物品分类管理、校园通知管理以及物品招领信息的查询统计等功能。校园失物招领系统的实现优化失物招领的流程,提高了校园失物招领的效率,促进了校园文化的建设,营造了良好的诚信氛围。

监控Tomcat解决方案监控应用服务器系列文章

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

aluobi9746的博客 199

监控Tomcat解决方案监控应用服务器系列文章

监控Tomcat解决方案监控应用服务器系列文章) 博客分类:  监控应用服务器 监控应用服务器监控TomcatJMX Proxy Servlet使用JMX监控Tomcat 前言:最近在做监控应用服务器(Tocmat、WebSphere、WebLogic)的项目,目前已小有规模,回 头看看,路走来,也算是磕磕绊绊,遇到过种种问题,走过不少弯路,不过程序员最不

jgwei的专栏 1711

使用JMX监控Tomcat监控应用服务器系列文章

前言:本文是从“监控Tomcat方案调研监控应用服务器系列文章) ”文剥离出来的,专门探讨如何使用JMX监控Tomcat,本系列文章详见本人专栏: 监控应用服务器 。     、激活TomcatJMX远程配置   要通过JMX远程监控Tomcat,首先需要激活TomcatJMX远程配置。   ① 先修改Tomcat的启动脚本,windows下为bin/ca

skiof007的专栏 1316

应用服务管理开发

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

killerover84的专栏-----天下 754

Java知识体系最强总结(2020版)

本人从事Java开发已多年,平时有记录问题解决方案和总结知识点的习惯,整理了些有关Java的知识体系,这不是最终版,会不定期的更新。也算是记录自己在从事编程工作的成长足迹,通过博客可以促进博主与阅读者的共同进步,结交更多志同道合的朋友。特此分享给大家,本人见识有限,写的博客难免有错误或者疏忽的地方,还望各位大佬指点,在此表示感激不尽。 整理的Java知识体系主要包括基础知识,工具,并发编程,数...

csdn_life18的博客 5万+

SAP ME制造执行系统实战:从核心功能到集成部署全解析

制造执行系统(MES)作为连接企业计划层与车间控制层的核心枢纽,是实现生产透明化与实时管控的关键技术。其核心原理在于打通ERP与现场设备的数据流,通过实时采集生产进度、质量与设备状态,形成计划、执行、反馈的数字化闭环。这技术为制造业带来的核心价值是消除信息孤岛,实现生产过程的精细化管理和全程可追溯,从而提升效率、保证质量并降低成本。在汽车、电子、制药等流程复杂、管控要求高的行业,MES的应用场景尤为广泛。本文聚焦于SAP ME这企业级MES解决方案,深入剖析其如何与SAP ERP(如S/4HANA)进行

weixin_34054931的博客 391

自己动手写tomcat之8多应用

本文看下我们的tomcat如何支持多应用的场景。

wang0907的博客 212

Tomcat本地部署+远程服务器部署超详细教程

修改,在<Host>path:浏览器访问项目路径docBase:本地项目真实存放路径reloadable="true":修改代码自动热部署,无需重启服务。

m0_63611023的博客 205

Tomcat

CATALINA_OPTS -Dsun.net.inetaddr.ttl=0 -Dsun.net.inetaddr.negative.ttl=01. Dsun.net.inetaddr.ttl=0:这个系统属性设置了网络地址(InetAddress)的生存时间(TTL,Time-To-Live)为0。- HTTP端口是用于处理HTTP请求的端口。:设置个自定义的响应头X-Real-IP,其值为发起请求的客户端IP地址,这有助于识别真实的客户端IP,特别是在使用了HTTP代理或负载均衡器的情况下。

2601_96206323的博客 234

科技成果转化效率低怎么办?.docx

科易网基于40亿+科创知识图谱数据库,深度探索AI技术在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,研究科技创新领域的AI+数智化解决方案,推动科技创新与产业创新智能化发展。

产业园区如何搭建统的科技服务平台?.docx

科易网基于40亿+科创知识图谱数据库,深度探索AI技术在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,研究科技创新领域的AI+数智化解决方案,推动科技创新与产业创新智能化发展。

复现基于改进秃鹰算法的微电网群经济优化调度研究(Matlab代码实现)

内容概要:本文围绕“基于改进秃鹰算法的微电网群经济优化调度”展开研究,提出了种改进的秃鹰搜索算法(BES),旨在解决微电网群在复杂运行环境下的多目标、强约束、非线性及高维经济调度问题。通过引入特定优化策略,增强了基础算法的全局搜索能力和收敛效率,克服了传统智能算法易陷入局部最优的缺陷。研究构建了个包含分布式电源、储能系统与多元负荷的微电网群调度模型,以最小化系统综合运行成本为核心目标,综合考虑功率平衡、设备出力能力、储能运行特性等多重约束条件。通过仿真实验验证了所提算法在调度精度、稳定性和计算效率方面相较于传统方法具有明显优势,并进步展示了其在降低能源开支、提升可再生能源消纳水平方面的实际应用价值。; 适合人群:具备定电力系统基础知识或优化算法背景,从事新能源调度、智能优化算法研究与应用等相关领域的研究生、科研人员及工程技术人员。; 使用场景及目标:①应用于微电网群、综合能源系统等场景下的经济调度优化;②为秃鹰算法及其他群体智能算法的改进、复现与性能对比提供参考范例;③服务于科研仿真、算法验证及工程化应用需求。; 阅读建议:建议读者结合文中提供的Matlab代码实现进行实践操作,重点关注算法改进机制与调度模型的构建逻辑,同时可借助网盘资源获取完整资料,以加深对算法性能表现与应用场景的理解。

上一篇: 编写JAVA程序收集Tomcat性能数据
下一篇: JMX连接Mbean获取Tomcat信息
asmallrole
博客等级 码龄15年 2粉丝 0原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值