tomcat学习之JMX应用
1 JMX概述
1.1 JMX是什么
Java Management Extensions(JMX)是java语言的扩展,是一种规范,提供对受管资源的管理功能。这种管理功能可以具体为查看对象的属性,或者调用对象的方法。举个具体的例子,JVM通过JMX提供了对内存的管理功能,我们可以通过jdk自动的工具jconsole查看JVM的内存使用情况,关于jconsole超出了本文的范围,这里不多说了。
据我所接触的,服务级别的程序比较喜欢用JMX,因为对自身资源的监控是服务器实现的重要部分。比如:应用服务器有weblogic、jboss、tomcat,之前看hadoop的源码,也看到了JMX的影子。
1.2 两个核心概念
Ø MBeanServer
可以看成JMX的容器,存储所有的受管对象(MBean)
Ø MBean
受管接口,告知MBeanServer可以对受管对象进行哪些管理操作。JMX提供了多种MBean,比如:Standard MBean、Dynamic MBean、Open MBean、Model MBean等。其中Standard MBean是以接口的方式告知MBeanServer,该接口的实现类都提供接口承诺的实现。Tomcat中的JMX是通过Dynamic MBean来实现的。
1.3 JMX例子
JMX的简单例子,网上有比较多,可以看看http://www.blogjava.net/hengheng123456789/articles/65690.html,更多更全的例子,可以在oracle官网下载JMX,里面有example,他对JMX的使用进行了详细的说明。
2 Tomcat中的JMX
2.1 JMX的作用
如上文所说,tomcat作为应用服务器,对tomcat资源的监控和管理是在做tomcat架构设计的时候需要考虑的问题。
用过tomcat的人,应该都会知道server.xml,tomcat读取该配置文件来实例化核心类和设置其属性,比如:Server、Listener、GlobalNamingResources、Service、Connector、Engine、Realm等。Tomcat的JMX服务提供了对这些核心类的管理功能。有图为证:
2.2 初始化过程
2.2.1 MBeanServer初始化
Tomcat中MBeanServer在启动类Bootstrap中完成,具体的代码在方法createClassLoader中,如下:
// Retrieving MBean server MBeanServer mBeanServer = null; if (MBeanServerFactory.findMBeanServer(null).size() > 0) { mBeanServer = MBeanServerFactory.findMBeanServer(null).get(0); } else { mBeanServer = ManagementFactory.getPlatformMBeanServer(); |
说实话,这段代码有点隐蔽,tomcat的用意是对创建的classLoader注册到MBeanServer中,但是为什么不使用如下的代码:
mserver = Registry.getRegistry(null, null).getMBeanServer(); |
从作用上来讲,应该是一样的,个人觉得更应该用后面的代码。
2.2.2 Mbean的注册
Tomcat中使用的是DynamicMBean,意味着每个被注册到MBeanServer中的类实例,都需要有一个对应的DynamicMBean的实例,提供对应的MBean元数据信息(提供哪些属性和哪些操作)。这里以StandardServer为例讲解注册过程。
对于StandardServer的MBean的元数据的获取有两种实现方式:
1、tomcat启动的时候,触发MBeanUtils.createRegistry(),执行registry.loadDescriptors("com.pengsy.catalina.core", cl) 代码,完成StandardServer预定义MBean的元数据的加载工作,同时加载的元数据,以键值对的方式存储在Register的属性descriptors和descriptorsByClass中,同样是两个键值对,键是有区别的,前者用的是ManagedBean的name,后者的键用的是ManagedBean的className。代码入口:
public static synchronized Registry createRegistry() { if (registry == null) { registry = Registry.getRegistry(null, null); ClassLoader cl = MBeanUtils.class.getClassLoader(); registry.loadDescriptors("com.pengsy.catalina.mbeans", cl); registry.loadDescriptors("com.pengsy.catalina.authenticator", cl); } return (registry); } |
2、在注册的时候StandardServer的时候,tomcat会在Register的descriptors和descriptorsByClass查找对应的ManagedBean信息,如果没有Register中没有存储这个信息,会再次尝试加载XML文件中预定义的ManagedBean信息,如果不存在XML文件,最后会用反射的方式,基于StandardServer类生成对应的ManagedBean信息,随后tomcat用这个对象去注册StandardServer。代码如下:
public ManagedBean findManagedBean(Object bean, Class<?> beanClass, String type) throws Exception { // first look for existing descriptor ManagedBean managed = findManagedBean(type); // Search for a descriptor in the same package if( managed==null ) { findDescriptor( beanClass, type ); managed=findManagedBean(type); } // Still not found - use introspection if( managed==null ) { if( log.isDebugEnabled() ) { log.debug( "Introspecting "); } // introspection loadDescriptors("MbeansDescriptorsIntrospectionSource", beanClass, type); managed=findManagedBean(type); if( managed==null ) { log.warn( "No metadata found for " + type ); return null; } managed.setName( type ); addManagedBean(managed); } return managed; } |
2.2.3 三个关键时间点
第一个时间点:MBeanServer的初始化,这一点在2.2.1节已经做过说明,不再赘述。
第二个时间点:触发MBeanUtils.createRegistry()的时间点。在tomcat加载配置文件server.xml中的GlobalResourcesLifecycleListener时,tomcat会创建这个类的实例,registry作为这个类的私有静态属性,直接在定义这个属性的时候,就通过调用MBeanUtils.createRegistry()方法赋值。代码如下:
public class MBeanUtils { private static Registry registry = createRegistry(); } |
第三个时间点:每个继承LifecycleMBeanBase的类执行其方法initInternal方法的时候。子类的initInternal方法总会贱贱的调用父类LifecycleMBeanBase的initInternal方法,将自己注册到MBeanServer中。
2.3 JMX类模型
说明:该图通过调整word的显示比例,可以看得更清楚。
核心类清单:
类名 |
作用说明 |
Registry |
提供加载MBean元数据服务; 提供MBean的注册服务; 提供MBean的查找服务。 |
ModelerSource |
抽象类,用于加载Mbean的元数据。 |
MbeansDescriptorsDigesterSource |
ModelerSource的子类,用于加载mbeans-descriptors.xml定义的MBean元数据。 |
MbeansDescriptorsIntrospectionSource |
ModelerSource的子类,用于通过反射机制创建指定类的MBean元数据。 |
BaseModelMBean |
注册到MBeanServer中的MBean对象,通过属性resource跟每一个具体的资源对象,比如StandardServer关联起来。 |
ManagedBean |
MBean的元数据信息封装类,通过调用createMBean(Object)生成具体的MBean对象(BaseModelMBean或者子类的实例)。 |
FeatureInfo |
MBean所有元数据的父类。 |
AttributeInfo |
MBean的属性元数据,提供产生MBeanAttributeInfo对象的方法。 |
OperationInfo |
MBean的操作元数据,提供产生MBeanOperationInfo的方法。 |
2.4 JMX的使用
Tomcat在启动的时候,会注册相当多的MBean到MBeanServer中,怎么管理MBeanServer中注册的MBean,这里提供一个简单的方法,使用JDK的小工具jconsole。
使用jconsole查看MBean可以按如下步骤操作:
1、指定特别的JVM参数,启动tomcat服务器
-Dcom.sun.management.jmxremote.port=1090 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false |
2、启动jconsole,JMX的服务器ip和port,进入管理控制台,示例图如下:
连接效果图
连接成功的效果图
3 总结
在对JMX有个基本的认识后,学习JMX,以及了解JMX在tomcat或者其他程序中的应用都不会太难。JMX给我们的一个最大的启示就是,后面的程序设计中,可以考虑使用JMX管理我们的程序。
转载于:https://my.oschina.net/psuyun/blog/291798