JMX(Java Management Extensions)是Java平台上为应用程序、设备、系统等植入管理功能的框架。JMX可以跨越一系列异构操作系统平台、系统体系结构和网络传输协议,灵活的开发无缝集成的系统、网络和服务管理应用。
结构
JMX Jconsole以及Web Browser属于应用层,我们可以不用关注:
- 分布层(Distributed layer):即图中RMI,HTTP/SOAP,HTTP/HTML,SNMP,这层通常被封装成适配器(Adapter),将JMX信息封装成调用接口提供给外层
- 代理层(Agent layer):即图中的MBeanServer,负责MBeans的注册管理
- 仪表层(Instrumentation layer):即图最下方的MBeans,每个MBean都是一个被管理的资源,通过对外暴露的方法和属性,实现被上层获取和调用
远程连接
如果要启用远程连接,需要在启动应用时添加以下参数:
1 | -Dcom.sun.management.jmxremote |
连接Tomcat配置
可以直接修改catalina.sh
,也可以修改setenv.sh
(推荐):
摘自
catalina.sh
Do not set the variables in this script. Instead put them into a script setenv.sh in CATALINA_BASE/bin to keep your customizations separate.
无需认证配置
1 | CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.port=7431 // jmx远程端口 |
认证配置
1 | CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.port=7431 // jmx远程端口 |
jmxremote.access&jmxremote.password
两个文件模板可以在../jdk/jre/lib/management
路径下找到
此处需要对这两个文件变更权限:
1 | chmod 600 jmxremote.* |
jmxremote.access
文件中配置了用户名,以及对应的权限:
1 | monitorRole readonly // 只读,监控权限配置这个即可 |
jmxremote.password
文件中配置了用户名,以及对应的密码:
1 | monitorRole QED |
配置完成后需要重启服务,通过jconsole
,使用配置的用户名(monitorRole
)和密码(QED
)即可连接服务
获取示例
1 | public class JmxSimpleTest { |
在ManagementFactory.java
中定义了一些我们可以直接获取到的jvm信息的类:
1 | // jvm类加载数量,卸载数量,对应`ClassLoadingMXBean` |
对比jconsole
,通过上面这种方式获取到的信息有限,例如OperatingSystem
只能获取到处理器数量等基本信息,无法获取到像是文件描述符数,交换空间大小等信息:
好在jmx还提供了另外一种方法MBeanServerConnection.getAttributes()
:
1 | ObjectName objectName = new ObjectName("java.lang:type=OperatingSystem"); |
通过这种方法,我们也可以获取tomcat相关信息:
1 | ObjectName objectName = new ObjectName("Catalina:name=\"http-nio2-20041\",type=GlobalRequestProcessor"); // 此处的20041为tomcat运行端口,在server.xml配置 |
创建自定义MBean
假如现在要定义一个计数器Counter,按照惯例,Counter对应的MBean需要以MBean结尾:
1 | public interface CounterMBean { |
CounterMBean
中定义的方法,都是可以提供给远程调用的,现在做下实现:
1 | public class Counter implements CounterMBean { |
接下来我们需要在MbeanServer
中注册CounterMBean
:
1 | public class CounterJmxRegisterTest { |
ObjectName
定义规则为“域:键值对(可以多个)
”,域
的值可以任意,示例中为test.xyz
,:
后为多组键值对(在jconsole中以嵌套文件夹体现),如a=abc
或者a=a,b=b
运行后使用jconsole连接:
可以看到CounterMBean
已经注册了,并且提供了一个可执行的方法incr
,以及可修改的属性Count
,因为我们对Count
实现了get/set方法,所以显示的的可读/可写都是true
修改MBean属性值和调用方法
除了获取MBean的属性值外,还可以修改MBean的属性值和调用接口方法:
1 | public class CounterJmxTest { |
通知(Notification)
Notification
起到了在MBean之间沟通桥梁的作用,Notification
模型和Java Event
模型类似,将一些重要的信息,状态的转变,数据的变更传递给Notification Listener
,以便资源的管理。Notification
由四部分组成:
1 | Notification:通用来说就是需要发送的消息,可以被直接使用,也可以根据传递的事件的需要而被扩展。 |
修改Counter
,添加一个通知:
1 | public class Counter extends NotificationBroadcasterSupport implements CounterMBean { |
创建监听器:
1 | public class CounterListener implements NotificationListener { |
在注册MBean后,注册监听器:
1 | public class CounterJmxRegisterTest { |
当调用Counter.setCount
时,控制台输出:
1 | 1 |
参考
JMX远程监控JVM
Deep Dive into Java Management Extensions (JMX)
从零开始玩转JMX
JMX超详细解读
JMX monitoring + Java custom metrics.