技术开发 频道

把JBoss缓存用作POJO缓存的实战演练

【IT168 技术文档】

 引言
 
  内存缓冲在大规模企业应用软件开发过程中是一个关键的技术,其中往往都有可伸缩性和高性能的需求。一个内存缓冲能存储应用程序状态信息(如,一个WEB应用程序中的HttpSession)或数据库查询结果(也即,实体数据)。由于许多企业应用软件运行在一个簇环境下,所以缓存需要跨越簇进行复制。而且,如果需要更高的可靠性的话,内存缓冲也应该被持续性存储到硬盘或数据库中去。
 
  大多数内存缓冲解决方案都属于我们所称的"普通"缓存系统类——其中存储和缓冲直接参考的对象。既然一个普通缓存直接处理参考对象,那么它就象一个详尽的HashMap结构一样,并因此使用起来非常直观。当一对象需要被复制或持续存储到一个普通缓存系统中时,对象必须实现Serializable接口。然而,普通缓存在复制或持续存储方面也存在一些明显的限制:
 
  ·用户必须具体地管理该缓存。例如,当一对象被更新时,用户需要执行一相应的API来更新缓存内容。
 
  ·Java对象串行化的需要可能会对性能有所妨碍。如果对象是巨大的,甚至单个的字段更新也将会激活整个对象的串行化与跨整个簇的复制。这样可能带来不必要的昂贵的代价。
 
  ·Java对象串行化不可能保存缓冲对象之间的关系。特别地,该缓冲对象不可能被其它对象参考多次,或到其自身有一个间接参考(循环)。否则,在串行化时该关系将被打破。
 
  相对于上面普通缓冲系统中存在的问题,还有另外一种新型的缓冲系统——POJO(简单Java对象)缓存。一个POJO缓存是一个系统——它担当一个"面向对象的"分布式的缓存。在这个系统中,一旦一个用户把POJO依附到该缓存上,那么缓冲方面(例如复制和持续性)应该对用户是透明的。一个用户只需简单地在该POJO上操作而不须担心更新该缓存内容或维持对象关系的问题。不存在显式的API调用可用来管理该缓存。另外,它还有三个特征:
 
  ·不需要为POJO实现Serializable接口。
 
  ·复制(或甚至持续性)是基于字段级的(这与普通缓存中的基于整个对象的二进制级形成对照)-这将导致潜在的性能推进。
 
  ·对象关系和身份被自动地保存在一分布式复制环境中,这带来透明的使用体验并且提高了软件性能。
 
  一个领先的内存POJO缓存解决方案就是开源JBoss缓存。JBoss缓存是第一个Java库——它支持可复制的,持续性的,事务性的和良好粒度的缓冲,它可以被使用作为POJO缓存和普通缓存。既然JBoss缓存是百分之百基于Java的,那么它就可以运行在任何Java SE环境中——包括应用程序服务器内部或作为独立的进程。例如,JBoss缓存已经被应用到针对EJB 3.0有状态的会话bean簇和HPP会话复制的应用程序服务器中。
 
  在本文中,我们将说明怎样把JBoss缓存用作一个POJO缓存(通过它的JBossCacheAop组件)。同时,还将给出一个应用案例来说明在分布环境中的一些关键特性。
 
JBoss缓存概述
 
普通缓存
 
  JBoss缓存中默认的普通缓存模块称为TreeCache。你可以通过编程方式或通过一外部XML文件对它进行设置。下面是你可以设置的一些特性:
 
  1. 缓存模式:它可以是本地的或者是可复制的。如果它是可复制的,那么你可以进一步指定同步的或异步的模式。
 
  2. TransactionManager:你可以为JBoss缓存查询指定一个与JTA相匹配的事务管理器。如果它发现一个正在进行中的事务上下文,那么它就会参予到该事务中并且相应地执行提交或回滚。
 
  3. 可插入的驱逐策略:该缓存驱逐策略参考该缓存使用的算法来终止它的内容。在JBoss缓存中,你可以经由一个可插入的接口来实现你自己的驱逐策略。JBoss缓存当前与一个基于地域化的LRUEvictionPolicy一起发行。
 
  4. 隔离级别:JBoss缓存使用JDBC风格的语义来实现锁定行为。你不是专门地指定读/写锁,而是为了易于使用起见,可以指定不同的隔离级别。
 
  5. 可插入的CacheLoader:CacheLoader允许你把持续性缓存内容装载回内存中。JBoss缓存当前支持文件装载器和基于SleepyCat和JDBC的装载器。
 
  6. 溢出:通过与一个缓存装载器和一个驱逐策略相联合,它提供了可以在EJB中见到的钝化/激活特性。无论什么时候驱逐一项,它都将被钝化-这样它就会一直是持续的。
 
POJO缓存
 
  JBoss缓存中的POJO缓存模块称作TreeCacheAop。为了使用该POJO缓存,你必须在这些对象被缓冲以前"准备"这些对象(这个过程也称作对象运行时字节码重构)。系统在拦截该POJO操作时正需要这样做。对象运行时字节码重构过程由JBoss AOP库来实现。JBoss AOP允许你经由一个XML文件或注解来指定将被进行字节码重构重构的类。当前,我们仅仅支持JDK-1.4风格的注解(一个特定的JBoss AOP特征)。JDK 5.0注解支持将要在下一个版本中才能出现并且它将使得运行时字节码重构过程几乎是透明的!
 
  TreeCacheAop是一个TreeCache的子类,因此它使用相同的XML文件进行配置并且提供与它的超类部分相同的缓冲功能。该JBoss POJO缓存还提供基于POJO的驱逐策略。
 
应用案例分析
 
  在本文的后面,我们将使用一个"传感器网络监控系统"示例来说明JBoss POJO缓存在提供即时的良好粒度的状态复制和自动保存状态对象关系方面的能力。
 
问题描述
 
  沿着一条高速铁路有一些不同的站点,这里有几千个传感器需要被监视和监控。这些仪器的一些示例包括温度,风和雨传感器-它们对于高速铁路的正常运转至关重要。如果一个特别的传感器正在失灵,那么在监督的系统中的管理器计算机应该向超级用户警报并且关掉该单元并/或调度它-为维护之目的。
 
  既然该操作是任务第一性的,那么就要求监督系统必须是高度可用的-这意味着无论何时在系统中的一台传感器管理器计算机出了问题,超级用户都应该能够无缝地切换到另一台机器以实现监视和积极的管理。因此,所有的管理器计算机必须实时地复制相同的传感器网络状态信息。注意,这种类型系统的特征-也就是,高可用性的要求和几千个(甚至更大数字)元素的存在-在现代网络管理中在其它一些情况下也是普通存在的。
 
  因为传感器网络的层次特性,典型情况下,在管理器方面一般都需要用一个复杂的域对象图来建模该传感器网络。当域对象状态没有被复制(或持续性存储时),对象关系的管理(例如,添加结点和遍历图添加)将由JVM本身来提供,并因此而对终端用户透明。然而,因为Java串行化过程不能够识别对象关系,所以当状态是复制或持续性时,这个看上去相当简单的对象-图关系将会垮掉。结果是,它导致管理器端组件的一个简单的持续性问题都难于实现。
 
  传统地,为了提供完全的持续性能力,必须设计专门的系统来显式地管理对象关系,就象在一个现代对象关系映射(ORM)的解决方案一样。并且在一个传统型实体持续性层风格设计中,你必须做到:
 
  · 外在化关系映射(例如,在一个XML文件中)。
 
  · 把对象分解成一些原型。
 
  · 建立对象身份的概念以保留关系。
 
  · 追踪使用中的字段(如果你想要避免整个的对串行化的代价)。
 
  · 最后,把原始类型装配成对象。
 
  然而,通过使用JBoss POJO缓存来管理你的对象状态,根本不存在上面提及的问题!说得更详细些,好处如下:
 
  · 即时持续性(通过状态复制)-不修改你的域对象模型或指定复杂的对象关系映射。
 
  · 可选的状态持续性也能够保存对象图。
 
  · 可以批量实现良好粒度的复制(或持续性)-为优化网络交通。
 
  如我们在上面描述的,在POJO缓存中的复制和/或持续性方面对用户是完全透明的。注意,对整个簇来说,还存在另一个方面-装载平衡或定位主和/或辅管理器-客户端GUI(对超级用户来说)和传感器都应该连接到其上。在此我们不讨论这些问题,而将只集中于讨论跨管理器的传感器网络状态的复制问题。
 
拓扑与对象建模
 
  举个例子,假设我们有两个站(Tokyo和Yokohama),而且在每一个站中,我们将有一个Wind和一个Rain传感器。对于每一种传感器,存在许多组件需要监控-例如,电源供应和传感器单元本身。我们的目标是高效地监控传感器-这是通过:监视单个项的状态以及它们的整个的状态;能够在运行时刻调入和调出单个传感器而不用重启簇管理器结点。
0
相关文章