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服务提供了对这些核心类的管理功能。有图为证:

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类模型

tomcat学习之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,进入管理控制台,示例图如下:

tomcat学习之JMX应用

连接效果图

tomcat学习之JMX应用

 连接成功的效果图

3 总结

在对JMX有个基本的认识后,学习JMX,以及了解JMX在tomcat或者其他程序中的应用都不会太难。JMX给我们的一个最大的启示就是,后面的程序设计中,可以考虑使用JMX管理我们的程序

转载于:https://my.oschina.net/psuyun/blog/291798