WebSphere Application Server 集群机制允许将整个应用服务器(包括 EJB 容器、EJB、Web 容器、Web 模块和 Servlet)作为一个集群进行复制。集群提供了工作负载管理以及 URL 和 EJB 请求故障转移。各个集群成员是该集群中完全相同的副本,它们可以运行于 WebSphere 单元中的节点。集群可以位于相同或不同的节点。Network Deployment 单元可以不包含集群、或者包含多个集群,这取决于该单元的管理需求。有关 WebSphere Application Server 集群的信息,请参见 WebSphere Application Server 联机帮助。
集群拓扑有两种类型,垂直集群或水平集群。垂直集群在同一节点或物理计算机上具有多个集群成员。水平集群在计算单元中的很多计算机的多个节点上都具有集群成员。本文将讨论如图 1 所示的水平集群拓扑。
图 1. 集群拓扑
我们将讨论在设计基于 Web 的应用程序时的三个注意事项:
集群拓扑有两种类型,垂直集群或水平集群。垂直集群在同一节点或物理计算机上具有多个集群成员。水平集群在计算单元中的很多计算机的多个节点上都具有集群成员。本文将讨论如图 1 所示的水平集群拓扑。
我们将讨论在设计基于 Web 的应用程序时的三个注意事项:
实现应用程序文件同步:我们将研究常用的机制是什么,以及如何利用 WebSphere Application Server 6.0 的新特性来实现它。
序列化会话对象:因为会话中包含的对象将在集群内的节点中进行同步,所以必须实现它们的 serializable 接口。本文提供了一个示例,以介绍如何强制完成这项工作。
使用动态缓存:我们将讨论如何使用 WebSphere Dynamic Cache 和 Data Replication Service 在集群中共享 Java? 对象。
实现应用程序文件同步
在企业应用程序的生命周期中,通常可以通过应用修复程序、添加新的 Web 内容或更新应用程序行为来对已部署的应用程序进行更新。一般来说,应用程序提供了允许用户上传在服务器端更改或创建的文件的用户界面。
将下面的场景作为一个示例:用户希望更新 Web 站点徽标图像文件,并且将原始文件作为 .war 文件应用程序的一部分进行存档。该应用程序提供了相关的功能和用户界面,以便用户完成这项任务。然后,用户选择一个新的图像作为 Web 站点的新徽标,并且上传该文件。系统使用新的文件替换原始的文件,并且当用户再次访问他的 Web 站点时,可以看到相应的更改。在单节点环境的应用服务器中,所有这些工作都可以顺利进行。然而,在集群环境中却存在一些问题。
在集群环境中,如图 2 所示,WebSphere Application Network Deployment 服务器中的 Deployment Manager 将接收到用户的上传请求,然后该请求被发送到 Node A。Node A 将执行相应的业务逻辑并使用本地文件系统中的新图像文件替换原始图像文件。然而该集群中其他的成员并不清楚这项更改,其本地副本并没有得到更新。因此,该集群中各个成员之间的这个图像文件就出现了不一致的情况。如果 Node A 因为致命错误而停机,而 Node B 接收到了该请求,那么仍将使用原始的 Web 站点徽标。看上去客户似乎丢失了他所做的更改。
这意味着,当应用程序运行于 WebSphere Application Server 时,需要在集群成员之间同步配置文件、二进制文件和资源文件。有一种机制可以处理上述问题。解决方案是使用共享的文件系统(例如,NFS)或共享的数据库。在这个解决方案中,所有经过更改或更新的文件都位于同一个共享文件系统或同一数据库中。对于共享的文件系统,所有应用程序都使用相同的位置,因此对于这些应用程序来说,任何文件更改都是可见的。对于共享的数据库,应用程序可以从数据库中获得相应的更改。
上述解决方案的缺点包括:
- 共享的文件系统和数据库导致一个新的单点故障。
- 它增加了编程和配置工作的复杂性。
- 它引入了一个新的性能瓶颈。
另一个解决方案是使用细粒度 WebSphere Application Server 应用程序管理 API,在集群的各个成员之间实现文件同步。WebSphere 6.0 中提供了这一特性。WebSphere 6.0 中包含许多改进,从而使得应用程序的部署更加容易并且更加高效。有关详细信息,请参见 WebSphere Application Server 信息中心
WebSphere 6.0 还提供了灵活的应用程序文件管理。它允许应用程序通过以下方式进行更新:
- 替换整个应用程序(例如,整个 .ear 文件)。
- 替换、添加或删除应用程序中的单个模块(例如,.war、EJB.jar 或 .rar 文件)。
- 替换、添加或删除单个文件。
- 替换、添加或删除多个文件。
在对集群中的某个成员上的应用程序文件进行更新之后,将使用另一个新的特性 Rollout Update 对集群中各个成员的文件进行同步。它通过以下方式对应用程序进行更新:
- 保存更新的应用程序配置。
- 停止给定节点上所有的集群成员。
- 通过同步配置和重新启动该节点上停止的集群成员来更新该节点上的应用程序。
让我们回到前面关于 Web 站点徽标更新的示例。在这个场景中,徽标的更新和同步对于用户来说应该是透明的,无需 WebSphere 管理员进行人工干预。这就意味着,应用程序必须控制应用程序的更新,如替换存档于 ear 文件中的原始文件,并在集群的成员之间执行文件同步。您可以通过调用 WebSphere 提供的 Java Management Extensions (JMX) 接口来完成这项任务。JMX 是一项 Java 应用程序资源管理标准。有关 JMX 的详细信息,请参见 JMX Web 站点
应用程序在接收到用户上传的文件之后,它将调用 File Updater 以构造增量 EAR 文件。这个增量 EAR 文件是一个存档文件,它具有与完整的应用程序 ear 文件相同的结构。增量 EAR 文件和完整的应用程序 EAR 文件之间的区别在于,该增量 EAR 文件仅包含要进行更新的文件。File Updater 将构建这个增量 EAR。它可以是封装了增量 EAR 生成逻辑的简单 Java 类,或者是添加了验证逻辑和生成文件的相关复杂组件。
序列化会话对象
使用集群方式的应用程序可以提高系统的可靠性和可用性。然而,这也引入了一些挑战,如会话管理。HTTP 会话是包括用户特定信息的集合。从用户开始访问到用户最后一次访问结束的这段时间内,由容器对会话进行维护。会话由一系列的会话属性组成。事实上,这些属性都是由系统或开发人员创建的 Java 对象。
在集群环境中,开发人员必须清楚,HTTP 会话可能运行于多个 JVM 中。这些会话属性应该在每个 JVM 中保持一致。否则,当应用程序运行于不同的节点时,相同的输入可能产生不同的结果,这是因为与用户相关的数据在这两个节点中不一致。
WebSphere 为集群方式的应用程序提供了实时的、完全一致的数据共享。然而,前提是必须对所有共享的属性进行序列化和反序列化。当您将 Java 对象放入到会话中并希望在所有的节点之间共享该对象时,需要将这个 Java 对象声明为一个 serializable 接口。下面的代码显示了在将对象放入到会话属性时进行的验证工作。
- public class MySession{
- public static void addObjectToSession(HttpServletRequest req, String key, Object value) {
- HttpSession session = req.getSession(true);
- if(value instanceof Serializable)
- session.setAttribute(key, value);
- else
- throw new NonSerializationException ();
- }
- public MySession() {
- }
- }
在上面的示例中,您创建了一个名为 MySession 的新类,用来将对象添加到会话中。您可以通过调用 addObjectToSession() 方法来添加它。首先应该检查该对象是否实现了 serializable 接口。如果已经实现,可以随后将这个对象添加到当前的 Http 会话中。否则,将会出现 NonSerializationException。有些时候,在运行于另一个 JVM 中时,会话属性中包含的信息无关紧要,如文件的绝对目录。在这种情况下,通过将其声明为瞬态属性可以使得这些字段不使用集群方式。
使用动态缓存
如上所述,将应用程序数据保存在中央数据库中可以确保在集群环境中写入和一致地读取数据。这种解决方案的缺点是,数据库服务器引入了新的单点故障 (SPOF),并且不适合那些需要高性能的应用程序。另一种解决方案是使用 WebSphere Dynamic Cache 和 Data Replication Service (DRS)。您可以在基于内存的对象缓存的方式下,通过共享整个集群中某些服务器上的对象,来实现这个解决方案。图 4 显示了带 Data Replication Service 的 WebSphere Dynamic Cache 的体系结构。
WebSphere Dynamic Cache 是面向 J2EE 体系结构和缓存对象的解决方案。表示层中 Web 服务、Servlet 和 JSP 的输出、WebSphere 命令类以及 Java 对象都可以使用应用程序编程接口 (API) 进行缓存,或者声明一些缓存策略并将其添加到应用程序中。
Data Replication Service (DRS) 是用于复制数据的 WebSphere Application Server 内部组件。DRS 使得集群中的各个服务器都可以使用会话管理、动态缓存和无状态会话 Bean 的数据。动态缓存可以利用应用服务器中的 DRS 在集群的各个服务器中复制缓存的数据。在集群范围内传输数据失效通知,以保持数据的一致性和有效性。图 5 显示了如何使用动态缓存和 DRS 在集群中共享应用程序数据。
首先,应用程序运行于 Server One,并通过调用 DistributedMap API 将 Object A 放入其本地缓存中。通过合适的配置,DRS 可以在整个集群范围内复制缓存的对象并保持缓存数据的一致性。因此,将 Object A 复制到 Server Two 的本地缓存。当应用程序运行于 Server Two(假如 Server One 遇到问题或根据负载平衡策略将事务提交到 Server Two)时,应用程序可以从 Server Two 的本地缓存中获得 Server One 的 Object A。
WebSphere Application Server 通过使用缓存实例存储和管理缓存的 Java 对象。缓存实例还可以用于对相关的对象进行逻辑分组。特定实例的缓存中存储的对象不会受到其他缓存实例的影响。如上所述,DistributedMap 公共接口使得应用程序可以直接访问缓存实例。
应用程序可以存储和检索任何实现了 java.util.Map 接口的对象。您所缓存的任何其他 Java 对象都必须实现 java.io.Externalizable 或 java.io.Serializable 接口。集群中的服务器可以通过使用其 JNDI 名称来访问缓存实例。这些服务器必须位于同一个复制域。下面的代码示例显示了应用程序如何通过其 JNDI 名称查找缓存实例,将对象放入缓存实例中,并稍后对其进行检索。
- Import javax.naming.InitialContext;
- Import com.ibm.websphere.cache.DistributedMap; ... InitialContext context=new InitialContext();
- DistributedMap map=(DistributedMap)context.lookup("cache/example_cache_instance");
- map.put("cache_id", yourJavaObject);
- YourJavaObject obj=(YouJavaObject)map.get("cache_id");
结束语
本文讨论了设计运行于 WebSphere 集群环境的应用程序时需要考虑的三个方面。存储于文件系统的应用程序数据应当在每个集群服务器中保存一致。针对这个需求的解决方案是使用共享的文件系统或共享的数据库。使用细粒度文件更新特性,您可以在集群范围内拥有更灵活的应用程序文件,并避免引入新的单点故障。会话管理是 Web 应用程序的一个重要的考虑事项。您应该考虑进行对象序列化和反序列化,以便在集群范围内进行共享。您可以使用自已定义的类将对象封装到会话中,然后同时执行验证。您还可以通过使用 WebSphere Dynamic Cache 和 Data Replication Service 实现集群范围内应用程序数据的共享,这将显著地提高应用程序的性能。
【编辑推荐】