Spring+JMX(Java Management Extensions)
来源:互联网 发布:奥数中最优化方法 编辑:程序博客网 时间:2024/04/30 08:21
基于J2SE 6来学习JMX。
目的:
JMX已经成功Java 2平台的一部分,它的目标是动态管理和监控你所感兴趣的资源,例如应用程序、设备、服务、JVM等,JMX能够支持通过本地和远程访问的方式,来实现对相关资源的管理和监控。
好处:
第一、基于JMX来管理现有的Java应用程序,可以非常容易的基于Java技术实现,而无需更大的投入;
第二、JMX定义了一种规范和一组标准API,业界已经将JMX技术纳入到自己的产品中来,例如JBoss、Weblogic等;
第三、JMX具有一套标准的架构,使得在管理方面具备动态性、灵活性、可扩展性和稳定性;
第四、JMX可以非常容易地与其他管理方案进行整合,如通过浏览器来访问代理服务器(MBean Server)。
JMX技术框架可以分为三层:设备层、代理层、远程管理层,下面分别介绍:
设备层:
这一层定义了需要管理的资源,如应用程序、设备、服务、网络,将这些资源以Java对象的形式,以MBean的方式暴露管理接口,例如标准MBean,通过定义名称含有MBean后缀的管理接口,在实现这些接口时与待管理的资源相关联,之后将这些Java对象注册到代理服务器(MBean Server)来实现远程管理和监控。
需要注意的是,对于标准MBean,如果MBean管理接口定义为xxxMBean,则实现一定为xxx,否则就无法通过MBean Server查找到对应的资源。
代理层:
代理层为待管理对象(如实现标准MBean管理接口的Java对象)提供了一个容器,其中只有满足要求并注册到容器中对象才能实现JMX管理。代理层最主要的组件就是MBean Server,它在我们的应用系统中充当一个管理功能的代理。
JavaSE 6平台中,可以通过调用ManagementFactory.getPlatformMBeanServer()来获取到一个MBean Server,然后向其中注册实现好的MBean资源,就能够通过JMX进行管理。查找本地的MBean Server(如果没有找到,会自动创建一个),有关如何查找以及可能需要创建,可以通过ManagementFactory.getPlatformMBeanServer()的代码来实现跟踪。在启动参数中,需要设置-Dcom.sun.management.jmxremote选项,表示可以通过远程进行管理。
远程管理层:
我们要管理应用系统的某些资源,是通过代理层来间接实现管理,那么在与代理层之间交互最为直接,所以远程远程管理层定义了我们通过什么方式来与MBean Server进行交互,如基于何种协议、怎样建立连接才能通过远程手段在MBean Server的JVM之外进行访问,从而实现管理和监控,例如基于JMXMP、RMI等。
所以,远程管理层最重要的两个组件就是协议适配器和连接器。Sun公司实现了一个基于JMXMP协议的工具JConsole,可以通过JConsole来方便地进行调试。启动JConsole后,可以通过本地进程或远程进程来进行远程管理。
创建一个基于RMI协议的连接器,示例如下:
String serviceURL = "service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi";
JMXServiceURL url = new JMXServiceURL(serviceURL);
JMXConnectorServer connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbeanServer);
Spring与JMX集成,实现方式灵活而且简单,主要体现在:
1、可以自动探测实现MBean接口的MBean对象,而且可以将一个普通的Spring Bean注册为MBean;
2、定制管理MBean的接口,根据需要暴露特定管理MBean的操作;
3、使用注解定义MBean管理接口;
4、可以实现对本地和远程MBean的代理。
标准MBean管理
对于实现标准MBean接口MBean资源,在Spring中可以设置不同的探测模式,主要是通过MBeanExporter来实现。例如,定义MBean管理接口:
- package org.shirdrn.spring.jmx.autodetect;
- public interface MyObjectMBean {
- public long getId();
- public void setId(long id);
- public String getName();
- public void setName(String name);
- public String show();
- }
对应的MBean实现,如下所示:
- package org.shirdrn.spring.jmx.autodetect;
- import org.apache.log4j.Logger;
- public class MyObject implements MyObjectMBean {
- private static final Logger LOG = Logger.getLogger(MyObject.class);
- private long id;
- private String name;
- public MyObject() {
- super();
- }
- public MyObject(long id, String name) {
- super();
- this.id = id;
- this.name = name;
- }
- public long getId() {
- return id;
- }
- public void setId(long id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String show() {
- StringBuffer sb = new StringBuffer().append("id=").append(id).append(
- ", name=").append(name);
- LOG.info("show()=" + sb.toString());
- return sb.toString();
- }
- }
上面是一个标准MBean的实现,可以使用JavaSE 6平台的JMX服务来管理,但是在Spring集成的环境下,也可以重用这些MBean实现,例如下面是一个典型的配置:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans
- xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
- <bean id="mbServer" class="org.springframework.jmx.export.MBeanExporter">
- <property name="autodetectModeName">
- <value>AUTODETECT_ALL</value>
- </property>
- </bean>
- <bean name="mydomain:myobj=MyObjectMBean" class="org.shirdrn.spring.jmx.autodetect.MyObject">
- <property name="id">
- <value>90000000001</value>
- </property>
- <property name="name">
- <value>shirdrn</value>
- </property>
- </bean>
- </beans>
上面配置中,MBeanExporter会查找本地MBean Server,指定的探测模式autodetectModeName为AUTODETECT_ALL,这也是MBeanExporter的默认值(这个属性完全可以省略,不用配置),无需手动向MBean Server进行注册,便能管理配置的MBean对象“mydomain:myobj=MyObjectMBean”。
对于探测模式autodetectModeName属性,Spring提供了4个取值:
AUTODETECT_NONE 不启用自动探测,需要手动向MBean Server进行注册,即通过MBeanExporter的beans属性进入注册;
AUTODETECT_MBEAN 在当前IOC容器中进行查找MBean组件;
AUTODETECT_ASSEMBLER 设置根据MBeanInfoAssembler的策略进行探测;
AUTODETECT_ALL 自动探测,是AUTODETECT_MBEAN和AUTODETECT_ASSEMBLER的并集。
另外,Spring的MBeanExporter也提供了autodetect属性,取值为true和false,指定对MBean组件的探测行为。
普通Spring Bean管理
对于一个普通的Spring Bean,也可以作为MBean来进行管理,Spring可以很好地支持。如下面一个普通的Java类:
- package org.shirdrn.spring.jmx;
- import org.apache.log4j.Logger;
- public class MyJavaObject {
- private static final Logger LOG = Logger.getLogger(MyJavaObject.class);
- private long id;
- private String name;
- public MyJavaObject() {
- super();
- }
- public MyJavaObject(long id, String name) {
- super();
- this.id = id;
- this.name = name;
- }
- public long getId() {
- return id;
- }
- public void setId(long id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String show() {
- StringBuffer sb = new StringBuffer().append("id=").append(id).append(
- ", name=").append(name);
- LOG.info("show()=" + sb.toString());
- return sb.toString();
- }
- }
它并没有实现MBean管理接口,可以通过MBeanExporter的beans属性进行注册,配置如下所示:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans
- xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
- <bean id="mbServer" class="org.springframework.jmx.export.MBeanExporter">
- <property name="beans">
- <map>
- <entry key="mydomain:myjavaobj=MyJavaObject" value-ref="myobj"/>
- </map>
- </property>
- </bean>
- <bean name="myobj" class="org.shirdrn.spring.jmx.MyJavaObject">
- <property name="id">
- <value>90000000001</value>
- </property>
- <property name="name">
- <value>shirdrn</value>
- </property>
- </bean>
- </beans>
因为org.shirdrn.spring.jmx.MyJavaObject没有对应的MBean接口,所以默认情况下,该类中public的成员都会暴露出来,通过MBean Server可以管理。实际上,系统中MBean的某些属性或方法可能不需要暴露给外部进行管理,为了克服这种缺点,Spring提供了基于方法列表和接口定制的功能,可以将你所感兴趣的属性或方法暴露给外部管理。
基于方法列表和接口定制的MBean管理
对于上述普通的Java类MyJavaObject,可以通过定制接口和方法列表,来暴露MBean属性或方法。例如,一个方法列表,可以在进行配置的时候指定,如下所示:
- <bean id="assembler" class="org.springframework.jmx.export.assembler.MethodNameBasedMBeanInfoAssembler">
- <property name="managedMethods" value="setId,setName,show" />
- </bean>
上面通过org.springframework.jmx.export.assembler.MethodNameBasedMBeanInfoAssembler来进行方法列表的设置。而对于接口,可以定义一个接口,如下所示:
- package org.shirdrn.spring.jmx.selected.interfaces;
- public interface SelectedMethodsInterface {
- public long setId(long id);
- public void setName(String name);
- public void show();
- }
Spring配置,如下所示:
- <bean id="assembler" class="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler">
- <property name="managedInterfaces">
- <list>
- <value>org.shirdrn.spring.jmx.selected.interfaces.SelectedMethodsInterface</value>
- </list>
- </property>
- </bean>
上面通过org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler,可以设置一个接口列表,来管理MBean暴露的接口。
对于上面两种方式,都得到一个assembler实例,需要将其注入到org.springframework.jmx.export.MBeanExporter中,如下所示:
- <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
- <property name="beans">
- <map>
- <entry key="mydomain:javaObj=MyJavaObject" value-ref="javaObject" />
- </map>
- </property>
- <property name="assembler" ref="assembler" />
- </bean>
基于注解的MBean管理
对于一个普通的Java类,作为MBean需要被管理,可以通过注解指定要暴露的属性和方法,示例如下:
- package org.shirdrn.spring.jmx.annotation;
- import org.apache.log4j.Logger;
- import org.springframework.jmx.export.annotation.ManagedAttribute;
- import org.springframework.jmx.export.annotation.ManagedOperation;
- import org.springframework.jmx.export.annotation.ManagedResource;
- @ManagedResource(objectName = "annojmx:myjao=AnnotationObject", description = "MyJavaAnnotationObject")
- public class MyJavaAnnotationObject {
- private static final Logger LOG = Logger.getLogger(MyJavaAnnotationObject.class);
- private long id;
- private String name;
- public MyJavaAnnotationObject() {
- super();
- }
- public MyJavaAnnotationObject(long id, String name) {
- super();
- this.id = id;
- this.name = name;
- }
- @ManagedAttribute
- public long getId() {
- return id;
- }
- public void setId(long id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- @ManagedAttribute
- public void setName(String name) {
- this.name = name;
- }
- @ManagedOperation
- public String show() {
- StringBuffer sb = new StringBuffer().append("id=").append(id).append(
- ", name=").append(name);
- LOG.info("show()=" + sb.toString());
- return sb.toString();
- }
- }
上面@ManagedResource表示指定该类的实例作为MBean注册到MBean Server中,然后可以通过对属性和方法分别使用@ManagedAttribute和@ManagedOperation来指定暴露的属性和方法。有关这些注解的详细内容,可以查阅相关文档。
下面是一个基本的配置内容:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
- <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
- <property name="assembler" ref="assembler" />
- <property name="namingStrategy" ref="namingStrategy" />
- </bean>
- <bean id="assembler"
- class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
- <property name="attributeSource" ref="jmxas" />
- </bean>
- <bean id="namingStrategy"
- class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
- <property name="attributeSource" ref="jmxas" />
- </bean>
- <bean id="jmxas" class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource" />
- <bean id="javaObj"
- class="org.shirdrn.spring.jmx.annotation.MyJavaAnnotationObject">
- <property name="id" value="201122121200" />
- <property name="name" value="shirdrn" />
- </bean>
- </beans>
上面使用了Spring的MBeanExporter,可以看到,Spring配置内容相对较多。
Spring还提供两种简化配置的方式,
一种是,提供了org.springframework.jmx.export.annotation.AnnotationMBeanExporter,可以将上述配置大大简化,等价的配置如下所示:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
- <bean class="org.springframework.jmx.export.annotation.AnnotationMBeanExporter"/>
- <bean name="myAnnoObject"
- class="org.shirdrn.spring.jmx.annotation.MyJavaAnnotationObject">
- <property name="id" value="201122121200" />
- <property name="name" value="shirdrn" />
- </bean>
- </beans>
另一种是,提供了<context:mbean-export />标签,更加简洁,等价的配置如下所示:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-2.5.xsd">
- <context:mbean-export registration="failOnExisting" />
- <bean name="myAnnoObject"
- class="org.shirdrn.spring.jmx.annotation.MyJavaAnnotationObject">
- <property name="id" value="201122121200" />
- <property name="name" value="shirdrn" />
- </bean>
- </beans>
通过远程代理访问MBean
根据JavaSE 6平台的JMX技术架构定义,分为设备层、代理层、远程管理层这三层,我们通过可以使用Spring提供的org.springframework.jmx.access.MBeanProxyFactoryBean实现,定义代理,来访问MBean Server管理MBean资源。实际上,Spring提供的这个代理功能位于JMX架构的远程管理层,那么在代理层和远程管理层之间,要定义连接器,才能通过远程管理层访问到代理层的MBean Server组件。下面通过实例来实现:
首先,定义个普通的Java类,作为待管理的MBean,如下所示:
- package org.shirdrn.spring.jmx.rmi;
- import org.apache.log4j.Logger;
- public class MyJavaObject {
- private static final Logger LOG = Logger.getLogger(MyJavaObject.class);
- private long id;
- private String name;
- public MyJavaObject() {
- super();
- }
- public MyJavaObject(long id, String name) {
- super();
- this.id = id;
- this.name = name;
- }
- public long getId() {
- return id;
- }
- public void setId(long id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String show() {
- StringBuffer sb = new StringBuffer().append("id=").append(id).append(
- ", name=").append(name);
- LOG.info("show()=" + sb.toString());
- return sb.toString();
- }
- }
其次,定义了一个Java接口,来按需暴露操作MBean资源的方法:
- package org.shirdrn.spring.jmx.rmi;
- public interface MyManagedInterfaces {
- public long setId(long id);
- public String getName();
- public String show();
- }
再次,看一下我们模拟代理层Spring配置server.xml内容:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
- <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
- <property name="beans">
- <map>
- <entry key="mydomain:myjavaobj=MyJavaObject" value-ref="myJavaObj" />
- </map>
- </property>
- <property name="assembler" ref="assembler" />
- </bean>
- <bean id="assembler"
- class="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler">
- <property name="managedInterfaces">
- <list>
- <value>org.shirdrn.spring.jmx.rmi.MyManagedInterfaces</value>
- </list>
- </property>
- </bean>
- <bean name="myJavaObj" class="org.shirdrn.spring.jmx.rmi.MyJavaObject">
- <property name="id" value="88000000001" />
- <property name="name" value="shirdrn" />
- </bean>
- <bean id="server" class="org.springframework.jmx.support.ConnectorServerFactoryBean" depends-on="registry">
- <property name="objectName">
- <value>connector:name=rmi</value>
- </property>
- <property name="serviceUrl">
- <value>service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jmxrmi</value>
- </property>
- </bean>
- <bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean">
- <property name="port">
- <value>1099</value>
- </property>
- </bean>
- </beans>
上半部分配置已经非常熟悉,就是将MBean注册到MBean Server中。下半部分是有关连接器的配置,它是基于RMI协议来进行适配,通过Spring提供的org.springframework.jmx.support.ConnectorServerFactoryBean来实现器,这样,远程管理层可以连接到启动的连接服务器,来访问MBean资源。
然后,我们启动MBean Server及其连接服务器,代码如下所示:
- package org.shirdrn.spring.jmx.rmi;
- import org.apache.log4j.Logger;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class Server {
- private static final Logger LOG = Logger.getLogger(Server.class);
- public static void main(String[] args) throws Exception {
- new ClassPathXmlApplicationContext("org/shirdrn/spring/jmx/rmi/server.xml");
- LOG.info("Server started.");
- Object lock = new Object();
- synchronized (lock) {
- lock.wait();
- }
- }
- }
启动后,我们定义的MBean已经注册到本地MBean Server中,同时启动了连接器,监听1099端口。
接着,我们定义远程访问层的Spring配置proxy.xml内容,如下所示:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
- <bean id="proxy" class="org.springframework.jmx.access.MBeanProxyFactoryBean">
- <property name="connectOnStartup" value="true" />
- <property name="objectName" value="mydomain:myjavaobj=MyJavaObject" />
- <property name="proxyInterface">
- <value>org.shirdrn.spring.jmx.rmi.MyManagedInterfaces</value>
- </property>
- <property name="serviceUrl">
- <value>service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jmxrmi</value>
- </property>
- </bean>
- </beans>
最后,启动代理,访问MBean资源,代码如下所示:
- package org.shirdrn.spring.jmx.rmi;
- import org.apache.log4j.Logger;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class Proxy {
- private static final Logger LOG = Logger.getLogger(Proxy.class);
- public static void main(String[] args) throws Exception {
- ApplicationContext ctx = new ClassPathXmlApplicationContext(
- "org/shirdrn/spring/jmx/rmi/proxy.xml");
- LOG.info("Proxy server started.");
- MyManagedInterfaces proxy = (MyManagedInterfaces) ctx.getBean("proxy");
- String message = proxy.show();
- LOG.info("proxy.show() = " + message);
- Object lock = new Object();
- synchronized (lock) {
- lock.wait();
- }
- }
- }
这里,只能访问通过org.shirdrn.spring.jmx.rmi.MyManagedInterfaces接口定义的方法来操作注册到MBean Server中的MBean资源。
- Spring+JMX(Java Management Extensions)
- Java Management Extensions (JMX)
- Java Management Extensions (JMX)
- JMX(Java Management Extensions,即Java管理扩展)
- JMX(Java Management Extensions,即Java管理扩展)
- JSR 3: Java Management Extensions (JMX) Specification
- java Management Extensions (JMX): End of Trail
- Getting Started with Java Management Extensions (JMX): Developing Management and Monitoring Solutions
- Getting Started with Java Management Extensions (JMX): Developing Management and Monitoring Solution
- JMX是Java Management Extensions 的简写,即Java管理扩展
- Java Management extentsions(jmx)与tomcat
- JMX(Java Management Extension)学习
- Getting Started with Java Management Extensions (JMX): Developing Management and Monitoring Solutions 2005/01/09 01:44:07
- java jmx整合Spring配置
- JMX Management and Monitoring
- JMX : Remote Management
- [Java]JMX
- Java JMX
- 九种改变未来世界的革命性技术
- ZOJ 1577 GCD & LCM
- css3选择类别
- PIN码查询网站
- 把excel文档中的内容读取到dataset中
- Spring+JMX(Java Management Extensions)
- 多线程的使用
- 顺时针打印矩阵
- oracle服务启动批处理 提高开机及运行效率
- Lua 与 C混合编程 .
- 【Linux Rsync3.0 实用版安装】
- OpenGL中所有的变换,都是在变换坐标系。
- Spring配置定时器的xml文件
- TCP