3.1 标准(Standard)MBeans

2016-02-22 23:35:05 8,827 0


本节展示一个直接的、标准的MBean的一个例子。

        一个标准的MBean的定义:编写一个叫做 HelloMBean 的Java接口 以及 一个实现该接口的、叫做 Hello 的Java类。在该接口中,每个方法要么定义该MBean的一个属性,要么定义该MBean的一个操作。默认情况下,每个方法都定义一个操作。属性和操作 是遵守某种设计模式的方法。一个标准的MBean由一个MBean接口(该MBean接口列出了所有被暴露的属性和操作对应的方法)和一个class(这 个class实现了这个MBean接口并提供被监测资源的功能)组成。

下面的章节展示了一个标准MBean例子,以及管理该MBean的一个简单的 JMX agent。

MBean接口

一个基本的MBean接口的例子,HelloMBean,如下:

package com.tianshouzhi.jmx.mbean;

public interface HelloMBean { 
 
    public void sayHello(); 
    public int add(int x, int y); 
    
    public String getName(); 
     
    public int getCacheSize(); 
    public void setCacheSize(int size); 
}

        习惯上,一个MBean接口的名字 由实现它的Java类的名字加上后缀 MBean 组成。在这里,接口叫做HelloMBean。实现该接口的类 Hello 在下一节描述。

        根据JMX规范,一个MBean接口由属性(可读的,可能也是可写的)和操作(可以由应用程序调用)组成。

1、属性:HelloMBean 声明了两个属性:Name是一个只读字符串,CacheSize 是一个可读并可写的整数。该接口声明了 Getter 和 setter 方法,以供管理程序访问和修改属性值。如JMX规范所定义,一个 getter 方法是任何 public 方法,不能返回void,其名字以get开始。getter 方法使得管理程序能够阅读该属性的值,其类型是返回对象的类型。setter 方法是任何public方法,带有一个唯一的参数,其名字以set开始。setter方法使得管理程序能够将一个新值写入该属性,其类型和参数的类型相同。

2、操作:HelloMBean 接口声明了两个操作:Java方法 add()sayHello()

这些操作和属性的实现将在下节展示。

MBean实现

下面的 Hello Java 类实现了 HelloMBean MBean 接口,需要注意的是根据JMX规范,实现类必须接口名去掉MBean,因此这里的实现类就是Hello:

package com.tianshouzhi.jmx.mbean;

public class Hello implements HelloMBean {
    public void sayHello() {
        System.out.println("hello, world");
    }

    public int add(int x, int y) {
        return x + y;
    }

    public String getName() {
        return this.name;
    }

    public int getCacheSize() {
        return this.cacheSize;
    }

    public synchronized void setCacheSize(int size) {
        this.cacheSize = size;
        System.out.println("Cache size now " + this.cacheSize);
    }

    private final String name = "Reginald";
    private int cacheSize = DEFAULT_CACHE_SIZE;
    private static final int DEFAULT_CACHE_SIZE = 200;
}

这个直接的 Hello 类提供了声明在HelloMBean中的操作和属性的定义。sayHello()和add()操作非常简单,但是现实生活中,根据需要,操作可以很简单也可以非常复杂。

读取Name属性的方法以及读写CacheSize属性的方法也都定义了。在这个例子中,Name属性的值永远不会改变。然而,在实际场景中,该属性可能会随着被管理资源的运行而改变。比如,该属性可能代表的是 诸如 运行时间和内存使用量 之类 的统计数据。这里,该属性只是"Reginald"这个名字。

通过调用 setCacheSize 方法,你可以改变CacheSize属性的默认值200。在实际的场景中,CacheSize属性可能需要其它操作来读写,比如抛弃一些条目或分配新条目的操作。这个例子只是打印一条消息,以确认缓存大小已经被改变了。然而,我们可以定义更复杂的操作,而不是简单地调用println()

Hello MBean及其接口定义好之后,就可以用它们来管理它们所代表的资源了。

创建一个JMX Agent来管理一个资源

一旦一个资源已经由MBeans监测,就可以通过JMX agent来管理该资源。

JXM agent的核心组件是MBean server。一个MBean server是被管理对象的一个服务器,MBeans就注册在其中。一个JMX agent也包括一组管理MBeans的服务。关于MBean Server实现的细节,请参见 MBeanServer 接口的API文档。

下面的 Main class代表了一个基本的JMX agent:

package com.tianshouzhi.jmx.mbean;

import java.lang.management.*;
import javax.management.*;

public class Main {

    public static void main(String[] args) throws Exception {

        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
        ObjectName name = new ObjectName("com.tianshouzhi.jmx.mbean:type=Hello");
        Hello mbean = new Hello();
        mbs.registerMBean(mbean, name);

        System.out.println("Waiting forever...");
        Thread.sleep(Long.MAX_VALUE);
    }
}

        这个JMX agent,Main,首先通过调用java.lang.management.ManagementFactory类的getPlatformMBeanServer()方法,来获取一个MBean server,该MBean Serer已经由Java SE平台创建并初始化。如果平台还没创建MBean server,那么 getPlatformMBeanServer()就会 通过调用JMX方法MBeanServerFactory.createMBeanServer(),自动地创建一个MBean Server。由Main获取的MBeanServer instance被叫做mbs。

        接着,Main 为 将要被创建的MBean instance 定义了一个对象名。每个JMX MBean都必须有一个对象名。对象名是JMX类ObjectName 的一个实例,必须遵守定义在JMX规范中的语法。也就是说,对象名必须包含一个domain以及一个"键-值"属性列表。由Main定义的这个对象名中,domain是com.example (包含这个MBean例子的包名)。此外,"键-值"属性 声明了该对象的类型是为Hello

        接着创建了Hello对象的一个实例,命名为mbean。然后,通过将这个叫做mbean的Hello对象 及其 对象名传入JMX方法MBeanServer.registerMBean(),该Hello对象,就被注册为MBean Server mbs中的一个MBean,其对象名为name

        当该 Hello MBean 注册到了该 MBean server中之后,Main简单地等待对Hello进行管理操作。在这个例子中,这些管理操作是 调用sayHello()add()方法 以及读写属性的值。

标准MBean的优势和局限:

  • 局限:操作方法的参数以及返回值的类型 只能是基本类型,比如String、int、long等等。

  • 优势:上面这个局限,正是SOA架构中,各Service松耦合所需要的!各MBean完全没有reference依赖!这种优势正是来自这个局限。

我 们也可以发现,通过JConsole操作MBean时,参数只能是基本类型!复杂类型是无法表述的!如果我们用了java.util.Date这样的复杂 类型,则JConsole只能读取,不能设置!如果我们在Getter/Setter中使用了自定义的类型(JDK中不存在),则 JConsole(Java SE7版)提示"不可用",因为JConsole无法识别它。

运行这个标准MBean例子

你已经查看了这个例子的相关classe,你现在可以运行该例子了。在本例中,我们使用JConsole来和该MBean进行交互。

要想运行这个例子,遵照下面的步骤:

    如果你用的是 JDK 6,那么用下面的命令启动这个Main应用程序。

java com.tianshouzhi.jmx.mbean.Main

  
    如果你用的JDK版本老于 版本6,那么你需要用下面指定的选项来启动该 Main 程序,从而暴露该程序中的MBean接口以供监控和管理。

 java -Dcom.sun.management.jmxremote com.tianshouzhi.jmx.mbean.Main

  
    启动程序后,在终端窗口中启动JConsole。

    jconsole

    新连接对话框就会被心事,展示一列运行中的、可供你连接的JMX agents。
    在新连接对话框中,从列表中选择 com.tianshouzhi.jmx.mbean.Main,然后点击Connect。你的平台的当前活动的一个汇总信息就会被现实出来。
    点击MBeans标签页。该版面现实了所有注册在该MBean Server中的MBeans。在左边的边框中,展开MBean树中的 com.tianshouzhi.jmx.mbean节点。
Image.png   

    你可以看见我们的样例MBean,Hello,它已经被创建,并由Main注册。如果你点击Hello,你就能在MBean树中,看见其相关的属性和操作节点。在这个界面中,你可以进行以下操作


    展开Hello MBean在MBean树中的属性节点。

    由Hello类定义的MBean属性就会被现显示出来。
    将CacheSize属性的值改为150。

    在你启动Main的终端窗口中,你将看到一条关于该属性的修改确认信息被生成。
    展开Hello MBean在MBean树中的操作节点。

    由Hello MBean声明的两个操作 sayHello() 和 add()就会被显示出来。
    通过点击sayHello按钮来调用 sayHello() 操作。

    一个JConsole对话框将会通知帮你,该方法被调用成功。在Main所运行的终端窗口中,"hello, world"消息被生成。
    为 add()操作提供两个整数,然后点击 add 按钮。

    答案将会显示在一个JConsole对话框中。
    要想关闭JConsole,选择 Connection -> Exit。

上一篇:3.0 MBeans介绍 下一篇:3.2 MXBeans