一、什么是JMX
JMX(Java Management Extensions)是一个为应用程序植入管理功能的框架。JMX是一套标准的代理和服务,实际上,用户可以在任何Java应用程序中使用这些代理和服务实现管理。
JMX的前身是JMAPI。
JMX致力于解决分布式系统管理的问题,因此,能够适合于各种不同的环境是非常重要的。为了能够利用功能强大的Java计算环境解决这一的问题,Sun公司扩充了Java基础类库,开发了专用的管理类库。
JMX是一种应用编程接口,可扩充对象和方法的集合体,可以用于跨越一系列不同的异构操作系统平台、系统体系结构和网络传输协议,灵活的开发无缝集成的系统、网络和服务管理应用它提供了用户界面指导、Java类和开发集成系统、网络及网络管理应用的规范。
管理对象是JMX应用程序的核心。JMX结构包括:支持Java的Web浏览器用户接口,管理运行模块ARM(Admin Runtime Module)和应用。这三个部件之间通过RMI(Remote Method Invocation)进行通信。这里需要说明的是,RMI是使得一个Java虚拟机(JVM)上运行的程序可以调用远程服务器上另一个JVM总的对象。
用户接口用来发布管理操作,这些操作可以间接的通过浏览器或通过单独的应用程序来激发。管理运行模块用来给应用提供实例化的管理对象。它包括Agent对象接口,通知接口和被管数据接口。应用指的是那些被管设备单元。
JMX是一个完整的网络管理应用程序开发环境,它同时提供了:厂商需要收集的完整的特性清单,可生成资源清单表格,图形化的用户接口;访问SNMP的网络API;主机间远程过程调用;数据库访问方法。
JMX这一轻型的管理基础结构,价值在于对被管理资源的服务实现了抽象,提供了低层的基本类集合,开发人员在保证大多数的公共管理类的完整性和一致性的前提下,进行扩展以满足特定网络管理应用的需要。
JMX注重于构造管理工具的软件框架,并尽量采用已成熟的技术。
JMX体系被分成三个层次
。表现层
。代理层
。分布式服务层
JMX框架
基本概念
JMX涉及到以下基本概念。
MBean:暴露用来操作和访问被管资源的管理接口的java对象
MBean Server:管理一组MBean的java类,类似一个查找Mbean的注册表,暴露出所有注册过的Mbean的管理接口,以及提供查找Mbean和通知监听器的方法。
MBean Agent:提供管理MBean的服务的一个Java进程,是MBean Server的容器。提供这些服务:建立MBean关系、动态加载类、简单监控服务、定时器等。
MBean Agent可以指望有一组协议适配器(Adaptor)或连接器(Connector),使远程客户和不同客户使用agent。协议适配器和连接器通常也是MBean。
协议适配器(Adaptor)或连接器(Connector):在MBean Agent之中的一些对象,用来将Agent暴露给管理应用和协议。
Adaptor和Connector区别: Adaptor通常要监听进来的信息,这些信息是在某个协议如HTTP或SNMP中构造的。在这个意义上,协议适配器在任何时间都存在于Agent中并只有一个组件。Connector由两个组件组成,一个在Agent端,一个在客户端。客户使用客户端连接器组件和服务器端连接器组件联系并和Agent通讯。
下图为RMI Connector的两个组件通讯情况:
管理应用:连接任意数量MBean Agent的用户应用。
JMX Agent可以通过定制开发适配器或连接器,和一个非jmx管理应用进行交互。
通知(Notification):由MBean或MBean Server发出的,封装了事件、警告和通用信息的Java对象。MBean或Java对象可以注册为监听者来接收通知。JMX的通知模型类似于Java的事件模型。
设备(Instrumentation):使用MBean或一组MBean暴露管理资源的进程。
管理应用(Manager Appliction):使用MBean的管理应用程序。
JMX的三层架构
分布层(Distributed Layer):包含了能使管理应用和JMX Agent通讯的组件
代理层(Agent Layer):包含了Agents和MBean Server
装备层(Instrument Layer):包含了可以代表可管理资源的MBean
1、分布层:jmx的最外层,负责向外界提供jmx的agent。
有两种类型的分布式交互(interaction),即建立一个连接(Connectin):
1) 通过Adaptor获取的交互方式:通过不同的协议如HTTP,SNMP提供到MBean的可见性(visibility)。
2) JMX Agent有Connector组件,将agent的API暴露给其他分布式技术,如RMI。
当远程客户端通过Adaptor或Connector和Agent建立连接后,就可以和agent中注册的MBean进行交互。接着就进入了代理层。
2、代理层:
代理层的主要组件是MBean Server,作为MBean的登记处,是代理层的核心。
代理层提供4个代理服务来更方便地管理MBean:定时器、监控、动态MBean 加载、关系服务。
代理层提供从管理应用到被管理资源的访问。
Jmx代理可以运行在管理资源的机器上的JVM中,也可以位于在远程。agent不需要知道它暴露出的资源的信息,或使用MBean的管理应用。
agent担当了一个服务的角色,用来处理MBean,允许通过暴露出的Connector或Adaptor的一系列协议来操作MBean。
3、装备层:离被管理资源最近的一层。由注册在Agent上的MBean组成。
每个MBean暴露一个底层资源的一块配置和功能,并通过一个Java对象来提供。如果底层资源不使用Java, 则MBean充当一个翻译器。
MBean是一个轻量级的类,知道如何使用、获取操作其资源,并向agent和用户提供访问途径和功能。
使用JMX作为应用程序架构:
jmx 代理层用来构件应用很理想。MBean Server可以用作应用组件,如数据层、日志组件、事务管理器的骨架。
使用这种架构,开发人员可以很容易地从服务器中增加、改变、删除应用服务。
二、表现层
表现层定义的是JMX可管理资源所在的层。
这些已管理的资源可以编写或封装为MBean。
MBean分为四种类型:
标准、动态、开放、模型
三、代理层
定义的是MBean向应用程序施加管理的层。包括MBean服务器和代理服务的定义。还至少包括一个协议适配器或连接器。
代理的组成:
。一个MBean服务器
。要管理的MBean
。作为MBean实现的代理服务
。至少一个协议适配器
3.1 MBean
在JMX中,最小的可管理单元是MBean。
MBean不是一个真正的接口和类,而是必须准循的设计模式以确保资源是一个兼容的MBean。
MBean的激活方法:
invoke()方法是管理应用程序用于激活MBean的方法的手段。
invoke()方法有三个参数,分别是方法的名称、表示属性的对象数组和描述方法签名的一个字符串数组。它与使用Java Reflection Api 激活方法的方式类似。
Notification(通知)模型:
MBean的通知模型类似与Java事件的监听器模型。
MBean或管理应用程序可以作为MBean事件的监听器注册。
通知支持由两个基本的概念组成,即广播器和监听器。
3.2 MBean服务器
MBean服务器用于注册可管理的MBean。
所有对MBean的请求或查询都是通过MBean服务器实施的。
3.3 代理服务
代理服务是一些特殊的函数,代理把这些服务提供给MBean,这些代理服务独立于任何MBean。
一个代理可以提供四种主要的服务:
。动态装载:允许代理通过下载这个Bean的类动态实例化MBean,这与装载applet的方式类似。
JMX使用m-let这个标记指定期望动态装载的MBean的位置。
。监控:允许代理通知有关的监听器监控一个MBean的属性值的变化
JMX允许使用三种基本类型的监控程序
(1)CounterMonitor:该程序可以观察类型方面的变化,比如Byte类似或Integer类型
(2)GaugeMonitor:该程序可以观察类型方面的变化,比如Byte类似或Integer类型,还可以在到达上下阀值时进行报告。
(3)StringMonitor:该程序可以观察java.lang.String类型的变化。
。计时器:允许预设的时间间隔发送通知,可以作为一个调度程序
。关系:允许创建和维护MBean之间的关系
四、分布式服务层
包含协议适配器和连接器两种类型的组件,通过它们连接到外部的应用,如RMI管理应用、基于浏览器的管理控制等
五、协议适配器和连接器
协议适配器是代理与管理客户通信的手段,每个通信的协议都可能不同。
它们都是管理客户与MBean交互的方式。
六、JMX的好处
。可减少对JAVA应用实施管理的投资
。提供了一个可伸缩的管理框架
。集成现有的管理方案:如:WBEM,SNMP,TMN
。使用现有的标准JAVA技术
。能使用未来的一些管理概念:如Jini连接技术、通用即插即用、服务定位协议(Service Location Protocol)
。只定义了一些可以访问的接口
七、 Getting Started:简单MBean
运行本文程序需要在JDK5.x环境下,并且要到java.sun.com网站上去下载Sun的JDMK5.1(Java Dynamic Management Kit 5.1),下载后解压,将lib目录下的jdmktk.jar文件加到项目的类路径上即可(如果找不到,可以向我索取 chengy@primeton.com )。
1. 定义接口4. 运行
在IE中打入http://localhost:9092/
- package jmxbook.ch2;
- public interface HelloWorldMBean {
- public void setGreeting(String greeting);
- public String getGreeting();
- public void printGreeting();
- }
2. 编写Mbean实现类
- package jmxbook.ch2;
- public class HelloWorld implements HelloWorldMBean {
- private String greeting=null;
- public HelloWorld() {
- this.greeting="I'm a standard MBean";
- }
- public HelloWorld(String greeting) {
- this.greeting=greeting;
- }
- public String getGreeting() {
- return greeting;
- }
- public void printGreeting() {
- System.out.println(greeting);
- }
- public void setGreeting(String greeting) {
- this.greeting=greeting;
- }
- }
3. 编写Agent
- package jmxbook.ch2;
- import javax.management.MBeanServer;
- import javax.management.MBeanServerFactory;
- import javax.management.ObjectName;
- import com.sun.jdmk.comm.HtmlAdaptorServer;
- public class HelloAgent {
- private MBeanServer server = null;
- public HelloAgent() {
- server = MBeanServerFactory.createMBeanServer("HelloAgent");
- HtmlAdaptorServer adapter = new HtmlAdaptorServer();
- HelloWorld hw = new HelloWorld();
- ObjectName adapterName = null;
- ObjectName mbeanName = null;
- try {
- mbeanName = new ObjectName("HelloAgent:name=helloWrold");
- server.registerMBean(hw, mbeanName);
- adapterName = new ObjectName(
- "HelloAgent:name=htmlAdaptor,port=9092");
- adapter.setPort(9092);
- server.registerMBean(adapter, adapterName);
- adapter.start();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public static void main(String args[]) {
- System.out.println("HelloAgent is running");
- HelloAgent agent = new HelloAgent();
- }
- }
说明:
1) 区分Mbean: 使用ObjcetName对象,分两部分:1) 域名 2) key-value对列表
如 HelloAgent:name=helloWorld
两个ObjectName的相等:
ObjectName objName1=new ObjectName(“HelloAgent:name=helloWorld,type=typeA”);
ObjectName objName2=new ObjectName(“HelloAgent: type=typeA,name=helloWorld”);
则objName1.equals(objName2)返回true.
2) ObjectName冲突: MBean Server注册两个相同ObjectName的MBean会抛出异常.
5.使用html客户端访问jmx agent:
1) Agent View: 显示所有注册的MBean
2) MBean View: 显示一个MBean信息
3) Admin View: 管理MBean,注册和取消注册MBean
输入key和java className, action选择Constrctors, 可以查看类的构造函数列表(需要MBean的接口命名为 名称+MBean, 如HelloWorldMBean), 输入构造函数的参数(有的话),按create可以建立新的MBean并注册到agent.
四.使用通知:
jmx可以使用通知机制,从一个MBean发送通知给另一个MBean,如下图:
使用通知的步骤如下:
1) 建立通知发送者:
两种方式:
(1) 实现javax.management.NotificationBroadcaster接口
(2) 扩展 javax.management.NotificationBroadcasterSupport类
改造HelloWorld.java
- package jmxbook.ch2.notification;
- import javax.management.Notification;
- import javax.management.NotificationBroadcasterSupport;
- public class HelloWorld extends NotificationBroadcasterSupport
- implements HelloWorldMBean {
- public HelloWorld() {
- this.greeting = "I'm a Notification Sender";
- }
- public HelloWorld(String greeting) {
- this.greeting = greeting;
- }
- public void setGreeting(String greeting) {
- this.greeting = greeting;
- Notification notification = new Notification(
- "jmxbook.ch2.helloWorld.test", this, -1, System
- .currentTimeMillis(), greeting);
- sendNotification(notification);
- }
- public String getGreeting() {
- return greeting;
- }
- public void printGreeting() {
- System.out.println(greeting);
- }
- private String greeting;
- }
2) 建立通知接收者:
接口: MyListenerMBean.java:
- package jmxbook.ch2.notification;
- import javax.management.NotificationListener;
- public interface MyListenerMBean extends NotificationListener {
- public void printInfo(String message);
- }
实现类: MyListener.java
- package jmxbook.ch2.notification;
- import javax.management.Notification;
- public class MyListener implements MyListenerMBean {
- public void printInfo(String message) {
- System.out.println(message);
- }
- public void handleNotification(Notification notification, Object handback) {
- this.printInfo("My listener recieve Nofitication: " + notification.getType() + " "
- + notification.getMessage());
- }
- }
3) 改造HelloAgent:
- package jmxbook.ch2.notification;
- import javax.management.*;
- import com.sun.jdmk.comm.HtmlAdaptorServer;
- public class HelloAgent implements NotificationListener {
- private MBeanServer mbs = null;
- public HelloAgent() {
- mbs = MBeanServerFactory.createMBeanServer("HelloAgent");
- HtmlAdaptorServer adapter = new HtmlAdaptorServer();
- HelloWorld hw = new HelloWorld();
- ObjectName adapterName = null;
- ObjectName helloWorldName = null;
- try {
- adapterName = new ObjectName(
- "HelloAgent:name=htmladapter,port=9092");
- mbs.registerMBean(adapter, adapterName);
- adapter.setPort(9092);
- adapter.start();
- MyListener listener = new MyListener();
- mbs.registerMBean(listener, new ObjectName(
- "HelloAgent:name=myListener"));
- helloWorldName = new ObjectName(
- "HelloAgent:name=helloWorld,notification=yes");
- mbs.registerMBean(hw, helloWorldName);
- hw.addNotificationListener(this, null, null);
- hw.addNotificationListener(listener, null, null);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }// constructor
- public void handleNotification(Notification notif, Object handback) {
- System.out.println("My listener recieve Nofitication: "
- + notif.getType() + " " + notif.getMessage());
- }
- public static void main(String args[]) {
- HelloAgent agent = new HelloAgent();
- System.out.println("HelloAgent is running");
- }
- }
4) 运行:
调用HelloWorld的greeting(“Can I help you?”)方法, 控制台显示:
Agent recieve Nofitication: jmxbook.ch2.helloWorld.test Can I help you?
My listener recieve Nofitication: jmxbook.ch2.helloWorld.test Can I help you?
五.使用RMI Connector:
1) 改造Agent:
- package jmxbook.ch3;
- import com.sun.jdmk.comm.*;
- import javax.management.*;
- public class JMXBookAgent {
- private MBeanServer server = null;
- public JMXBookAgent() {
- System.out.println("/n/tCREATE the MBeanServer.");
- server = MBeanServerFactory.createMBeanServer("JMXBookAgent");
- startHTMLAdapter();
- startRMIConnector();
- }
- protected void startHTMLAdapter() {
- HtmlAdaptorServer adapter = new HtmlAdaptorServer();
- ObjectName adapterName = null;
- try {
- adapter.setPort(9092);
- adapterName = new ObjectName("JMXBookAgent:name=html,port=9092");
- server.registerMBean(adapter, adapterName);
- adapter.start();
- } catch (Exception e) {
- ExceptionUtil.printException(e);
- System.out.println("Error Starting HTML Adapter for Agent");
- }
- }
- protected void startRMIConnector() {
- RmiConnectorServer connector = new RmiConnectorServer();
- ObjectName connectorName = null;
- try {
- connector.setPort(2099);
- connectorName = new ObjectName("JMXBookAgent:name=RMIConnector");
- server.registerMBean(connector, connectorName);
- connector.start();
- } catch (Exception e) {
- ExceptionUtil.printException(e);
- }
- }
- public static void main(String[] args) {
- System.out.println("/n~~~~~~~~~~~~~~~~~~~~~~~"
- + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
- System.out.println("/n>>> START of JMXBook Agent");
- System.out.println("/n>>> CREATE the agent...");
- JMXBookAgent agent = new JMXBookAgent();
- System.out.println("/nAgent is Ready for Service.../n");
- }
- }
2) 添加异常显示类
- package jmxbook.ch3;
- import javax.management.*;
- public class ExceptionUtil {
- public static void printException(Exception e) {
- System.out.println("-------[ Exception ]-------");
- e.printStackTrace();
- if (e instanceof MBeanException) {
- boolean hasEmbeddedExceptions = true;
- Exception embeddedExc = e;
- while (hasEmbeddedExceptions) {
- embeddedExc = ((MBeanException) embeddedExc)
- .getTargetException();
- System.out.println("-------[ Embedded Exception ]-------");
- embeddedExc.printStackTrace();
- if (!(embeddedExc instanceof MBeanException)) {
- hasEmbeddedExceptions = false;
- }
- }
- }
- }
- }
3) RMI 工厂
- package jmxbook.ch3;
- import com.sun.jdmk.comm.RmiConnectorAddress;
- import com.sun.jdmk.comm.RmiConnectorClient;
- public class RMIClientFactory {
- public static RmiConnectorClient getClient() {
- RmiConnectorClient client = new RmiConnectorClient();
- RmiConnectorAddress address = new RmiConnectorAddress();
- address.setPort(2099);
- System.out.println("/t/tTYPE/t= " + address.getConnectorType());
- System.out.println("/t/tPORT/t= " + address.getPort());
- System.out.println("/t/tHOST/t= " + address.getHost());
- System.out.println("/t/tSERVER/t= " + address.getName());
- try {
- client.connect(address);
- } catch (Exception e) {
- ExceptionUtil.printException(e);
- }
- return client;
- }
- }
5) 建立RMI客户端:
- package jmxbook.ch3;
- import javax.management.*;
- import jmxbook.ch2.*;
- import com.sun.jdmk.comm.*;
- public class MBeanSetup {
- public MBeanSetup() {
- try {
- RmiConnectorClient client = RMIClientFactory.getClient();
- ObjectName hwName = new ObjectName("JMXBookAgent:name=helloWorld");
- client.createMBean("jmxbook.ch2.HelloWorld", hwName);
- client.invoke(hwName, "printGreeting", null, null);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public static void main(String args[]) {
- MBeanSetup setup = new MBeanSetup();
- }
- }
6) 运行:
运行agent:
- java -cp ../lib/jdmkrt.jar;. jmxbook.ch3.JMXBookAgent
- >>> START of JMXBook Agent
- >>> CREATE the agent...
- CREATE the MBeanServer.
- Agent is Ready for Service...
运行客户端:
- java -cp ../lib/jdmkrt.jar;. jmxbook.ch3.MBeanSetup
- TYPE = SUN RMI
- PORT = 2099
- HOST = chengy
- SERVER = name=RmiConnectorServer
引用:
http://docs.huihoo.com/java/jmx/jmx_base.html
http://gocom.primeton.com/modules/newbb/item38916_38916.htm