JMX应该说是关于网络应用管理的的框架,如果你开发了一个比较复杂的系统,无疑你要提供这个系统的自身管理 系统,JMX更多应用是体现在Server上,如果你要使用java开发一个自己Server或复杂的应用系统,那么推荐你基于JMX架构来开发, JBoss 3.0 weblogic等就是基于JMX开发的符合J2EE规范的服务器软件。
了解JMX可以使你深入了解J2EE服务器, 为什么我们平时说 "EJB"是个比较"Weight"的方案选择,其中一个原因是J2EE服务器软件本身 也是你的系统中一部分,它作为你系统的容器,对你的系统有至关重要的作用,如果无法直接介入 管理或“调教”它,那么无疑你的系统本身存在着隐含的危险, 现在,通过JMX,你现在可以深入到你J2EE容器内部的管理了。 (好像国内出现了第一个自己J2ee服务器,不知道那是不是基于JMX开发的?)
J2EE并不能概括所有的应用领域,比如对速度和性能要求极高的游戏或股票行情等系统就需要自己直接来开发Server, 如果是能够基于JMX开发,那么可以说就大大提高编写管理程序的效率,可以将你的模块变成JMX的MBean,可以通过Agent在程序内部或者通过 WEB管理页面对你的MBean模块进行初始化 重启 以及参数设置。
JMX的好处还有:可以方便整合连接现有的Java技术,如JNDI JDBC JTS及其它。特别是能够使用Jini的查询 发现机制以及协议,我们知道,Jini提供了一种服务的查询和发现机制,这些services都可以通过JMX 来实现管理。
现在我们开始JMX的了解:
1.到java.sun.com首页的JMX页面,下载JMX的规定说明和Samples程序。
2.按照JMX的说明进行一次Tutorial,了解如何加入 删除 配置一个MBean,Tutorial中是以SimpleMBean为例,那么我们能否建立一个自己的MBean?
我们来做一个Hello 的MBean,这里有一个小关键点,你的class取名有个规则, 需要以MBean为结尾,如这里我们取名为HelloMbean:
public interface HelloMBean {
// management attributes
public String getName();
public void setName(String name);
// management operations
public void print();
}
在这个Class里,有一个隐含attributes: name, 提供了set和get的方法,同时有一个操作方法print():
再定义一个concrete类:
public class Hello implements HelloMBean {
private String name = "";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void print() {
System.out.println("Hello, " + name + "!!" );
}
}
这样一个简单的MBean就做好了,我们可以通过admin界面加入这个Hello,
再按 Tutorial启动BaseAgent,在Agent Administration中参考Simple填入:
Domain: Standard_Hello_MBeans
Keys : name=Hello,number=1
Java Class: Hello
将出现Create Successful信息。进入MBean View 给Name赋值,点按Apply ,然后再按print,这是你的Hello中的方法,在控制台你会看到输出。
是不是很惊奇Hello中的 attributes 和operations能被动态的访问和控制? 已经隐约感到JMX的架构原理了吧?
下面再深入明确一些概念:
上面HelloMBean资源是通过admin这样的HTTP WEB界面管理,这种管理资源方式是属于JMX的Distributed服务层, JMX 通过Distributed层能够部署和管理MBean资源。就象上面的例子,是通过HtmlAdaptor提供的HTTP WEB界面来方面的维护管理HelloMBean.
那么我们能否在程序中自动管理和部署我的MBean?当然可以,这是通过Agent层来完成,现在我们已经有了这个层次,MBean所在的资源层,
最外面的Distributed服务层,Distributed服务层是通过Agent层来访问MBean资源的,看看下面来自Sun公司JMX规定的架构图:
从图中看出,Agent Level(Agent层)包括MBean Server和Agent Services,那么我们来做一个上面例子HelloMBean的Agent:
// CREATE the MBeanServer
//
System.out.println("/n/tCREATE the MBeanServer.");
MBeanServer server = MBeanServerFactory.createMBeanServer();
// CREATE Registe HelloMBean
//
System.out.println("/n/tCREATE, REGISTER a new Hello Standard_MBean:");
HelloMBean helloMBean = new Hello();
ObjectName hello_name = null;
try {
hello_name = new ObjectName("Standard_Hello_MBeans:name=Hello,number=1");
System.out.println("/tOBJECT NAME = " + hello_name);
//将HelloMBean注册到MBeanServer中去
server.registerMBean(helloMBean, hello_name);
}
catch (Exception e) {
e.printStackTrace();
return;
}
向MBeanServer注册后,以后JMX就知道有了这个HelloMBean资源。
管理一个agent的MBean资源或使用它提供的服务必须通过一个protocol adaptor 或者connector,adaptor 或者connector属于Distributed layer level(Distributed服务层),我们上面例子中通过HTTP WEB界面管理HelloMBean就是浏览器通过HtmlAdaptor这个adaptor来实现的。
通过本篇文章,你应该大体了解了JMX的架构和一些原理和应用,再深入可以研究SUN的JMX Specification.
我们前章举例的HelloMBean是StandardMBean,这是JMX中的MBean的一种,还有一种 叫DynamicMBean,这是JMX在运行期间能够控制它, 无论哪种MBean,他们的区别只是在他们如何被开发,而不是在它们如何被管理, JMX的Agent提供了处理这两种类型的抽象的处理方法,也就是说,一旦这两种MBean 被JMX的Agent管理,这两种MBean在外界看来没什么区别。
一个标准的standard MBean的Java class是通过它的attributes和operations 被外界管理的,Attributes是内部的一些属性变量,它通过getter 和 setter方法被外界管理 在HelloMBean中,它们是
public String getName();
public void setName(String name);
Operations 是这个class中其它愿意被管理的方法,在HellMBean中是
public void print()
所有这些方法需要在MBean接口中定义,然后通过introspection(内省机制) 显露给一个agent, 上述方法是制造一个可管理资源的最直接办法。
DynamicMBean
而在开发一个DynamicMBean时,attributes 和operations是通过方法调用 间接的显露给agent的。DynamicMBean 适合管理那些已经存在的资源和代码。
需要被JMX的Agent认为是 DynamicMBean,这个Java class或它的子类必须继承 一个DynamicMBean的标准接口。
getMBeanInfo:
DynamicMBean不象StandardMBean那样通过introspection(内省机制)向外界 显露他的attributes和operations,而是通过在运行时,返回这个方法的值来向 外界显露他的attribute names 和 types 以及 operation signatures 。 这个方法返回的是MBeanInfo实例.
getAttribute 和 getAttributes
这是获得相应的attribute name属性名称或属性名称表的值,这个类似StandardMBean的 getter方法,不同点是由调用者提供所需要的属性名,如 public Object getAttribute(String attribute_name) 不同于StandardMBean的getXXXX(Attribute_name)。
setAttribute 和 setAttributes
这个类似StandardMBean的setter方法, 设置相应属性的name-value对。
invoke
invoke方法是让外界来调用DynamicMBean的操作,这儿调用者必须提供 操作名称 作为参数传递的object和这些参数的类型,具体如: public Object invoke(String operationName, Object params[], String signature[])
当DynamicMBean在JMX agent中注册后,DynamicMBean其实就和StandardMBean 是一样的,外界将首先通过getMBeanInfo获得一个管理接口,其中包含attributes 和 operations 名称,然后才将调用DynamicMBean的getters, setters 和invoke方法,
MBean原始类
从上面可以看到,MBean有一些自己规定的诸如MBeanInfo这样的原始类,一共有如下几种:
MBeanInfo - 罗列出所有的属性attribute, 操作operations, 构造器constructor 和 notification
MBeanFeatureInfo - 下面类的子类
MBeanAttributeInfo - 描述一个属性attribute
MBeanConstructorInfo - 描述一个构造器constructor MBean构造器是由签名单独地定义,这个签名是参数的次序和类型.
MBeanOperationInfo - 描述一个操作operation
MBeanParameterInfo - 描述一个操作或构造器的参数
MBeanNotificationInfo - 描述一个notification
通过与使用这些原始类,将你的具体资源就可以动态的嵌入DynamicMBean了.
我们看看下面HelloDynamic程序是如何使用这些原始类构成一个DynamicMBean的:
我们还以上章中的Hello为例,Hello是以Standard MBean来实现了对name的赋值和打印功能.那么通过使用Dynamic MBean我们也来实现这个功能,在这个资源中,有一个属性name以及操作方法print.下面示例展示如何将这个属性和这个操作方法使用DynamicMBean的原始类来实现:
// /** public class HelloDynamic //这是我们的属性名称 private MBeanInfo mBeanInfo = null; private MBeanAttributeInfo[] attributes = new MBeanAttributeInfo[1]; public HelloDynamic() { //设定一个属性 //设定构造函数 //operate method 我们的操作方法是print mBeanInfo = new MBeanInfo(className, description, attributes, } public Object getAttribute(String attribute_name) { public AttributeList getAttributes(String[] attributeNames) { // if attributeNames is empty, return an empty result list for (int i = 0; i < attributeNames.length; i++) { } public void setAttribute(Attribute attribute) {
try { } } public AttributeList setAttributes(AttributeList attributes) { // if attributeNames is empty, nothing more to do // for each attribute, try to set it and add to the result list if successfull }
// Check for a recognized operation name and call the corresponding operation } public MBeanInfo getMBeanInfo() { }
|
编制一个HelloAgent来调用这个HelloDynamic:
// java imports // import java.util.*; import java.io.*; import java.net.*; // RI imports import com.sun.jdmk.comm.HtmlAdaptorServer; import javax.management.Attribute;
public static void main(String[] args) { // CREATE the MBeanServer String domain = server.getDefaultDomain(); server.createMBean(mbeanName,object_name); Attribute stateAttribute = new Attribute("Name","I am big one"); String name = (String) server.getAttribute(object_name,"Name"); server.invoke(object_name,"print",null,null); } |
直接运行HelloAgent就可以在屏幕输出上得到
"Hello ,I am big one, this is from HelloDynamic"