Java高级开发必备技能之JMX监控

JMX监控java项目内容 之 标准MBean

JMX是Java Management Extensions 的简写,即Java管理扩展.
通过JMX,我们可以监控的内容包括:

1、服务器中各种资源的使用情况:如CPU、内存等
2、JVM内存使用情况
3、JVM中的线程情况
4、JVM中加载的类

JMX技术可以被分为3层,如下:

* 监测(Instrumentation)
* JMX代理
* 远程管理

图片如下:

监控层的作用就是使用MBean来监控我们关心的性能指标。因为通常关注的性能指标比较多,通常情况下,在监控层我们会有多个MBean,每个MBean监控一类信息。

JMX代理相当于一个容器,所有的MBean都注册到这个容器中。这个容器可以接受外部的请求,返回MBean的监控信息。当我们想从远程获取某个MBean的检测信息,我们就给这个容器发送一个请求,由这个容器将这个MBean的检测信息返回给我们。JMX代理的核心组件是MBean server,它是一个被管理对象的服务器,MBeans在其中注册。一个JMX代理还包括一组用于管理MBeans的服务和至少一个通信适配器(adaptor)或连接器(connector) 以供管理程序访问。

使用一个远程客户端连接MBean Server来获取MBean的监控信息。


JMX规范定义了5种MBean:
	1.	标准MBeans
	2.	动态MBeans
	3.	Open MBeans
	4.	Model MBeans
	5.	MXBeans

但是对于我们日常需要监控的数据,我们只需要编码方式比较简单的标准MBeans即可,这种方式返回的都是基本的数据类型。


下面讲解标准MBean的编写方式和规范

要有一个叫xxxMBean的接口,然后继承这个MBean接口的类名必须是xxx类,否则无法注册到jmx代理中。

第一步:编写MBean接口和对应的实现类

实现类

public class Test implements TestMBean {

   private String name = "你好啊";

   public String getName() {
	  return name;
   }

   public void setName(String name) {
	  this.name = name;
   }

   @Override
   public String printHello() {
	  String name = "你好!";
	  return  name;
   }

   @Override
   public String printTestParams(String param) {
	  return param;
   }

}

接口

public interface TestMBean {

   public String printHello();

   public String printTestParams(String param);

}

上述代码中的第二种方法可以通过修改传参来获取到对应的数据!

第二步:创建对应的jmx代理并将mbean注册到代理中

public static void main(String[] args) throws Exception {

   MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
   ObjectName name = new ObjectName("com.game.jmx.mbean:type=Test");
   Test mbean = new Test();
   mbs.registerMBean(mbean, name);

   System.out.println("Waiting forever...");
   Thread.sleep(Long.MAX_VALUE);
}

若是要启动远程连接此时就需要定义一个IP和端口

/**
 * 开启JMX监控
 *
 * @throws Exception
 */
public void startJmx(int port) {
   try {
	  String ip = InetAddress.getLocalHost().getHostAddress();//获得本机IP
	  LocateRegistry.createRegistry(port);
	  JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + ip + ":" + port + "/jmxrmi");
	  JMXConnectorServer ser = JMXConnectorServerFactory.newJMXConnectorServer(url, null, server);
	  ser.start();
   } catch (Exception e) {
	  JmxMgr.log.error("启动jmx错误,{}", e);
   }
}

上述代码中的server就是MBeanServer。

ps:要开启远程监控的方式需要配置如下
如果只是本地类测试,只需要配置端口和ip即可

若要远程监控需要配置

找到文件 /tomcat/bin/catalina.sh
找到下面的内容
# —– Execute The Requested Command —————————————–
在其上,添加以下配置


authenticate,true 开启鉴权功能
access.file,权限文件路径
password.file,密码文件路径

将 JAVA_HOME/jre/lib/management 下面的 jmxremote.access 和jmxremote.password.template 拷贝到 tomcat conf目录下
1:jmxremote.password.template文件名修改为jmxremote.password。
2:修改两个文件的权限
chmod 600 jmxremote.access
chmod 600 jmxremote.password

第三步:查看MBean数据

此时jmx代理也编写完毕,此时就有两种方式来查看MBean对应的信息
第一种方式就是直接的打开Jconsole或者Jvisulevm来查看对应的mbean
第二种方式就是编码连接到jmx代理然后进行查看

这里说一下第二种方式
连接到jmx服务器

/**
 * 客户端链接到远程jmx服务器
 */
public static MBeanServerConnection connectJmx(int jmxPort) {
   MBeanServerConnection mbsc = null;
   try {
	  //链接到远程JMX
	  String jmxAddress = InetAddress.getLocalHost().getHostAddress();//获得本机IP,远程的就是远程机器的IP地址
	  JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + jmxAddress + ":" + jmxPort + "/jmxrmi");
	  JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
	  mbsc = jmxc.getMBeanServerConnection();
   } catch (Exception e) {
	  log.error("链接jmx服务器失败,错误{}", e);
   }
   return mbsc;
}

上述代码可以获取到对应的jmx远程连接,此时可以通过远程连接到操作对应的mbean了
如下:

//构建要查询的类
ObjectName objectName = new ObjectName("gs:name=com.server.game.jmx.mbean.Test");
MBeanInfo mBeanInfo = mbsc.getMBeanInfo(objectName);

//获取MBean的方法
TestMBean testMBean = MBeanServerInvocationHandler.newProxyInstance(mbsc, objectName, TestMBean.class, false);
String s = testMBean.printHello();

System.out.println(s);

获取内存的数据

//获取内存的使用情况
MemoryMXBean memBean = ManagementFactory.newPlatformMXBeanProxy(mbsc, ManagementFactory.MEMORY_MXBEAN_NAME, MemoryMXBean.class);
MemoryUsage heap = memBean.getHeapMemoryUsage();
//堆使用情况
long used = heap.getUsed();
long committed = heap.getCommitted();

至此,一个基于标准MBean的jmx监控就开发完毕了。

当然jmx的监控也没有这么简单,其中还有MBean与Mbean之间的通知的机制,同时也有其他动态的MBean,此种MBean的方式可以返回比较复杂的数据结构,不想MBean只能返回基本的数据类型。

昨天老大又说要返回一个对象!此刻,懵逼了!好吧,继续研究JMX!

JMX监控java项目内容 之 MXBean

jmx可以返回对象这种复杂的数据类型,这个叫MXBean 。 前提是返回的对象的父类中不能有Abstract类,否则会报错。报错的如下

javax.management.NotCompliantMBeanException: 
com.server.game.jmx.mxbean.map.MapInfoMXBean:
Method com.server.game.jmx.mxbean.map.MapInfoMXBean.getMServer has parameter 
or return type that cannot be translated into an open type

注册MBean的时候报错,其实就是在对返回的对象进行内省的时候判断不是接口而是Abstract就包上述错误了
源码如下:

 private MBeanAnalyzer(Class<?> mbeanType,
        MBeanIntrospector<M> introspector)
        throws NotCompliantMBeanException {
    if (!mbeanType.isInterface()) {
        throw new NotCompliantMBeanException("Not an interface: " +
                mbeanType.getName());
    } else if (!Modifier.isPublic(mbeanType.getModifiers()) &&
               !Introspector.ALLOW_NONPUBLIC_MBEAN) {
        throw new NotCompliantMBeanException("Interface is not public: " +
            mbeanType.getName());
    }

    try {
        initMaps(mbeanType, introspector);
    } catch (Exception x) {
        throw Introspector.throwException(mbeanType,x);
    }
}

好吧!那就自己重写返回的对象,即可!

编写MXBean的方式和MBean的方式是一样的,只是将MBean接口改为MXBean接口即可。

总结:Jmx是很强大的一种jvm监控工具,我们在开发中还是必须要掌握的一种技能!

猜你喜欢

转载自blog.csdn.net/huanghailiang_ws/article/details/96837529
今日推荐