`
zpball
  • 浏览: 898833 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

监控应用服务器---使用JMX监控Tomcat

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

一、激活Tomcat的JMX远程配置

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

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

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】一句后的大段的注释后面。

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


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

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 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示例代码
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));  






三、完整的示例代码文件
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();  
    }  
}  





分享到:
评论

相关推荐

    tomcat-catalina-jmx-remote-8.0.9.jar

    当你想深入学习jvm的时候,肯定会用到。用于使用jvisualvm.exe远程监控服务器jvm

    通过Tomcat开启JMX监控的方法图解

     # cd /opt/tomcat/apache-tomcat-8.0.48/bin/  2、编辑配置文件  # vim catalina.sh  3、在下图中上面添加参数    参数添加后的样子  3.1、此配置连接jmx不需要账号密码:  CATALINA_OPTS=$CATALINA_OPTS ...

    tomcat zabbix 监控模板

    修改&lt;TOMCAT_HOME&gt;/conf目录下的tomcat-users.xml文件,在&lt;tomcat-users&gt;节点下添加一个user节点 如: c. 重启验证 http://ip:port/manager/jmxproxy 输入账号密码能显示TOMCAT状态信息 2)监控脚本 ...

    JConsole_远程监控Tomcat_ricky

    JConsole是一个基于JMX的GUI工具,用于连接正在运行的JVM,不过此JVM需要使用可管理的模式启动。如果要把一个应用以可管理的形式启动,可以在启动是设置com.sun.management.jmxremote。JConsole能够提供被监控虚拟机...

    Jetty中文手册

    Porting from Tomcat Jetty版本比较列表 参考 Jetty 7 Latest JavaDoc Jetty 7 Latest Source XRef Index of Generated Release Documents–API and XRef documentation for previous releases. 通用参考 Jetty体系...

    Jpom项目监控软件-其他

    3、cpu、ram 监控、导出堆栈信息、查看项目进程端口、服务器状态监控 4、多节点管理、多节点自动分发 5、实时监控项目状态异常自动报警 6、在线构建项目发布项目一键搞定 7、多用户管理,用户项目权限独立(上传、...

    springboot参考指南

    在前端代理服务器后使用Tomcat ix. 64.9. 使用Jetty替代Tomcat x. 64.10. 配置Jetty xi. 64.11. 使用Undertow替代Tomcat xii. 64.12. 配置Undertow xiii. 64.13. 启用Undertow的多监听器 xiv. 64.14. 使用Tomcat7 i...

    java开源包1

    Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO操作,以提升性能。 预输入搜索 Cleo Cleo 是一个灵活的软件库用于处理一些预输入和自动完成的搜索功能,该项目是 LinkedIn 公司...

    java开源包10

    Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO操作,以提升性能。 预输入搜索 Cleo Cleo 是一个灵活的软件库用于处理一些预输入和自动完成的搜索功能,该项目是 LinkedIn 公司...

    java开源包8

    Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO操作,以提升性能。 预输入搜索 Cleo Cleo 是一个灵活的软件库用于处理一些预输入和自动完成的搜索功能,该项目是 LinkedIn 公司...

    java开源包11

    Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO操作,以提升性能。 预输入搜索 Cleo Cleo 是一个灵活的软件库用于处理一些预输入和自动完成的搜索功能,该项目是 LinkedIn 公司...

    java开源包2

    Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO操作,以提升性能。 预输入搜索 Cleo Cleo 是一个灵活的软件库用于处理一些预输入和自动完成的搜索功能,该项目是 LinkedIn 公司...

    java开源包3

    Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO操作,以提升性能。 预输入搜索 Cleo Cleo 是一个灵活的软件库用于处理一些预输入和自动完成的搜索功能,该项目是 LinkedIn 公司...

    java开源包6

    Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO操作,以提升性能。 预输入搜索 Cleo Cleo 是一个灵活的软件库用于处理一些预输入和自动完成的搜索功能,该项目是 LinkedIn 公司...

    java开源包5

    Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO操作,以提升性能。 预输入搜索 Cleo Cleo 是一个灵活的软件库用于处理一些预输入和自动完成的搜索功能,该项目是 LinkedIn 公司...

    java开源包4

    Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO操作,以提升性能。 预输入搜索 Cleo Cleo 是一个灵活的软件库用于处理一些预输入和自动完成的搜索功能,该项目是 LinkedIn 公司...

    java开源包7

    Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO操作,以提升性能。 预输入搜索 Cleo Cleo 是一个灵活的软件库用于处理一些预输入和自动完成的搜索功能,该项目是 LinkedIn 公司...

    java开源包9

    Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO操作,以提升性能。 预输入搜索 Cleo Cleo 是一个灵活的软件库用于处理一些预输入和自动完成的搜索功能,该项目是 LinkedIn 公司...

    java开源包101

    Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO操作,以提升性能。 预输入搜索 Cleo Cleo 是一个灵活的软件库用于处理一些预输入和自动完成的搜索功能,该项目是 LinkedIn 公司...

Global site tag (gtag.js) - Google Analytics