第2章 JMX MBean 基础知识

来源:互联网 发布:ubuntu 14.04安装qq 编辑:程序博客网 时间:2024/06/06 03:00

JMX MBean  基础知识

1  引言

这节课介绍JMX API的基本概念,即被管理的beans,或者叫MBeans

一个MBean是一个被管理的Java对象,有点类似于JavaBean,它遵循了JMX规范的一些设计模式。一个设备、一个应用或者任何需要被管理的资源都可以被表示为MBeanMBean会暴露一个管理接口,这个接口主要包括如下几个操作:

  • 一组可以读取或者写入,或既能读取也能写入的属性
  • 一组触发读取或者写入的操作
  • 一个自我描述

管理接口在MBean实例的生命周期内不会改变。当一些预定义的事件发生时,MBean也可以发送通知。

JMX API规范定义了5种类型的MBean

  • 标准MBean
  • 动态MBean
  • 开发MBean
  • 模型MBean
  • MXBean

接下来举几个例子来说明最简单类型的MBean,即标准MBeanMXBean

2  标准MBean

这一节介绍一个简单的标准MBean的例子。

一个标准MBean这样定义的:编写一个叫做SomethingMBean的接口,然后编写一个叫做Something的类来实现这个接口。接口中的每一个方法要么定义了MBean的一个属性,要么定义了MBean的一个操作。默认情况下,每一个方法定义一个操作。

属性和操作都是遵循一定设计模式的方法。

一个标准MBean由一个MBean接口和实现了这个接口的类组成。MBean接口列出了所有需要暴露的属性和操作的方法。实现了这个接口的类提供了资源的功能。

接下来的小节举例说明如何通过标准MBean和简单的JMX代理来管理MBean

2.1 MBean接口

下面是一个基本的MBean接口的例子,HelloBean

按照惯例,一个MBean接口用一个实现它的类的名字加上后缀MBean命名。在上面的代码中,接口的名字为HelloBean。我们将在下一小节介绍实现了这个接口的Hello类。

根据JMX规范,除了具有名称和类型的操作(被MBean管理的应用可以触发这些操作)外,一个MBean接口还包含具有名称和类型的属性,这些属性是可读的,也有可能是可写的。HelloBean接口声明了两个操作:add()方法和sayHello()方法。

HelloBean声明了两个属性:name(一个可读的字符串),cacheSize(一个可读可写的整数)。GetterSetter方法允许访问被管理的应用,也可能改变这些属性的值。正如JMX规范定义的那样,一个Getter方法是一个返回值不为空,以“get”开头命名的public方法。一个Getter方法使管理者能够读取属性的值,而属性的类型就是返回值的类型。一个Setter方法是一个只有一个输入参数,以“set”开头命名的public方法。一个Setter方法使管理者能够向属性中写入新值,而属性的类型就是输入参数的类型。

这些操作和属性的实现在下一节中。

2.2 MBean的实现

下面的Hello类实现了HelloMBean接口:

Hello类明确地定义了HelloMBean接口中声明的操作和属性。sayHello()add()操作极其简单,但是实际中的操作根据需要既可以很简单也可以很复杂。

获取name属性的方法、获取cacheSize属性的方法、设置cacheSize属性的方法也都在Hello类中定义了。然而,在真实的场景中,被管理的资源在运行过程中,属性值可能会变化,例如那些表示开机时间或者内存使用的属性。

在这里,name属性的值仅仅是“Reginald”,不能改变。

cacheSize属性的默认值是200,可以调用setCacheSize方法改变这个属性。在真实的场景中,改变属性值需要执行一些其他的操作,例如丢弃条目或者分配新的条目。这个例子中仅仅打印了一条消息来确认cacheSize属性值已经改变了。然而,应该定义一些更加复杂操作,而不是简单的调用println()方法。

上面定义的Hello MBean以及它的接口,可以被用于管理它们所代表的资源了,就像下一节展示的那样。

2.3 创建JMX代理来管理资源

一旦某个资源被MBean监测,那么就可以通过JMX代理管理这个资源了。

JMX代理的核心组件是MBean服务器。MBean服务器是一个被管理对象的服务器,MBean被注册到了服务器。JMX代理也包含了一组服务来管理MBean。可以查看API文档了解MBeanServer接口及MBean服务器实现的详细信息。

下面所示的Main类表示一个基本的JMX代理:

首先,JMX代理类Main调用java.lang.management.ManagementFactory类的getPlatformMBeanServer()方法从平台获取一个MBean服务器,该服务器由平台负责创建并初始化。如果平台还没有创建MBean服务器,那么getPlatformMBeanServer()方法将自动调用MBeanServerFactory.createMBeanServer()方法创建一个MBean服务器。Main类获取的MBean服务器实例的名字为mbs

下一步,Main类定义了一个MBean实例的对象名。每个JMX MBean必须有一个对象名。对象名是JMXObjectName的实例,必须遵守JMX规范定义的语法。即对象名必须包含一个域和一组键属性。在Main类中定义的对象名,域是com.example(就是包含MBean的包名),另外,键属性声明了这个对象的类型为Hello

然后,创建一个Hello实例对象mbean,连同对象名一起作为MBean注册到MBean服务器mbs中。通过调用JMX方法 MBeanServer.registerMBean(),并将对象及对象名作为入参传递给该方法实现注册。

Hello MBean注册到MBean服务器后,Main类只是简单地等待Hello里面的管理操作被执行。在这个例子里面,这些管理操作主要是sayHello()add()方法,以及属性的getset方法。

2.4 运行这个标准MBean的例子

如果已经检查过例子中的类,你现在就可以运行这个例子了。在这个例子中,使用jconsoleMBean进行交互。

  1. 保存JMX例子的压缩包jmx_examples.zip到你的工作目录work_dir
  2. 在命令行或者终端使用下面的命令解压缩这个包:unzip jmx_examples.zip
  3. work_dir目录下编译例子中所有类:javac com/example/*.java
  4. 如果你运行的是JDK6,就用下面的命令行启动Main应用:java com.example.Main

   如果你运行的是JDK6以前的版本,你需要使用下面指定的可选参数启动Main应用,并暴漏应用给以便监控和管理:java -Dcom.sun.management.jmxremote example.Main

   确认显示Main正在等待一些事情发生。

  1. 在同一台机器上打开一个新的命令行或者终端窗口,输入命令jconsole启动jconsole
  2. 在新建连接对话框中,从列表中选择com.example.Main中,并点击connect。这时,平台的当前活动的概述将会显示出来。
  3. 点击MBean标签,这个面板将会显示所有的已经注册到MBean服务器中的MBean
  4. 在左边的MBean树中,展开com.example节点。你会看到在Main创建并注册的MBean Hello。如果你点击Hello,你会在MBean树中看到它关联的“属性”和“操作”节点。
  5. MBean树中,展开Hello MBean的“属性”节点。在Hello中定义的MBean属性就会显示出来。
  6. cacheSize属性的值改为150。在启动Main的命令行或者终端窗口,可以确认属性已经修改。
  7. MBean树中,展开Hello MBean的“操作”节点。可以看到两个在Hello MBean中声明的操作:sayHello()add()
  8. 点击sayHello按钮,触发sayHello()操作。JConsole对话框会通知你sayHello方法调用成功。在运行Main类的命令行窗口产生了“hello, world”消息。
  9. add()操作提供两个整数,并点击add按钮。在JConsole对话框中将会显示出答案。
  10. 要想关闭JConsole,选择 连接->退出。

3 MXBean

这一节解释一个特殊的MBeanMXBean

MXBean也是MBean,只是它引用了一些预定义的数据类型。这样你可以确保你的MBean可以被任何MBean客户端使用,包括远程客户端。不需要额外的要求,任何客户端都有权访问代表你的MBean的造型特异的类。MXBean提供了一个便捷的方式将相关的值捆绑在一起,而不需要客户端有特殊的配置就能处理这个bundle

用与标准MBean相同的方式,MXBean是这样定义的:编一个接口叫SomethingMXBean,并编写一个类来实现这个接口。然而,不像标准MBeanMXBean不需要这个类的名字必须为Something。接口中的每一个方法要么定义了MXBean的一个属性,要么定义了MXBean的一个操作。注解@MXBean可以用于标注这个接口,而不需要这个接口的名字的后缀必须为MXBean

MXBean存在于Java2平台标准版J2SE5.0的包java.lang.management中。然而,除了在java.lang.management包中定义的标准MXBean,用户可以定义自己的MXBean。

MXBean的主要思想是一些类型,例如java.lang.management.MemoryUsage,被MXBean接口java.lang.management.MemoryMXBean引用。在这种情况下,在包javax.management.openmbean定义的所谓开放类型(Open Types)可以被映射到标准类型集上。精确的映射规则在MXBean规范中。然而,一般原则是简单数据类型(例如int,String)保持不变,而复杂数据类型(例如MemoryUsage)则映射到标准类型CompositeDataSupport。

MXBean的示例主要包含下面几个文件,可以在jmx_examples.zip中找到:

  • QueueSamplerMXBean:接口
  • QueueSampler:实现了MXBean接口的类
  • QueueSample:MXBean接口中的getQueueSample()方法的返回值类型
  • Main:设置和运行示例的程序。

MXBean示例用这几个类完成下面的几个动作:

  • 定义一个简单的MXBean来管理Queue<String>类型的资源。
  • MXBean中声明了一个get方法getQueueSample(),当触发该方法时可以获得队列的快照,返回值为QueueSample类型,它捆绑了下面这些值:快照生产的时间,队列大小,指定时间队列的头。
  • 将MXBean注册到MBean服务器。

 

3.1 MXBean接口

下面的代码展示了MXBean接口QueueSamplerMXBean:

注意:声明MXBean接口和声明MBean接口的方式是完全一样的。QueueSamplerMXBean声明了一个get方法getQueueSample和一个操作clearQueue。

 

3.2 定义MXBean操作

MXBean操作是在QueueSampler类中定义的,如下所示:

QueueSampler定义了在MXBean接口中声明的getQueueSample()方法和clearQueue()操作。getQueueSample()操作返回一个QueueSample类的实例,这个实例由java.util.Queue类的peek()方法返回值和size()方法返回值以及java.util.Date类实例构造。

3.3 定义MXBean接口中的返回值类型

QueueSampler类中返回的QueueSample实例定义在QueueSample类中,如下所示:

在QueueSample类中,MXBean框架调用QueueSample中所有的get方法,将给定的实例转换成一个CompositeData instance实例,使用@ConstructorProperties注解从CompositeData实例中重构出QueueSample实例。

 

3.4 创建MXBean并将其注册到MBean服务器中

到目前为止,我们已经定义了下面几个类:一个MXBean接口,一个实现了该接口的类,还有一个返回值的类型。下一步,必须创建一个MXBean,并将其注册到MBean服务器中。这些动作也是由JMX代理Main类来执行,同标准MBean示例一样,但是相关的代码没有在标准示例中显示。

Main类执行了下面几个动作:

  • 获取平台MBean服务器
  • 创建MXBean QueueSampler的对象名
  • 创建QueueSampler MXBean要处理的Queue实例
  • Queue实例创建一个QueueSampler MXBean实例
  • 将这个MXBean实例注册到MBean服务器(用于标准MBean一样的方式)

 

 

3.5 运行MXBean示例

MXBean示例使用jmx_examples.zip包里面的类,同标准MBean那一节是一样的。这个例子需要Java SE6以上版本。按照下面的步骤运行MXBean示例:

  1. 如果这一步还有做,那就保存JMX例子的压缩包jmx_examples.zip到你的工作目录work_dir
  2. 在命令行或者终端使用下面的命令解压缩这个包:unzip jmx_examples.zip
  3. work_dir目录下编译例子中所有类:javac com/example/*.java
  4. 启动Main应用:java com.example.Main。确认显示Main正在等待一些事情发生。
  5. 在同一台机器上打开一个新的命令行或者终端窗口,启动JConsole。新建连接对话框将会显示出来,列表中显示出可以连接的正在运行的JMX代理。
  6. 在新建连接对话框中,从列表中选择com.example.Main中,并点击connect。这时,平台的当前活动的概述将会显示出来。
  7. 点击MBean标签,这个面板将会显示所有当前注册到MBean服务器中的MBean
  8. 在左边的MBean树中,展开com.example节点。你会看到在Main创建并注册的MBean QueueSampler。如果你点击QueueSampler,你会在MBean树中看到它关联的“属性”和“操作”节点。
  9. 展开“属性”节点。你将会看到属性QueueSample出现在右边的面板,还有它的值javax.management.openmbean.CompositeDataSupport。
  10. 双击CompositeDataSupport值。你会看到QueueSampledateheadsize属性值。因为MXBean框架已经将QueueSample实例转换成了CompositeData。假设你定义的QueueSampler是标准的MBean而不是MXBean,那么JConsole就找不到QueueSample类,因为它不在类路径里。如果QueueSampler是一个标准的MBean,那么当你恢复QueueSample属性值时,你会收到一个ClassNotFoundException异常消息。JConsole能够找到QueueSampler类的事实说明:当通过通用JMX客户端(例如JConsole)连接JMX代理时,使用MXBean是很有用的。
  11. 展开“操作”节点。触发clearQueue操作的按钮就会显示出来。
  12. 点击clearQueue按钮。就会显示触发方法成功的确认消息。
  13. 再次展开“属性”节点,双击CompositeDataSupport值。你会看到,Head和size的值已经被重置。
  14. 要想关闭JConsole,选择 连接->退出。

 

 

 

 

 

 

 

原创粉丝点击