15.2 JMX的基本概念
15.2.1 JMX的3层架构
JMX技术解决的是如何管理各类资源的问题。完整的JMX应用所关联的对象分为以下两类。
l 可管理资源(Manageable Resources):JMX管理的资源可以是系统、应用、服务、设备或是一个用户,只要这些对象可以通过Java语言描述。当这些资源通过MBean描述时,它们就被封装成为可管理资源。
l 管理应用(Manage Application):管理应用指各类通过JMX管理接口对可管理资源所进行的操作。
JMX要将各种资源封装成可管理资源,同时为各类管理应用访问可管理资源提供支持。三者的关联如图15-2所示。

图15-2 JMX应用所关联的两类对象
JMX应用架构被分成3个层次,分别为:装配层(Instrumentation Level)、代理层(Agent Level),分布式服务层(Distributed Service Level),如图15-3所示。对照图15-2,中间的代理层提供类似总线的连接和可插拔服务的相关实现,装配层对应着可管理资源的相关实现,分布式服务层对应着管理应用的相关实现。

图15-3 JMX架构图
(1) 装配层(Instrumentation Level)
装配层的主要任务就是对资源进行封装,使之成为可管理资源。所谓封装,就是通过将资源用类似Java Bean的方式描述出来。当资源以这种方式被封装成为可管理资源后,就被称作MBean(Management Bean)。
(2) 代理层(Agent Level)
代理层位于装配层和分布式服务层之间,包含MBean服务器、注册的MBean和连接器。代理层的作用体现在内外两方面:对内它通过MBean服务器(Managed Bean Server)维护着MBean的生命周期(包括注册和注销MBean),同时为所注册的MBean提供各类服务;对外通过连接器将已注册的MBean的管理接口暴露给外面的管理应用使用。
(3) 分布式服务层(Distributed Service Level)
分布式服务层驻留着管理应用。管理应用通过连接器(Connector)与MBean服务器建立连接,并通过管理接口(Management Interface)去访问各个Mbean所包装的可管理资源。JMX Remote API Specification(JSR-166)对分布式服务层的应用给出了具体的规范。
JMX的3层架构的每一层都分布着不同的JMX组件,下面分别加以介绍。
15.2.2 MBean组件
MBean是Management Bean的缩写,负责将可管理资源和服务封装成类似Java Bean的形式。通过MBean的特性可以访问可管理资源的各类信息。MBean对资源的封装体现在以下几个方面:
l 属性名称及读写类型。
l 对资源的操作。
l 指定类型的通知。
说明:JVM已经默认被封装成可管理对象。可通过它去访问内置的JVM,从而远程监控并管理JVM。
MBean在JMX的3层架构中位于装配层和代理层,这两层中的MBean有着不同的作用:位于装配层的MBean被用来封装可管理资源,而位于代理层的MBean被用来封装MBean服务器提供的代理服务(比如定时器服务和监视器服务)。
从MBean的实现上来看,MBean分为两种类型:标准(Standard)MBean和动态(Dynamic) MBean。其中动态MBean又进一步分为Open MBean和Model MBean,如图15-4所示。

图15-4 MBean的分类
1. 标准(Standard)MBean
标准MBean适用于描述那些数据稳定且可被事先准确定义的资源。标准MBean就是一个普通Java Bean,MBean服务器通过Java的内省(Introspection)机制来获知标准MBean的属性、事件和方法,只是这里内省所遵循的命名规定是JMX特有的命名约定。
在各类MBean中,标准MBean的实现最为快捷方便。但在某些情况下,标准MBean并不能满足需要,比如一个资源对于不同用户有着不同的访问接口,或在不同运行状态有着不同的访问接口,这时管理接口将无法预先定义,这时就需通过动态MBean来解决问题。
2. 动态(Dynamic)MBean
动态MBean适用于描述那些要在运行时才可确切知道的数据结构的资源。与标准 MBean不同的是,动态MBean所暴露的管理接口不必事先确定,而是可根据运行时的情况,判断生成最终的管理接口。比如用以描述配置的MBean,可能需要通过对配置文件的分析来最终获得属性的名称和类型。
动态MBean的标志是实现了javax.manangement.DynamicBean接口。接口中的方法getMBeanInfo()所返回的就是要对外发布的管理接口。与标准MBean不一样的是,MBean服务器不是通过内省,而是通过getMBeanInfo()方法的返回值来获取动态Bean的管理接口。
动态MBean和MBean服务器所支持的接口非常一致,这是因为MBean服务器要对标准MBean的管理接口进行内省的实现,而这也是动态MBean自身要实现的逻辑。这样,管理应用在通过MBean服务器访问两类MBean时感觉不到任何差别,因为两者的差别在MBean服务器内部被屏蔽掉了。
Model MBean和Open MBean都是动态MBean的延伸。
(1) Model MBean预先实现了某些行为,并允许在运行过程中间进一步定制这些行为。Model MBean的标志是实现Model MBean接口,并在ModelBeanInfo对象中提供元数据的资源配置。Model MBean提供了将资源适配到MBean接口的能力。
(2) Open MBean是一类特殊的动态Mbean,它的特征是只针对特定对象,比如原始的数据类型(如int和float)和复合的数据类型。
3. MBean与Java Bean比较
Java Bean是最早的Java规范,它实际上是一套命名规范和设计模式。MBean沿用了Java Bean的一些命名规范并继承了Java Bean的许多特性。比如,通过内省机制得到MBean的属性和方法;通过辅助类MBeaninfo提供了更精确的关于MBean的信息;为特定需求动态MBean所提供的对MBeaninfo的实现类似于Java Bean的Customer接口的实现;通用工具如JConsole对访问MBean的支持类似于IDE(集成开发环境)对访问Java Bean的支持。
15.2.3 MBean服务器
MBean服务器位于JMX的3层架构中的代理层,它是代理层的核心,负责完成代理层的主要功能。MBean服务器管理着MBean的生命周期,即注册和注销,并向MBean提供各类服务,包括动态加载(Advanced Dynamic Loading)服务、监视(Monitor)服务、定时器(Timer)服务和关联(Relation)服务。
MBean服务器和它所代理的MBean所驻留的Java虚拟机被称作代理端(Agent Side),而管理应用所驻留的Java虚拟机被称作管理端(Manage Side)。管理端对代理端的访问多为远程访问,而MBean服务器对其代理的MBean的访问都是本地访问。
1. Object Name
Object Name是MBean的唯一标识,它在MBean向MBean服务器中注册时指定。管理应用可以通过这个标识来寻址MBean。Object Name体现了MBean服务器关于MBean的命名机制,这一机制是管理应用和MBean之间实现松耦合的关键。Object Name的语法如下:
[domainName]:property=value[,property=value]*
可以看到,Object Name由两部分组成:域名和一组关键属性,具体说明如下。
(1) 域名(Domain Name)
关于域名的命名和Java包的约定一致,即“反向的DNS名 + 组织自定义的字串”。比如由Sun公司开发的MBean,其DNS名是sun.com,则其域名格式是com.sun.MyDomain。
(2) 关键属性(Key Properties)
关键属性是一些Key-value对,通过它们可以为MBean在指定的域中添加包括名字、类型和说明等属性,但这些属性可以不是MBean的实际属性。
【例15.1】几个Object Name的实例:
MyDomain:description=Printer,type=laser
MyDomain:description=Disk,capacity=2
DefaultDomain:description=Disk,capacity=1
DefaultDomain:description=Printer,type=ink
2. 管理接口
MBean被MBean服务器注册并启用后,MBean服务器将解析MBean所获得的管理接口并将其暴露给外部的管理应用。管理应用必须通过MBean服务器提供的管理接口来访问MBean,而不能直接访问MBean。MBean服务器提供的管理接口具体包含以下几部分:
l 管理注册的MBean。包括属性读写和方法调用。
l 接受MBean发出的通知。
l 实例化并注册MBean。这些MBean可以是来自驻留在代理端的类(Class),也可以是从网络或本地装载来的新类。
【例15.2】注册Mbean:
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
CacheControl MBean = new CacheControl();
//注册时,必须给MBean指定一个唯一的object name
ObjectName name = new ObjectName("com.example:type=CacheControl");
mbs.registerMBean(MBean, name);
// 也可以使用下句:
//mbs.createMBean(CacheControl.class.getName(), name);
3. 描述MBean服务器的Delegate MBean
在JMX规范中,MBean服务器默认定义了一个叫做JMImplementation的域,并在这个域中默认地注册了一个叫MBeanServerDelegate的MBean。这个MBean所标识和描述的就是MBean服务器。MBean服务器发出的事件通知就是由这个对象播发出去的。
MBeanServerDelegate所定义的属性都是只读的。它的对象名是JMImplementation:type= MBeanServerDelegate。用JConsole连接到任一个MBean服务器,都可以看到这个对象,如图15-5所示。

图15-5 描述MBean服务器的Delegate MBean
15.2.4 JMX消息模型
Notification(消息)被用来特指JMX应用中的事件。JMX消息模型所描述的是MBean之间交换信息的机制。JMX消息模型包括消息播发器、JMX消息、侦听器(Listener)和过滤器等对象。JMX消息经过过滤器的筛选,由消息播发器发送给消息侦听器。JMX消息模型如图15-6所示。

图15-6 JMX消息模型
消息播发器和侦听器可以是任意对象,只要它们实现了相应的接口,MBean和MBean服务器都可以充当消息播发器或侦听器的角色。侦听器需支持NotificationListener接口,这个接口定义了事件被触发时侦听器所要完成的操作。消息播发器则要求维护一个所要通知的消息侦听器的列表,它通常实现了接口NotificationBroadcaster或NotificationEmitter。过滤器须实现NotificationFilter 接口,并通过实现接口中的方法isNotificationEnabled(Notification notification)来决定过滤哪些消息。
JMX消息是Notification类或其子类的实例,它封装了播发器所要通知侦听器的内容和相关信息,参见表15-1。
表15-1 JMX消息的构成
|
属 性 |
说 明 |
|
Source |
消息播发器的实例引用 |
|
message |
对Notification的说明 |
|
SequenceNumber |
Notification实例的唯一标识 |
续表
|
属 性 |
说 明 |
|
TimeStamp |
时间戳。Notification何时生成 |
|
Type |
用点标注法表示的JMX消息类型。比如JMX.MBean.registered |
|
UserData |
具体的要传达的信息 |
JMX通知机制与Java Bean的事件机制主要的不同在于:JMX通知在播发器和侦听器之间的传递是统一的。这样播发器和侦听器无需预先约定事件类型,而对不同通知的差别可以通过Notification类的Type和通用的UserData来表述。
15.2.5 代理服务(Agent Service)
MBean服务器提供给注册MBean的服务被称作JMX代理服务,它们本身也被封装成MBean的形式。代理服务位于JMX架构中的代理层。代理服务主要包括四类:动态加载(Advanced Dynamic Loading)服务、监视(Monitor)服务、定时器(Timer)服务和关联(Relation)服务。分别说明如下。
(1) 动态加载服务——通过获取包含MBean相关信息的XML文件MLet(Management Applet),实例化并注册MBean。
(2) 监视服务——监视MBean的属性变化,当属性值的变化超出预定义的范围时,相应地发出通知。根据所监视的属性,JMX定义了三类监视器。
l 计数器监视器(Counter Monitor):监视整型(Integer)类型的属性值,当数值变更幅度超出预设时触发事件。
l 度量监视器(Gauge Monitor):监视整型(Integer)或浮点类型(Floating)的属性值,当数值超出预设的上限或下限时触发事件。
l 字符串监视器(String Monitor):监视字符串(String)类型的属性值,当字符串变更时触发事件。
(3) 定时器服务——在指定时间触发事件或周期性地重复触发事件。
(4) 关联服务——定义MBean之间的关联并且维护关联的一致性。这方面的实现由包javax.management.relation提供。
15.2.6 连接器(Connector)
连接器位于JMX的3层架构中的分布式服务层。连接器负责建立MBean服务器和管理应用之间的通信。连接器由一个驻留在代理层的连接服务器(Connector Server)和管理应用的连接客户端(Connector Client)构成。连接器屏蔽了协议的差别和协议连接的复杂性,使得管理应用和MBean服务器之间的通信过程以协议无关的方式进行。在Java SE中,RMI连接器被指定为默认的连接器。
分布式服务层中另一个用来帮助建立管理应用和MBean服务器连接的组件是协议适配器(Protocol Adaptor)。协议适配器支持建立在某个协议之上的对MBean的访问。比如通过HTML适配器可以在Web浏览器中显示一个MBean。Java SE默认并未包含任何适配器。
【例15.3】构建到GlassFish应用服务器的JMX连接:
//构建JMX Agent URL
JMXServiceURL url = new JMXServiceURL(
"service:jmx:rmi:///jndi/rmi://localhost:8686/jmxrmi");
Map env = new Hashtable();
//访问GlassFish应用服务器的用户名和口令
String[] creds = {"admin", "adminadmin"};
env.put(JMXConnector.CREDENTIALS, creds);
//创建JMXConnector
JMXConnector connector = JMXConnectorFactory.connect(url, env);
//得到MBeanServerConnection
MBeanServerConnection mbsc = connector.getMBeanServerConnection();
例中通过JMXServiceURL来指定建立连接所需的信息,工厂类JMXConnectorFactory通过JMXServiceURL提供的信息创建了连接器connector,通过这个连接其可以进一步访问驻留在MBean服务器中的MBean。
JMXServiceURL提供了关键的连接信息,它的格式如下:
service:jmx:protocol:sap
其中protocol为传输协议,本例中为rmi。sap是查找到连接器服务器的地址位置,本例中为///jndi/rmi://localhost:8686/jmxrmi。







