UML软件工程组织

 

 

使用 JMX 设计模式进行应用程序管理设计

2008-05-20 作者:Justin Murray 出处:dev2dev.bea.com.cn

 

Java 管理扩展 ( JMX ) 技术是 Java 2 平台的标准版 ( J2SE ) 5 和企业版 ( J2EE ) 的重要组成部分。现在,与 J2EE 兼容的应用服务器需要支持这个标准,因为其中一些服务器使用 JMX MBean 作为基础架构。设计模式自从开始引入以来就一直很受欢迎,现在,我们还可以把这些设计理念用于应用程序的易管理性设计中。

为了使应用程序在生产过程中更易于管理,我们将结合 JMX 和记录的使用,对整套设计模式进行介绍,同时将这些策略外延到代码中。这部分应用程序对架构师来说非常重要,因为大多数应用程序的生命周期仅限于部署阶段。为了使操作人员能够对应用程序进行有效的监控和管理,有必要对应用程序进行控制和可视化操作。现在,对于某些因为其他目的而继续使用较传统的记录的动态要求来说,使用 JMX 来操纵应用程序是监控和管理应用程序的最佳方法。

您可以构建自己的自定义 MBean , 它将与应用服务器一起提供的 MBean 或 Java 虚拟机 ( JVM ) 提供的 MBean 一起使用。当应用程序的内部工作的可管理性需求高于应用程序的内部对象和属性的可视性需求时,使用这种组合是最好的做法。从应用程序中将消息记录到文件或其他目标文件中是一种常用技术,该技术为操作人员提供了对运行产品的某种程度的监控。记录消息是一种跟踪发生在应用程序内部的异常情况或静态错误(包括从指示性错误到致命性错误)的有效方法。记录是让管理人员了解应用程序内部情况的基本办法。

但是,对于高速变化的应用程序性能数据(即测量应用程序的整体性能的数据)来说,日志文件并不适合。例如,由于登录人数无时无刻不在变化,不可能为每一位登录系统的用户都提供新的日志消息。

数据捕获

较好的办法是先将这些不断变化的数据收集到一个对象中 ,即 JMX MBean 中,然后定期将这些数据从 MBean 收集到一个管理工具中。例如,可使用该技术捕获系统进程中事务的数量,或者捕获包含等待处理的请求的那个队列的长度。通过把要处理的业务事务的数量与队列中等候处理的事务数进行比较,就可以了解应用程序的运行状况。

以这种方式使用 MBean 是使用 JMX 的最佳实践之一。 MBean 是计算因管理应用程序而可视的那些项的数量的一个好工具。随着时间的推移,这些从 MBean 中收集来的数据最后还可以绘成图形,用来表示相关的性能,或者表示应用程序的其他度量标准之一。 JMX MBean 还可用于统计不变的数据,例如警告、异常或者错误消息,但这些不是它的主要用途。

在编写适用于 JMX 模型的代码时应考虑到一些问题。在此,需要考虑的问题是:该模型的哪些方面经常变化?

  1. 创建 MBean 对象的目的是为实现应用程序的可管理性提供数据源和控制点。业务对象本身也可以实现或继承适当的 MBean 接口,使自己成为一个拥有自身权利的 MBean ,这一过程包括创建一个业务对象,因此,要严格遵守 Standard MBean (即 DynamicMBean ) 接口的规则。 ( 关于这些 MBean 接口规则的更多信息。 )
  2. MBean 对象在向 MBean 服务器注册之后才能使用。其中, MBean 服务器是应用服务器的一个组成部分,或者是 JVM 进程 的一个组成部分。
  3. MBean 在注册时使用的名称是一串单独的字符串,扮演 MBean 客户角色 的其他所有对象都必须使用该字符串,以便这些对象被正确找到。
  4. MBean 对象通过向 MBean Server 提供 MBean 名称和 MBean 上某一方法的名称(二者都以字符串的形式提供的),来调用 MBean 上的方法,并请求 MBean Server 调用 MBean 上的这个方法。
  5. 在某些时候, MBean 还会发出通知,以确定是否出现某些条件。

现在我们已经对将 JMX 用于可管理性有了一个总的看法,下面让我们来分析一下这些模式的特殊用途。很明显,将基于字符串的名称用于散布在整个应用程序中的对象和方法是一种趋势。这些名称经常发生变化并产生错误;因此,我们应该以某种模式封装它们,这也正是开发 MBeanHelper 模式的动力所在。

MBeanHelper

MBeanHelper 模式可以简化从使用 MBean 的 对象访问 MBean 的过程 ( 参见 图 1 ) 。该模式可以加强业务对象和相关 MBean 之间的联系。二者之间的联系基于两个字符串的需求,一个字符串用于对象名称,另一个字符串用于方法调用及其参数。这些字符串会破坏我们试图在对象之间维护的强类型( strong typing )。将使用的 MBean 的名称封装在 Helper 类中。将调用的方法名称也通过使用一个强类型接口封装在 MBeanHelper 类中,以便提供编辑时类型检查。 Helper 类对客户隐藏了用来在 MBean 服务器中搜寻 MBean 的所有代码。

图 1 : MBeanHelper 模式

MBeanHelper 模式可以简化从使用 MBean 的 对象访问 MBean 的过程 , 并加强业务对象与相关 MBean 之间的联系。

在应用程序中构建可管理性的一个重要方法是创建一个或多个业务对象,这样就可以让它们将重要数据写入 JMX MBean 中。但是,我们不想在这些业务对象的逻辑中加入太多特定于 JMX 的代码。我们想使指令变得简洁一些,对 JMX MBean 调用一个 简单的方法是在业务代码中需要做的所有事情,这意味着对业务对象隐藏命名和查找适当 MBean 的所有方法。这些指令应该在设计模式下完成。

MBeanHelper 模式就是为此目的而设计的。它通过 MBean 的名称在 MBean 服务器的储存库中查找正确的 MBean , 并调用正确的方法。 MBeanHelper 本身并不是一个 MBean , 它仅仅是某种类型的 MBean 的一个众所周知的端点 , 可将它用作通向 MBean 的一个关口。

字符串本身并无法保证应用程序开发人员在输入 MBean 名称和调用方法的名称时不会出错。编辑器根本不可能发现这类错误,因为它对 MBean 的名称和应用于这些名称的规则一无所知。不过,对 MBeanHelper 类上的某个方法的调用是通过编辑器进行类型检查的。我们只需让 Helper 类知道基于字符串的 MBean 名称并检测其准确性即可,无需对应用程序中的每次 MBean 使用都进行检测。 JMX1.2 版本中新增的 JMX 库为 InvocationHandlers 提供了 类似功能。

MBeanHelper 对象的生命周期必须与 MBean 本身的相同。所以这时处理 MBeanHelper 对象的生命周期问题一定会被认为是一项附加任务。 而且 MBeanHelper 的方法调用成本与 MBean 本身的方法调用成本之间也存在权宜,这可能对性能产生影响。

MBeanHelper 是 MBean 的惟一接口 , 所以如果想实现从 MBean 发出通知 , 还必须实现从 MBeanHelper 发出通知。

MBeanForAppConfig

现在让我们看一下 MBeanForAppConfig 模式 , 它包含 MBean 的 一种最简单的用途 —— 一个包含 应用程序启动信息和运行时配置信息的容器。 ( 参见 图 2 )

图 2. 启动容器

MBeanForAppConfig 模式提供了一个包含应用程序启动信息和运行时配置信息的容器,这是 MBean 最简单的用途之一。

用于应用程序配置数据的 MBean 允许应用程序在启动时从外部来源收集初始配置信息(例如属性文件)。然后,通过对应用程序进行适当设计,操作人员可以更改应用程序的配置元素。这些更改是通过在应用程序的生命周期期间从配置 MBean 发送到其他对象的通知来完成的,无需重启。例如,为了获得关于应用程序内部情况的更多数据,您可能希望更改所看到的日志级别。

在应用程序中,一个或多个 MBeanForAppConfig 对象都要符合这种样式,根据配置要求的复杂性的不同,每个对象控制着应用程序配置的不同部分,例如用户配置、数据库连接配置或其他配置。

在启动应用程序时, MBeanForAppConfig 对象从文件、数据库或者管理员已经设置了各种属性的其他介质中读区配置属性。然后, MBeanForAppConfig object 对象允许经过授权的管理员访问和更改属性的值,这些属性可以通过管理工具(或基于浏览器的管理工具)进行配置。所做的更改可以通过 Observer 模式或者 JMX 通知传递给相关的业务对象,如果有必要的话。

MBeanForAppConfig 对象可以对照某一单独对象来确定正在设置的属性是否是所允许的值,如果不符合要求,则不允许设置这个新的设置。我们还可以创建另一个 MBean (最好是动态 MBean ),用它来捕获所允许的组成应用程序配置的那些数据项的值,但是创建这个 MBean 对大多数应用程序来说太困难了。这个逻辑可能也存储在 MBeanForAppConfig 对象中。

MBeanForAppConfig 对象还可以通过如下方式进行设计:把所有配置更改写回一个文件中。如果任务需要的话,还可以将这些更改写回最初派生其初始值的属性文件中。 在需要 将运行时对配置所做的所有更改反射到下一个启动配置中去时,将应用这个过程。

如果允许在应用程序的生命周期中的任意时间点进行更改,那么 MBeanForAppConfig 对象在这个过程的生命周期内也应该是有效的。通过使用在 JMX 中也可用的通知方案,对象可以以断开连接的方式传输状态的变化。接收来自 MBeanForAppConfig 对象的通知的 NotificationListener 对象的列表会随时间发生变化 , 因此 MBeanForAppConfig 对象不应将自身与其生命周期相关联。

SeparateMBean

为应用程序易管理性设计的方法之一是:允许应用程序中的任何业务对象通过创建 MBean 接口,然后设计使用业务对象实现该接口,来拥有 MBean 风格的接口。该技术的优势在于能够直接实现接口。这意味着业务对象要在同一对象中同时提供业务功能和管理功能。

但是,这项技术容易产生问题。例如,任何涉及对象的管理接口的工具都将直接影响业务对象的性能。当业务对象处理重要事务时,可能还会要求业务对象在同一时间通过其 JMX 接口对管理人员的介入作出相应。这说明当业务对象执行业务逻辑的重要操作时,我们需要设置屏障来防止操作人员的干涉。这样做的风险是需要长时间锁定对象。

在实现或编码层次上,将业务和管理问题混淆可能会带来其他不利影响(这一点将在 SeparateMBean 模式中讨论)。总之,在设计阶段,应该将系统的管理接口和业务接口分开考虑。这两个接口是由不同的对象实现的。

SeparateMBean 模式主要描述 MBean 的创建过程 , 这个 MBean 对象是与需要管理的某个业务对象或者某些对象分隔的单独的对象。将管理方面的问题与业务方面的问题混合到一个对象中将破坏业务接口的整洁性。将这些问题混在一起可能带来安全性问题,比如说操作员错误地调用业务方法,或者业务人员错误地调用运算方法。在使用混合接口的情况下,业务逻辑开发人员还必须了解对象的所有管理方面,或者该对象的与 JMX 相关的方法。虽然在许多团队中,可能由单独的架构师来分别进行这两种类型的设计,但是, MBean 接口的设计和实现是与业务对象的设计联系在一起的。

通过将 MBean 和与之相关的业务对象分开,成为与这些对象不同的对象 , SeparateMBean 模式可以解决这些问题。在创建业务对象时,这些对象不必实现 MBean 接口。而是引用一个充当其管理方的单独的 MBean 对象。管理 MBean 的创建时间可能与业务对象的相同,也可能不同。

表示 Separate MBean 模式的 BusinessObjectManager ( 参见 图 3 ) 由 BusinessObject 或其他各方创建 , 因此 , 它可以管理 BusinessObject 所属的那个类的一个或多个实例。 BusinessObjectManager 包含提供管理接口所需的所有逻辑 , BusinessObject 或其他各方可以使用这些逻辑。 BusinessObject 可以 调用方法或者向 BusinessObjectManager 发送通知 ,以便使用 与管理工具相关的信息进行更新。 BusinessObjectManager 还可以调用 BusinessObject 上的方法来检索这些信息。

图 3. 表示

BusinessObjectManager 表示了 Separate MBean 模式 , 它由 BusinessObject 或其他各方创建 , 因此 , 它可以管理 BusinessObject 所属的那个类的一个或多个实例。

该模式通过使用更多的对象对问题进行区分。过去,一个业务对象同时也是一个管理对象,如今,这种模式拥有两个具有不同用途的对象。

使用此模式的代价是在业务对象和管理该对象的 MBean 之间维护一个引用。如果使用继承 / 接口实现的方法来创建一个也是 Mbean 的业务对象的话,那么可以省去这个引用。使用这种模式要求在创建 Factor 方面有更多 的智能 , 主要与何时创建 BusinessObjectManager MBean ( 或者为整个 BusinessObject 实例集合一次性创建该对象 ) 有关。

采用这种模式时 , 需要制定设计决策 , 以确定业务对象是否需要通过方法调用主动向 BusinessObjectManager MBean 发送数据 , 或者 BusinessObjectManager MBean 是否定期轮询业务对象来获得数据。对于不同的情况,这两种模式可能都很有用,但是为了保持性能,多数情况下采用推模型( push model ) —— 即在必要的时候,业务对象主动将数据推向 MBean 对象。

Policy Separation Pattern

SeparatePolicyfromMBeanPattern 模式的用途是 : 让可变更管理策略的所有考虑事项统统避开收集性能数据的 MBean (参见 图 4 )。 我们采用的第一种方法是把 MBean 用 作数据容器 , 而不是将它用作可管理性策略的算法实现。我们想立即把这两个实体分散到不同的对象中去。

图 4 : 分离

采用 SeparatePolicyfromMBeanPattern 模式 , 让可管理性策略的所有考虑事项统统避开收集性能数据的 MBean 。

例如,收集关于 JMS 主题的某些项的重要队列的长度或深度数据的操作,与只要队列在 50 个条目上所花的时间超过一分钟即发出报警信号的策略是分开的。后者所关注的是管理策略。前者关注的主要是数据采集。我们可以将用于策略的逻辑存储在 MBean 中,或者将它存储于完全在该过程之外的一个独立的管理引擎中。我们可以在 MBean 属性中存储数据,同时对这些数据进行计算。只有最基本的计算 ( 如果有的话)应该 在 MBean 代码中进行。

如果不想兼顾从 MBean 中提取管理策略的原则,可以考虑使用具有可更改策略的单独的 MBean 以及那些从外部可获得的 MBean 来执行更改操作。通过把 MBean 作为数据容器从如何处理它的规则中分离出来,我们在及时更改策略的方法上获得了更多的灵活性。

在应用程序可管理性设计中采用的一个重要构造模式就是仅仅把 MBean 当作数据容器使用,而不是将它作为可管理性策略的算法持有者。例如,像“当应用程序中一次使用的购物车超过 1000 辆时,在管理控制台上显示一条信息”这类的做法将会改变。捕获这些策略是 MBean 领域之外的工具的工作;因此,无需破坏 MBean 的逻辑或重新编辑它即可进行更改。但是,采用这种方法是有特殊原因的。进行设计的时候总是需要一些妥协,所以即使是那些最佳实践和模式,也不能把它们看成适合所有情形的硬性规则。

我们讨论了许多允许构造 Java 、 J2EE 或者 Web service 应用程序的可管理性方面的设计模式。一旦投入生产,良好的可管理性就是应用程序成功的关键。在实际应用中,常常都是由非开发人员来管理应用程序。每一种模式在使用过程中都有其优缺点。在应用程序中建立可管理性以及在实现过程中使用这些模式的同时,还要认真分析应用程序的性能。

应用程序设计人员在设计阶段就应该考虑应用程序的可管理性,而不是在以后才考虑。一种选择是将与业务相关的逻辑和可管理性逻辑分开,在应用程序中为这些问题提供单独的对象。我们推荐您使用这种分离问题的方法, MBeanHelper 模式中显示了这种分离。

本文只是抛砖引玉地介绍了一些用于 JMX 和应用程序可管理性的设计模式,希望感兴趣的架构师和软件设计人员为这些设计模式做更多的贡献。惠普的开发人员网站提供了一个论坛,供开发人员交流心得并讨论这些用于可管理性的设计模式。

 

组织简介 | 联系我们 |   Copyright 2002 ®  UML软件工程组织 京ICP备10020922号

京公海网安备110108001071号