级别: 中级 Alan Chambers, IT 咨询专家, IBM
2008 年 3 月 17 日
本文将帮助您了解有关 IBM® WebSphere® Extended Deployment V6.1 的 ObjectGrid 组件的一些基本概念,介绍如何将 ObjectGrid 用作内存分布式数据库(几种可用模式之一)来构建一个可扩展的、弹性的示例配置,并帮助您着手构建可以利用 ObjectGrid 功能的解决方案。
来自 IBM WebSphere Developer Technical Journal。
引言
您是否:
- 具有这样的应用程序:需要对大量数据进行高速访问,对于此要求,传统的数据库速度根本无法满足需要?
- 需要缓存数据库或其他后端数据存储区中的数据,并需要以其他方式无法达到的速度访问这些数据?
- 具有可以拆分为多个部分的应用程序,对不同的数据执行并行操作,使用网格解决方案非常理想?
- 需要比传统的数据库复制更快的速度在相距遥远的位置之间快速传播应用程序数据?
如果对上述问题的回答是“是”,那么答案就是使用 ObjectGrid。
本文介绍了 IBM WebSphere Extended Deployment V6.1 的 ObjectGrid 组件,概括了其功能,同时还详细介绍了如何设置简单的 ObjectGrid 配置并将其连接到测试应用程序。您还将了解到如何证实 ObjectGrid 提供的可伸缩性和故障转移功能。
虽然此处编写的示例程序将运行在独立的 Windows® 系统上,但您可以方便地调整该示例程序,使之运行于任何受支持的平台上。本文假定您仅具有 Java™ 和 Windows 操作系统的应用知识。尽管这些示例程序没有 Java 也可以运行,但要使用这些示例程序,熟悉 Eclipse 中的 Java 开发将非常有益。
什么是 ObjectGrid?
ObjectGrid 是一个用于 Java 对象的分布式内存数据存储区,专门针对可伸缩性、弹性和高性能而设计。ObjectGrid 具有多种应用程序用途,如:
- 传统数据库的高性能备选方案,提供了对仅在内存中保存的数据的单一一致副本的多线程或进程的共享访问。
- 对持久保存在其他系统(传统数据库、企业应用程序等)中的数据的高性能缓存。
- 真正的网格处理,其中应用程序跨多个进程分布,使执行始终与数据共存,从而提供进程内数据访问性能。
最新版本的 ObjectGrid 突出了其在多个领域作为传统数据库备选方案的有效性,同时还提供了简化的配置选项。
ObjectGrid 是 WebSphere Extended Deployment V6.1(以下称为 Extended Deployment)的一个组件,既可以通过购买完整的 Extended Deployment 产品获得,也可以购买名为 WebSphere Extended Deployment Data Grid 的组件。它可作为 WebSphere Application Server 或 WebSphere Extended Deployment 的组成部分安装、独立于应用服务器使用,或在任何其他 Java 应用服务器中运行。
ObjectGrid 以客户端服务器模式运行时的工作方式
本文的目的是创建以上列出的第一种可能用途的示例:实现一个分布式内存数据库,其数据跨多个服务器实例分布并且可从多个客户端进程中访问。
在以前版本的 ObjectGrid 中,这需要通过使用静态配置来实现,在此情况下,有关数据和副本位置的详细信息是在配置文件中指定的。但是,版本 6.1 引入了替代方案动态配置,有关数据和副本的放置留给 ObjectGrid 自己决定,并且可以随着时间的推移根据服务器实例添加到拓扑中或从中删除而动态更改。这些决定可以完全留给 ObjectGrid,也可以就存放位置定义一些规则;例如,确保任何数据都至少有一个副本放置在地理位置不同的另外一个位置,以供灾难恢复之用。
对于动态配置,附加的 ObjectGrid 组件 Catalog Server 可针对整个拓扑做出放置和其他决定。(本文中的这一示例使用了动态配置。)
数据在哪里,如何访问它?
ObjectGrid 访问和存储数据的最简单方法是使用 ObjectMap,ObjectMap 从根本上说是一个 Java 映射。数据的每一项都与一个键关联,并且该键和数据可以是任何 Java 对象。例如,要使用 Java 对象“myKey”作为键,将名为“myData”的新项插入名为“myMap”的映射中,您可以这样编码:
myMap.put(myKey, myData);
要检索它,则可以这样编码:
Object myResultData = myMap.get(myKey);
数据被存储在 BackingMap 中的服务器上,缺省情况下,每个客户端还有一个本地 BackingMap,以容纳它已经访问过的任何数据。但是,应用程序实际上访问的是 ObjectMap,这是在事务启动时自动创建的。此 ObjectMap 仅在该事务的生命周期内存在;当提交事务时,将把所有更新写入到本地 BackingMap——并且还将写入到服务器上的 BackingMap,然后其他客户端也可以访问更新的数据。此过程如图 1 中所示。
图 1. 两个应用程序在访问 ObjectGrid 中的数据
在此示例中:
- 两个应用程序(App1 和 App2)正在访问名为“Account Bal”的 Backing Map 中的数据,Account Bal 中包括帐户余额并使用帐户编号(一个四位数的数字字符串)作为其键。
- 每个应用程序都有一个本地 BackingMap,在访问该 BackingMap 时,会将服务器上 BackingMap 中的数据复制到此本地 BackingMap 中。在此示意图中,第一个应用程序 (App 1) 访问了帐户 0007、0012 和 0015 的帐户余额,第二个应用程序 (App 2) 访问了帐户 0004、0007 和 0015。
- 第二个应用程序 (App 2) 正在更新帐户 0015 的帐户余额,但是尚未提交事务。新的帐户余额临时存放在一个 ObjectMap 中。当该应用程序提交事务时,将把新值复制到本地 BackingMap 中,还将复制到服务器上的 BackingMap 中。然后将删除该 ObjectMap。
与传统数据库上提供的设置兼容的并行设置通过使用复制模式和锁定战略,确保了不同风格的应用程序在一致性和性能之间达到了完美的平衡。ObjectGrid 文档中完整地介绍了这些内容(请参阅“参考资料”)。
ObjectGrid 如何实现可伸缩性和弹性
ObjectGrid 中的可伸缩性是通过数据分区实现的,弹性是通过使用复制实现的。
在典型配置中,ObjectGrid 使用从该键中派生的哈希代码作为将数据分为几个分区的基础,然后跨并行运行的服务器实例分布这些分区。例如,包含客户数据的 BackingMap 可以根据客户姓氏进行分区;如果您指定需要 13 个分区,ObjectGrid 可以将以 A 和 B 开头的姓名分配到一个分区中,将以 C 和 D 开头的姓名分配到下一个分区中,依此类推。如果运行三个 ObjectGrid 服务器进程,ObjectGrid 可能会将四个分区放在其中的两个进程上,将五个分区放在另外一个进程上,总共形成 13 个分区,如图 2 中所示。
图 2. 三个服务器上的 13 个分区
此行为是动态的,因此,如果启动一个新服务器,其中的一些现有分区或其副本可能会重新分配到这个新的服务器,同样,分区和副本将被再一次跨所有的可用服务器平均分布,如图 3 中的示例所示。
图 3. 四个服务器上的 13 个分区
 |
示例与现实
在实践中,ObjectGrid 的算法比这更成熟。ObjectGrid 会考虑主要分区和副本的放置位置,并避免不必要地移动分区。在图 3 中,根据副本的配置情况,有可能在新服务器上创建附加副本(未显示),而不是像图例中那样移动主要分区和副本。而且,在缺省情况下,由于分区是基于从这些键中衍生出的哈希代码进行的,因此不会像图例中那样用如此简单的方法与数据关联。 |
|
您需要在配置文件中指定的只是分区的数量,其余的将由 ObjectGrid 完成。在决定需要多少分区和多少服务器方面,应考虑以下因素:
-
数据量:每个 JVM 中的堆都设定了每个服务器实例可以容纳的有限数量限制,因此,数据越多,就会需要更多的服务器容纳这些数据。
-
弹性:通过跨多个服务器分布数据,您可以减少任何一个服务器故障造成的影响。
-
可伸缩性:您需要有足够的分区来使用最初和将来运行的服务器数量。可以将服务器添加到运行的集群中,但是更改分区数量需要重新启动所有的服务器,因此,最好将分区数量设置到足够高,以避免重新启动您的拓扑。
可伸缩性:
将服务器添加到运行的 ObjectGrid 集群这一能力为可伸缩性提供了一个非常灵活的机制。随着负载或数据量的增长,可以添加更多的服务器,并且 ObjectGrid 将跨所有服务器自动重新平衡。类似地,如果一个服务器因某种原因离线,或者发生意外故障,会将该数据重新平衡到其余的服务器上。客户端将与数据所在的服务器直接通信,因此,无需使用本身可能成为瓶颈和限制可伸缩性的路由组件。
由于在 32 位 JVM 上,每个服务器最多可容纳 2GB 的数据(在 64 位 JVM 上更多),并且可以让数百个服务器运行在单一 ObjectGrid 集群中,因此内存中可以容纳大量的数据。
复制和故障转移
为了预防出现进程故障和包含在任何分区中的数据丢失,需要维护这些分区的副本。在可能的情况下,将在另一计算机上的另一个服务器进程上自动分配副本分区。对一个分区中的数据更新时,该副本也将得到更新。如果原始分区(主分区)出现故障,将把它的一个副本提升为新主分区,然后在其他地方创建一个新副本。所有这一切都是实时进行的,对客户端应用程序的唯一影响是,当此进程进行时,某些事务可能会回滚。您可以通过在数量足够多的计算机上指定适当数量的副本,并且让它们在地理位置上分散开(如果还需要灾难恢复)来选择您的 ObjectGrid 的伸缩性有多大。
配置服务器
现在我们介绍一个简单的 ObjectGrid 集群的安装和配置,该集群由 5 个 ObjectGrid 服务器(将用来容纳应用程序数据)和一个 ObjectGrid Catalog Server(一个新组件,用于管理动态配置中的数据存放)组成。您还需要编写和运行两个小客户端应用程序,以访问 ObjectGrid 中的数据,并介绍此配置如何从 ObjectGrid 服务器故障中恢复。
 |
关于示例
此处介绍的示例可用作学习 ObjectGrid 基础知识的教程,也可以作为演示其弹性和可伸缩性的基础。为了清楚和简单起见,此处使用的示例有意设计得非常通俗浅显,并不代表真正的应用程序。您可以将其视为 ObjectGrid 版的“Hello World”程序。 |
|
虽然可以使用其他 JVM,但本文将 ObjectGrid 配置为单独与 IBM Java 5 运行时一起运行。
-
安装 ObjectGrid 运行时文件
如果您具有 WebSphere Extended Deployment V6.1 或 WebSphere Extended Deployment Data Grid V6.1 的完整副本,请将 Data Grid 组件安装在您的文件系统中的方便位置,然后定位 ObjectGrid 目录(图 4)。您可以将 ObjectGrid 目录复制到所希望的任何其他位置,也可以在原位置使用;其内容不以任何方式依赖于其余的 Extended Deployment 安装。
如果您没有该产品版本,则可以下载 ObjectGrid 的评估副本。此版本是一个完整功能的版本,每次可以运行 60 分钟——此后,必须重新启动所有的 ObjectGrid 服务器才能再得到 60 分钟的时间,依此类推,运行次数不限。
图 4. 定位 ObjectGrid 运行时文件
无论您以哪种方法获取 ObjectGrid 文件,都需要将 ObjectGrid 目录的内容放到您的文件系统的某个方便位置。就本文而言,所有的文本和数字都指向 c:\og61 中的 ObjectGrid 目录。
-
下载和安装这些示例
这里为您提供了两个选项:
- 您可以直接继续到下面的步骤,这些步骤解释了如何安装测试 ObjectGrid,并且介绍了如何创建必需的配置文件和批处理文件,并按顺序解释了每一项,还介绍了两个向您的 ObjectGrid 存储数据和从中检索数据的示例应用程序。
- 您还可以下载示例数据包(本文中包括此数据包),然后继续到下一部分,以了解各种文件,而无需实际从头创建这些文件。如果采用这种方法,请下载 dwsample.zip 文件并将其解压缩到 ObjectGrid 所在的根目录中。完成此操作后,该目录结构应与图 5 中所示的类似。
图 5. 示例文件的位置
-
设置环境变量
您必须为 ObjectGrid 设置几个环境变量。有些环境变量可以通过 ObjectGrid\bin 目录中提供的 setupCmdLine 批处理文件(不要修改此文件)来设置,但是您还必须设置 JAVA_HOME 和 PATH。针对本例,为设置该环境,我们从 c:\og61 下的一个名为“dwsample”的目录中运行我们的示例,因此名为 setup.bat 的批处理文件被保存在 c:\og61\dwsample 目录中。如果您尚未进行此操作,请在 c:\og61 下创建一个 dwsample 目录,然后在其中创建该 setup.bat 文件。
此示例使用通过 WebSphere Application Server V6.1 提供的 Java 运行时,它安装在 c:\WAS61 中,但是,您可以使用任何受支持的 Java 运行时,但需要相应地修改 setup.bat。清单 1 显示了此环境的 setup.bat 文件。请记住,您需要编辑此文件,并要考虑到您的 Java 和 ObjectGrid 运行时文件的位置。
清单 1. 设置环境变量的示例批处理文件
@rem
@rem Set the JAVA_HOME environment variable to the Java runtime ObjectGrid will use.
@rem
set JAVA_HOME=c:\WAS61\java\jre
@rem
@rem Add the ObjectGrid and Java bin directories to the PATH
@rem
path=c:\og61\bin;%JAVA_HOME%\bin;%PATH%
@rem
@rem Run SetupCmdLine (in the ObjectGrid bin directory) to set
@rem some more environment variables required by ObjectGrid
@rem
call setupCmdLine.bat |
-
创建 XML 配置文件
要启动 ObjectGrid 服务器,需要提供一个称为 startOgServer.bat 的批处理文件。对于动态配置,您需要提供三个参数:
- 您为此特定服务器实例提供的名称。
- 一个用于指定要创建的 ObjectGrids 的一些详细信息、备份映射等的 XML 文件(ObjectGrid XML 文件)。
- 一个用于指定将应用于在 ObjectGrid XML 文件中定义的备份映射的分区和复制策略的 XML 文件(分区和部署策略 XML 文件)。(如果该部署策略 XML 文件未指定,将假定有一个不带复制的分区。)
对于基本示例,两个 XML 文件可能会相当简单。创建一个其中仅有一个 BackingMap 的 ObjectGrid。为分区和复制指定一些设置,但在其他方面接受所有的缺省设置。如果是这样,可以使用 ObjectGrid XML 文件,如清单 2 中显示的文件。此文件被称为“MyGrid.xml”。此文件仅将您的 ObjectGrid 命名为“MyObjectGrid”,将您的 BackingMap 命名为“MyBackingMap01”。
清单 2. MyGrid.xml
<?xml version="1.0" encoding="UTF-8"?>
<objectGridConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ibm.com/ws/objectgrid/config ../objectGrid.xsd"
xmlns="http://ibm.com/ws/objectgrid/config">
<objectGrids>
<objectGrid name="MyObjectGrid">
<backingMap name="MyBackingMap01" />
</objectGrid>
</objectGrids>
</objectGridConfig> |
第二个 XML 文件显示在清单 3 中,它提供了分区和其他部署策略的详细信息,被称为“MyGridReplication.xml”。
清单 3. MyGridReplication.xml
<?xml version="1.0" encoding="UTF-8"?>
<deploymentPolicy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://ibm.com/ws/objectgrid/deploymentPolicy ../deploymentPolicy.xsd"
xmlns="http://ibm.com/ws/objectgrid/deploymentPolicy">
<objectgridDeployment objectgridName="MyObjectGrid">
<mapSet name="MyMapSet" numberOfPartitions="20"
minSyncReplicas="2" maxSyncReplicas="5"
maxAsyncReplicas="0" numInitialContainers="3">
<map ref="MyBackingMap01" />
</mapSet>
</objectgridDeployment>
</deploymentPolicy> |
这里,您可以看到为名为“MyObjectGrid”的 ObjectGrid(前面的 ObjectGrid XML 文件引用过)指定的 ObjectGrid 部署详细信息,以及对“MyBackingMap01”的引用(与在 ObjectGrid XML 文件中的命名一样)。但是,此映射的部署设置是在 mapSet 标签下指定的,它已经被命名为“MyMapSet”。在需要相同分区和复制设置的 ObjectGrid 中,MapSet 组合了大量的 BackingMap。
这里,您可以看到为名为 MyObjectGrid 的 ObjectGrid(前面的 ObjectGrid XML 文件引用过)指定的 ObjectGrid 部署详细信息,以及对 MyBackingMap01 的引用(与在 ObjectGrid XML 文件中的命名一样)。但是,此映射的部署设置是在 mapSet 标签下指定的,它已经被命名为 MyMapSet。在需要相同分区和复制设置的 ObjectGrid 中,MapSet 组合了大量的 BackingMap。
MapSet 设置在 ObjectGrid 文档中进行了详细的记录,但是,在此示例中,我们指定将数据分为 20 个分区,每个分区至少两个同步副本。这意味着,如果主分区出现故障,始终将有一个最新副本可以接管故障分区,并且当故障发生时,还将存在另外一个副本,因此,永远不会存在只有一个分区数据副本的解决方案——即便间隔很短也不可能。由于同步副本必须在主分区更新的同时更新,因此会影响总体性能,重要一点是不要有太多的同步副本,因此,我们指定最多有 5 个。
使用异步副本是一个备选方案,这可以避免同步副本带来的某些性能开销,但是这不能保证与主分区始终同步。在此示例中未使用异步副本,因此 maxAsynchReplicas 的值被设置为零。
在此示例中,初始容器数量被设置为 3。这意味着在启动 ObjectGrid 实例时,您需要至少有三个 ObjectGrid 服务器运行时才能启动对分区和副本的分配。这可以避免在启动期间 ObjectGrid 服务器可用时,分配(然后移动)分区和副本使目录服务器造成过重的工作负荷。此设置的缺省值是一个大于最少同步副本数的值。
如果您尚未这样做,请如上所示,创建两个 XML 配置文件,即 MyGrid.xml 和 MyGridReplication.xml,然后将它们放到名为 c:\og61\dwsample\config 的新的子目录中。
-
创建批处理文件以启动 ObjectGrid
现在您基本上可以使用 startOgServer.bat 命令来启动您的 ObjectGrid 服务器实例了。但是,因为这需要相当长的命令行,创建一个批处理文件来启动五个服务器中的每个服务器比较方便。例如,要启动第一个服务器实例(被命名为“ogServ1”),您可以创建一个类似于 startsrv1.bat 的批处理文件,如清单 4 中所示。(在该批处理文件中,在一行中输入此命令;为了便于显示,此处分为多行显示)。
清单 4. startsrv1.bat
startOgServer.bat ogServ1 -objectgridFile C:\og61\dwsample\config\MyGrid.xml
-deploymentPolicyFile C:\og61\dwsample\config\MyGridReplication.xml
-catalogServiceEndpoints localhost:2809 |
类似地,创建批处理文件以启动 ogServ2、ogServ3、ogServ4 和 ogServ5,并将所有这些批处理文件都放在 c:\og61\dwsample 目录中。
在类似这样的动态配置中,ObjectGrid 服务器将在 Catalog Server 已经运行时才启动。还可以使用 startOgServer.bat 命令来启动,为了方便起见,还可以创建一个包含此命令的批处理文件。c:\og61\dwsample 目录中的 startcat.bat 文件显示在清单 5 中,启动 Catalog Server(即 cat1)的单一实例。
清单 5. startcat.bat
startOgServer.bat cat1 -catalogServiceEndpoints cat1:localhost:6601:6602 |
-
启动 ObjectGrid
与我们一样使用该动态配置时,您必须至少启动一个 Catalog Server,然后才可以启动任何 ObjectGrid 服务器;如果您尝试先启动后者,则在它试图连接到 Catalog Server 时,将会出现一些 CORBA 错误。因此:
-
请启动命令提示窗口,更改到测试文件所在的目录 (c:\og61\dwsample),然后运行您的 setup.bat 命令以设置这些环境变量:
setup
-
假设在运行时未出现错误,然后可以运行您的 startcat.bat 命令以启动该目录服务器:
startcat
这需要一些时间,在此期间,命令提示窗口中将显示一些信息性消息。当完成启动后,文本的最后几行看起来非常类似于图 6 中所示的内容。
图 6. 表明成功启动 Catalog Server 的消息
-
接下来,运行每个 startsrv?.bat 命令以启动五个 ObjectGrid 服务器:
startsrv1 startsrv2
如此等等。
如果您正在运行个人防火墙,一定要注意任何警告,在这些服务器启动时,要确保该防火墙不会阻止它们与 Catalog Server 之间的通信。在每个组件启动时,命令提示窗口中都会显示一些消息,当它启动后,看起来与图 7 相似。
图 7. 表明成功启动 ObjectGrid Server 的消息
现在,您已经有一个弹性、可伸缩的 ObjectGrid 在运行。这里唯一的不足之处是 Catalog Server,因为您只启动了其中的一个实例。在更加实际的示例中,至少需要在单独的计算机上启动其中的两个实例才能提供自动化的故障转移,从而消除这个依然存在的单点故障。当然,您还要在多个计算机上运行 ObjectGrid 服务器实例。
日志和跟踪信息
在每个组件启动时,您已看到一些信息出现在命令提示窗口中。这些消息的格式非常类似于 WebSphere Application Server 生成的消息,同样,每个服务器实例还将创建 SystemOut.log 和 SystemErr.log 文件。它们在子目录的日志目录下,其名称与相应服务器的名称匹配。还有一个 ffdc 目录(它有第一个故障数据捕获数据)和一个 Catalog Cluster 目录(Catalog Server 日志位于其中)。如果启用了信息跟踪(通过 StartOgServer.bat 命令上的选项),还会生成信息跟踪文件,这些文件的样式也与 WebSphere Application Server 创建的文件样式类似。对于本练习,您不需要启用信息跟踪。
图 8 显示了在启动您的目录和各种 ObjectGrid 服务器实例后的目录结构。
图 8. ObjectGrid 日志和信息跟踪文件的位置
开发 ObjectGrid 客户端应用程序
现在您已经有一个分布式 ObjectGrid,它包含一个称为 MyBackingMap01 的映射,但是未包含任何数据。在其他一些方案中,您可能已经使用所提供的插件接口开发了一个加载器,并且在您的 ObjectGrid XML 文件中引用了它。加载器一般在以下情况中使用:ObjectGrid 被用作容纳某些后端存储区(如数据库)中数据的缓存,并且负责从后端存储区加载数据和向后端存储区传播更新。(这是以前提到的另一种使用模式。)
但是,为了简单起见,我们假定该数据由一个应用程序创建,由另一个应用程序读取;换句话说就是没有外部数据源。为保持这些应用程序极为简单,仅将一系列键下的某些简单数据插入到您的映射中,然后检索。
连接到 ObjectGrid 和您的映射
为了访问您的备份映射,您必须在 ObjectGrid Catalog Server 的帮助下查找它。清单 6 中显示的代码与 Catalog Server 连接(在本地计算机上,使用缺省端口 2809),并使用获取的上下文来获取对 ObjectGrid(MyObjectGrid,与在 ObjectGrid XML 文件中的命名一样)的引用。获取了 ObjectGrid 的会话后,该代码将使用该会话来获取对您已定义的备份映射 (MyBackingMap01) 的 ObjectMap 引用。
清单 6. 通过编码访问 ObjectMap
ObjectGridManager ogMgr = ObjectGridManagerFactory.getObjectGridManager();
ClientClusterContext myCtx = ogMgr.connect("localhost:2809", null, null);
ObjectGrid myOG = ogMgr.getObjectGrid(myCtx, "MyObjectGrid");
Session sess = myOG.getSession();
ObjectMap myMap = sess.getMap("MyBackingMap01"); |
将数据放到您的 ObjectGrid 中
如清单 7 所示,现在可以将一些数据插入到该映射中。该代码将使用编号为从 0 到 199 的整数键插入 200 个值。关联的数据非常简单:字符串“Hello World”附带有该键号。
清单 7. 通过编码将数据插入到 BackingMap 中
int i;
for (i = 0; i < 200; i++) {
sess.begin();
Integer key = new Integer(i);
Object o = myMap.get(key);
if (o == null) {
myMap.put(new Integer(i), "Hello World " + i);
}
sess.commit();
} |
注意,在每次插入之前,需要调用从上面获得的 Session 对象上的 begin() 方法来启动一个新事务,然后在放置该数据之后,方可调用 commit() 方法。该 commit() 导致将相关数据从与该事务相关的 ObjectMap 中复制到该应用程序的本地 BackingMap 中,以及服务器上的 BackingMap 中,其他应用程序可以在其中看到该数据。
不必一直对在该 Session 对象上的 begin() 和 commit() 方法调用进行编码,因为 ObjectGrid 为 Session 事务范围之外的 ObjectMap 上调用的方法提供了自动提交支持。对于这些示例,我们对这些事务进行了明确定义,以便说明这些方法的用途,在更加实际的应用程序方案中,这些方法通常非常必要。
这个简单示例可检查在编写新数据之前当前键中是否已经有一个项,以避免因存在具有此键的数据而发生的异常。
请注意,此处的几个调用可能会生成 Java 异常,因此通常被 try/catch 子句包装。为了清楚起见,此处省略了这一点;但整个示例包含在抛出一般异常的方法中,这可以避免其他情况下可能生成的编译时错误。参见清单 8 中的完整程序。
清单 8. 将数据放入 ObjectGrid (MyOgClientWriter.java) 中的完整应用程序
package ogdemo;
import com.ibm.websphere.objectgrid.ClientClusterContext;
import com.ibm.websphere.objectgrid.ObjectGrid;
import com.ibm.websphere.objectgrid.ObjectGridManager;
import com.ibm.websphere.objectgrid.ObjectGridManagerFactory;
import com.ibm.websphere.objectgrid.ObjectMap;
import com.ibm.websphere.objectgrid.Session;
public class MyOgClientWriter {
public static void main(String[] args) {
try {
ogtest();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void ogtest() throws Exception {
ObjectGridManager ogMgr =
ObjectGridManagerFactory.getObjectGridManager();
ClientClusterContext myCtx =
ogMgr.connect("localhost:2809", null, null);
ObjectGrid myOG = ogMgr.getObjectGrid(myCtx, "MyObjectGrid");
Session sess = myOG.getSession();
ObjectMap myMap = sess.getMap("MyBackingMap01");
int i;
for (i = 0; i < 200; i++) {
sess.begin();
Integer key = new Integer(i);
Object o = myMap.get(key);
if (o == null) {
myMap.put(new Integer(i), "Hello World " + i);
}
sess.commit();
}
System.out
.println("\n\n*** Finished loading data into ObjectMap ***");
}
} |
访问 ObjectGrid 中的数据
访问 ObjectGrid 的备份映射中的数据非常类似于上述用于插入数据的代码。访问 ObjectGrid、Session 和 BackingMap 对象的步骤都是一样的。清单 9 中说明了数据检索。
清单 9. 通过编码访问 ObjectGrid 中的数据,显示分区编号
BackingMap bm = myOG.getMap("MyBackingMap01");
PartitionManager pm = bm.getPartitionManager();
for (i = 0; i < 200; i++) {
Integer key = new Integer(i);
Object o = myMap.get(key);
if (o != null) {
System.out.println("Key " + i
+ " value: " + o.toString()
+ " Partition number: "
+ pm.getPartition(key));
}
} |
为了更加有趣地说明,我们将分配给每个特定数据项的分区编号说明包括在内。该示例还介绍了所使用的自动提交,它替换了显式 Session.begin() 和 Session.commit() 方法调用。
清单 10 显示了完整的客户端应用程序 (MyOgClientReader.java)。
清单 10. 从 ObjectGrid 中访问数据的应用程序 (MyOgClientReader.java)
package ogdemo;
import com.ibm.websphere.objectgrid.BackingMap;
import com.ibm.websphere.objectgrid.ClientClusterContext;
import com.ibm.websphere.objectgrid.ObjectGrid;
import com.ibm.websphere.objectgrid.ObjectGridManager;
import com.ibm.websphere.objectgrid.ObjectGridManagerFactory;
import com.ibm.websphere.objectgrid.ObjectMap;
import com.ibm.websphere.objectgrid.PartitionManager;
import com.ibm.websphere.objectgrid.Session;
public class MyOgClientReader {
public static void main(String[] args) {
try {
ogtest();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void ogtest() throws Exception {
ObjectGridManager ogMgr =ObjectGridManagerFactory.getObjectGridManager();
ClientClusterContext myCtx = ogMgr.connect("localhost:2809", null, null);
ObjectGrid myOG = ogMgr.getObjectGrid(myCtx, "MyObjectGrid");
Session sess = myOG.getSession();
ObjectMap myMap = sess.getMap("MyBackingMap01");
BackingMap bm = myOG.getMap("MyBackingMap01");
PartitionManager pm = bm.getPartitionManager();
int i;
for (i = 0; i < 200; i++) {
Integer key = new Integer(i);
Object o = myMap.get(key);
if (o != null) {
System.out.println("Key "
+ i
+ " value: "
+ o.toString()
+ " Partition number: "
+ pm.getPartition(key));
}
}
}
} |

 |

|
运行客户端应用程序
-
从命令提示符
如果您只想运行本文提供的示例,并进行故障转移试验(后面介绍),则可以使用所提供的批处理文件从命令提示符运行它们来完成此操作。要将一些数据加载到 ObjectGrid 中,请从命令提示符运行以下批处理文件:
writesample.bat
这需要几秒钟时间运行,运行之后,您会看到一条消息“Finished loading data into ObjectMap”(清单 11)。
清单 11. 从 MyClientWriter 应用程序中得到的输出
C:\og61\dwsample>c:\was61\java\bin\java –classpath
myclient.jar;C:\og61\lib\ogclient.jar ogdemo.MyOgClientWriter
[10/07/07 16:34:30:828 BST] 1420142 RuntimeInfo I CWOBJ2604I: The stream query jar file
|--10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- XML error: The previous line is longer than the max of 90 characters ---------|
is not in the class path.
[10/07/07 16:34:35:093 BST] 1420142 ObjectGridImp I CWOBJ1308I: Security of the
ObjectGrid instance MyObjectGrid is disabled.
*** Finished loading data into ObjectMap *** |
要从 ObjectGrid 检索数据,请从命令提示符运行以下批处理文件:
readsample.bat
这也需要一些时间,运行之后,您可以看到,在由前面的程序创建的 BackingMap 中,有一个包含 200 个项的列表,以及与每个项相关的分区编号。清单 12 中列出了该输出的前几行内容。
清单 12. MyOgClientReader 应用程序的一些输出
C:\og61\dwsample>c:\was61\java\bin\java -classpath
myclient.jar;C:\og61\lib\ogclient.jar ogdemo.MyOgClientReader
[10/07/07 16:39:57:640 BST] 1420142 RuntimeInfo I CWOBJ2604I: The stream query jar file
|--10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- XML error: The previous line is longer than the max of 90 characters ---------|
is not in the class path.
[10/07/07 16:40:01:734 BST] 1420142 ObjectGridImp I CWOBJ1308I: Security of the
ObjectGrid instance MyObjectGrid is disabled.
Key 0 value: Hello World 0 Partition number: 0
Key 1 value: Hello World 1 Partition number: 1
Key 2 value: Hello World 2 Partition number: 2
Key 3 value: Hello World 3 Partition number: 3
Key 4 value: Hello World 4 Partition number: 4
Key 5 value: Hello World 5 Partition number: 5
Key 6 value: Hello World 6 Partition number: 6
Key 7 value: Hello World 7 Partition number: 7
Key 8 value: Hello World 8 Partition number: 8
Key 9 value: Hello World 9 Partition number: 9
Key 10 value: Hello World 10 Partition number: 10
Key 11 value: Hello World 11 Partition number: 11
Key 12 value: Hello World 12 Partition number: 12
Key 13 value: Hello World 13 Partition number: 13
Key 14 value: Hello World 14 Partition number: 14 |
-
从 Eclipse 或 Rational Application Developer
如果您正在使用 Eclipse 或基于 Eclipse 的工具(如 IBM Rational® Application Developer)开发客户端应用程序,则需要确保 Java 项目在其构建路径和类路径中具有 ogclient.jar 文件。此文件在 ObjectGrid 的 lib 目录中;在本例中是 c:\og61\lib。
在 Eclipse 中设置构建路径的操作步骤:
- 打开您的 Java 项目的 Properties 面板。
- 从属性列表中选择 Java Build Path。
- 使用 Add External JARs... 将引用添加到 lib 目录的 ogclient.jar 文件中。
完成此步骤后,Properties 对话框应该类似于图 9。
图 9. 在 Eclipse 中设置 Java 构建路径
如果基于 Eclipse 的开发工具被配置为在非 IBM Java 运行时环境中运行,则必须在 JRE 中实现 IBM 提供的一些文件,以避免在 CORBA 实现中出现不兼容现象。ObjectGrid 文档中提供了相关的详细内容。如果已经有 IBM 运行时,在首次测试时,仍应指定一个 IBM 运行时。如果您的 Eclipse 环境运行在另一个 JRE 上,则可以为您启动的应用程序指定一个 IBM 运行时。为此,转到您的应用程序的 Run... 配置对话框,然后选择一个 IBM JRE(您可能需要使用 Installed JREs 按钮在该文件系统中查找 IBM JRE)。
图 10. 在 Eclipse 中设置测试配置以使用 IBM JRE

 |

|
弹性:当进程失败时会发生什么情况?
您可以通过尝试以下操作自行验证分区故障转移有效:
-
在启动 Catalog Server 和每个 ObjectGrid 服务器时,注意操作系统赋予各个进程的进程 ID。在 Windows 中,在启动每个组件和寻找 java.exe 实例时,可以通过查看 Task List 窗口(在 Processes 选项卡上)来完成此操作。在每个组件启动时,都将有两个 Java 进程启动,但是随后将有一个消失;剩下的这个就是实际的服务器进程。
-
运行测试客户端应用程序,将一些数据加载到 ObjectGrid 中,使用一系列键以便将数据放到您的所有分区中。您可以通过运行 writesample.bat 批处理文件或通过运行开发环境中的 MyOgClientWriter 应用程序来完成此操作。
-
运行测试客户端应用程序以查询和列出数据。您可以通过从命令提示符运行 readsample.bat 批处理文件来完成此操作,也可以通过运行 MyOgClientReader 应用程序从您的开发工具中完成此操作。
-
使用 Task Manager 的 End Process 按钮,删除其中一个 ObjectGrid 服务器进程。
-
再次运行测试客户端应用程序以查询和列出数据。注意,这不会丢失任何数据。
-
如果您仍然不放心,可以重新启动您删除的服务器实例,像以前那样记下它的进程 ID,然后删除另外一个进程。重复此操作,直到逐个删除和重新启动所有的进程,自己验证一下该进程的每一步中的数据都没有改动。
请小心,不要删除 Catalog Server 进程——或者与您的 Eclipse 环境相关的任何 Java 进程。在生产环境中,将运行多个 Catalog Server 来提供故障转移,但是,在此示例中只运行了一个实例,因此,如果您删除它,该应用程序将无法再运行。
结束语
本文介绍了使用 ObjectGrid 的几种模式之一:作为内存分布式数据库。设置简单的测试 ObjectGrid 需要的最少配置文件集包括五个服务器和两个小 Java 应用程序,以便将数据插入 ObjectGrid 和从中提取数据。最后学习了如何查看 ObjectGrid 故障转移功能的运行。
虽然 ObjectGrid 还有本文中未介绍到的许多更加高级的功能,但我们希望,本文的介绍为您深入学习有关此高级组件的功能提供一个良好起点。
致谢
作者感谢:
- Jonathan Marshall,IBM UK Software Business 的资深 IT 专家,感谢他在理解 ObjectGrid 方面提供的帮助,还感谢他提供的许多好注意。
- Matthew Perrins,IBM Hursley Lab Services 的资深咨询 IT 专家,感谢他为本文提供的建议,感谢他的支持和鼓励。
- Stuart Foster,IBM UK Software Business 的咨询 IT 专家,感谢他详细审阅了本文并对相关示例进行了实际测试。
- 来自 ObjectGrid 开发部的 Billy Newport 和 Jared Anderson,感谢他们所提供的大力支持。
下载 | 名字 | 大小 | 下载方法 |
|---|
| dwsample.zip | 9 KB | HTTP |
参考资料 学习
获得产品和技术
关于作者  | |  | Alan Chambers 是一名 IBM UK Software Business 的 IT 咨询专家,专门向金融服务部门的客户提供有关 WebSphere 技术方面的建议,他尤其擅长 WebSphere Application Server 和 WebSphere Extended Deployment。在 Alan 就职于 IBM 期间,他不断将重点放在新的编程技术上,他是 90 年代中期 Java 技术的倡导者,还是此前面向对象和 GUI 开发技术的倡导者。多年来,他以 OS/2 操作系统及其 API、Presentation Manager 和 Workplace Shell 子系统方面的专家而闻名,同时还是 OS/2 Restricted Workplace Shell 计划产品的开发人员。 |
对本文的评价
|