jmx监控tomcat

jmx监控tomcat

一、环境:

1、监控端client:macOS

2、被监控端server:系统Ubuntu16.0.4,tomcat8

二、步骤:

1、修改文件配置tomcat/bin/catalina.sh

在文件开头的一大段注释下添加以下内容:

CATALINA_OPTS=”$CATALINA_OPTS -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 -Djava.rmi.server.hostname=192.168.31.187”

这其中-Dcom.sun.management.jmxremote.port=8999 设置端口号

-Dcom.sun.management.jmxremote.ssl=false 不使用ssl安全认证

-Dcom.sun.management.jmxremote.authenticate=true 设置用户名和密码认证

-Dcom.sun.management.jmxremote.password.file=../conf/jmxremote.password 用户和密码文件

-Dcom.sun.management.jmxremote.access.file=../conf/jmxremote.access 权限文件

-Djava.rmi.server.hostname=192.168.31.187”设置本机的ip(不设置的话client请求到本机本机会返回一个hostname对象,client再请求本机hostname对应的ip,参考http://blog.csdn.net/yangyan19870319/article/details/6732411
2、复制java/jdk/jre/lib/management/下的jmxremote.access、jmxremote.password.template文件到/tomcat/conf/下
(1)把jmxremote.password.template重命名为jmxremote.password,
修改两个文件的权限:
chmod 600 jmxremote.access
chmod 600 jmxremote.password
(2)设置用户权限,在jmxremote.access里的最后面添加(没有则添加)如下内容:
monitorRole readonly
controlRole readwrite \
create javax.management.monitor.,javax.management.timer. \
unregister
这里写图片描述
(3)编辑最后的账户密码,在jmxremote.password.里的最后面添加(没有则添加)如下内容:
monitorRole mj #密码可以随便取
controlRole mj #密码可以随便取
这里写图片描述
3、到tomcat/bin下用 ./shutdown.sh和./start.sh来测试是否能正常启动和关闭tomcat,若不能则配置错误;
4、启动tomcat,用netstat –ntlp
这里写图片描述
看得刚才配置8999端口,证明成功一半了。
5、监控端连接tomcat的代码:

package jmx;

import java.lang.management.MemoryUsage;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.management.MBeanServerConnection;
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 tomcat {
    private static Formatter format = new Formatter();

    public static void main(String[] args) throws Exception {
        String jmxURL = "service:jmx:rmi:///jndi/rmi://192.168.31.133:8999/jmxrmi";  
        JMXServiceURL serviceURL = new JMXServiceURL(jmxURL);  

        Map map = new HashMap();  
        // 用户名密码,在jmxremote.password文件中查看  
        String[] credentials = new String[] { "monitorRole", "QED" };
        map.put("jmx.remote.credentials", credentials);
        JMXConnector connector = JMXConnectorFactory.connect(serviceURL, map);  
//      JMXConnector connector = JMXConnectorFactory.connect(serviceURL, null);  
        MBeanServerConnection mbsc = connector.getMBeanServerConnection();  

        // 端口最好是动态取得  

         ObjectName grpObjName = new ObjectName("Catalina:type=GlobalRequestProcessor,*");
         Set<ObjectName> grps = mbsc.queryNames(grpObjName, null);
         for (ObjectName obj : grps) {
             System.out.println("名称:" + obj.getKeyProperty("name"));
             ObjectName objname = new ObjectName(obj.getCanonicalName());
             System.out.println("bytesReceived:" + mbsc.getAttribute(objname, "bytesReceived"));
             System.out.println("bytesSent:" + mbsc.getAttribute(objname, "bytesSent"));
             System.out.println("requestCount:" + mbsc.getAttribute(objname, "requestCount"));
         }
         //线程池
         ObjectName threadObjName = new ObjectName("Catalina:type=ThreadPool,name=\"*http*\"");
         Set<ObjectName> smbi = mbsc.queryNames(threadObjName, null);
         for (ObjectName obj : smbi) {
             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"));
         }
         // ------------------------ 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("连续工作时间:" + tomcat.formatTimeSpan(timespan));

      // 堆使用率
         ObjectName heapObjName = new ObjectName("java.lang:type=Memory");
         MemoryUsage heapMemoryUsage = MemoryUsage
                 .from((CompositeDataSupport) mbsc.getAttribute(heapObjName, "HeapMemoryUsage"));
         long maxMemory = heapMemoryUsage.getMax();// 堆最大
         System.out.println("heap size:" + maxMemory);
         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*");
         Set<ObjectName> sperm = mbsc.queryNames(permObjName, null);
         for (ObjectName obj : sperm) {
             ObjectName objname = new ObjectName(obj.getCanonicalName());
             MemoryUsage permGenUsage = MemoryUsage.from((CompositeDataSupport) mbsc.getAttribute(objname, "Usage"));
             long committed = permGenUsage.getCommitted();// 持久堆大小
             long used = heapMemoryUsage.getUsed();//
             System.out.println("perm gen:" + (double) used * 100 / committed + "%");// 持久堆使用率
         }
    }
    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 format.format("%1$d天 %2$02d:%3$02d:%4$02d.%5$03d", days, hours, mins, seconds, minseconds).toString();
    }

}

6、运行代码如果以下错误
这里写图片描述
原因是:除了JMX server指定的监听端口号外,JMXserver还会监听一到两个随机端口号,
这里写图片描述
绿色线两个端口就是随机端口(pid跟8999端口的pid一样)。
解决方法有两种:
第一种:关闭防火墙
第二种:每次启动java进程后查看这两个随机端口然后添加这两个端口到防火墙配置(最好的方法是用脚本获取两个随机端口然后修改防火墙配置并重启防火墙)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值