|
WebLogic Server 群集实现了两个重要功能:负载平衡和故障转移。下列部分提供的信息有助于架构师和管理员配置满足特定 Web 应用程序各种需求的群集:
群集中的 WebLogic Server 实例使用两种基本网络技术互相通信:
WebLogic Server 使用 IP 多播和套接口通信的方式会影响群集的配置方式。
IP 多播是一种简单的广播技术,使多个应用程序能够“订阅”某个给定的 IP 地址和端口号,并监听消息。多播地址是一个介于 224.0.0.0 到 239.255.255.255 之间的 IP 地址。
| 注意: | WebLogic Server 使用的默认多播值为 239.192.0.0。不应使用 x.0.0.1 范围内的多播地址。 |
IP 多播向应用程序广播消息,但是不能保证这些消息真正被接收到。如果应用程序的本地多播缓冲区已满,则新的多播消息则无法写入该缓冲区,当消息被“丢弃”时,也不会通知该应用程序。因为此限制,所以 WebLogic Server 实例允许存在偶尔丢失通过 IP 多播广播的消息的可能性。
WebLogic Server 对于群集中服务器实例之间的所有一对多通信均使用 IP 多播。此类通信包括:
因为多播通信控制着与检测故障和维护群集范围的 JNDI 树(如群集范围的 JNDI 命名服务中所述)相关的重要功能,所以确保群集配置和网络拓扑结构不干扰多播通信是极为重要的。以下部分提供了有关在群集中避免多播通信出现问题的指南。
在很多部署中,群集服务器实例都位于一个子网中,从而确保了多播消息的可靠传输。但是,您可能希望将 WebLogic Server 群集分布在广域网(Wide Area Network,简称 WAN)中的多个子网中来增加冗余性,或者在一个更大的地理区域内分布群集服务器实例。
如果选择将群集分布在 WAN 上(或跨多个子网),则请对网络拓扑结构进行计划和配置,以确保多播消息可以可靠传输到群集中的所有服务器实例。具体来说,您的网络必须满足下列要求:
| 注意: | 除了上述多播要求之外,在 WAN 上分布 WebLogic Server 群集可能还需要一些网络工具。例如,您可能想配置负载平衡硬件来确保客户端请求以最高效的方式指向服务器实例(以避免不必要的网络跃点)。 |
尽管可以使多播流量以隧道方式通过防火墙,但是对于 WebLogic Server 群集不推荐此方法。请将每个 WebLogic Server 群集视为向 Web 应用程序的客户端提供一个或多个独特服务的逻辑单元。不要在不同的安全区域之间拆分此逻辑单元。另外,可能延迟或中断 IP 流量的任何技术都可能会因为心跳丢失而生成错误故障,从而干扰 WebLogic Server 群集的运行。
尽管多个 WebLogic Server 群集可以共享一个 IP 多播地址和端口,但是其他应用程序不应广播或订阅您的一个或多个群集使用的多播地址和端口。就是说,如果承载群集的一台或多台计算机同时承载着使用多播通信的其他应用程序,则请确保这些应用程序使用的多播地址和端口与该群集不同。
与其他应用程序共享群集多播地址会强制群集服务器实例处理不必要的消息,从而导致不必要的开销。共享多播地址还会使得 IP 多播缓冲区超载,并延迟 WebLogic Server 心跳信号的传输。这样的延迟会导致将 WebLogic Server 实例标记为失效,这仅仅是因为未及时收到其心跳信号。
因为上述原因,所以要分配一个专门的多播地址用于 WebLogic Server 群集,并确保该地址可以支持使用该地址的所有群集的广播流量。
如果群集中的服务器实例未及时处理传入的消息,则可能会导致网络流量增加,这些流量包括 NAK 消息和心跳重新传输。网络上重复传输多播数据包的现象称为“多播风暴”,它可能会加大网络和相连站的负担,从而可能导致端站挂起或失败。增大多播缓冲区的大小可能会提高公告传输和接收的速率,防止发生多播风暴。请参阅配置多播缓冲区大小。
IP 套接口提供了一种用于在两个应用程序之间传输消息和数据的简单的、高性能的机制。群集 WebLogic Server 实例将 IP 套接口用于下列用途:
| 注意: | WebLogic Server 中 IP 套接口的使用会扩展到群集场景之外 - 所有 RMI 通信都通过使用套接口进行,例如当某个远程 Java 客户端应用程序访问某个远程对象时。 |
正确的套接口配置对于 WebLogic Server 群集的性能而言至关重要。两个因素决定着 WebLogic Server 中套接口通信的效率:
尽管套接口读取器线程的纯 Java 实现是一种可靠的、可移植的端到端通信方法,但是它不能为 WebLogic Server 群集中套接口的频繁使用提供最佳的性能。使用纯 Java 套接口读取器,线程必须主动轮询所有打开的套接口以确定它们是否包含要读取的数据。换句话说,套接口读取器线程总是在“忙于”轮询套接口,即使这些套接口没有要读取的数据也是如此。这种不必要的开销可能会降低性能。
当服务器实例具有的打开套接口数多于它所拥有的套接口读取器线程(每个读取器线程必须轮询多个打开的套接口)数时,这种性能问题就更为明显了。当套接口读取器遇到非活动套接口时,它会等待直至超时,然后才会向另一个套接口提供服务。在此超时时间段内,当套接口读取器轮询非活动套接口时,某个活动套接口可能变为未读取状态,如下图所示。

为了获得最佳的套接口性能,请将 WebLogic Server 主机配置为使用用于您的操作系统的本地套接口读取器实现,而不是纯 Java 实现。本地套接口读取器使用更为有效的技术来确定套接口上是否具有要读取的数据。使用本地套接口读取器实现,读取器线程不需要轮询非活动套接口 - 它们只为活动套接口提供服务,当某个给定套接口变为活动状态时,它们将立即收到通知(通过中断)。
| 注意: | Applet 不能使用本地套接口读取器实现,因此在套接口通信方面的效率有限。 |
有关如何配置 WebLogic Server 主机使其使用用于您的操作系统的本地套接口读取器实现的说明,请参阅在承载服务器实例的计算机上配置本地 IP 套接口读取器。
如果一定要使用纯 Java 套接口读取器实现,仍然可以通过为每个服务器实例配置适当数量的套接口读取器线程的方式,来改善套接口通信的性能。为了获得最佳的性能,WebLogic Server 中的套接口读取器的线程数应该等于可能打开的最多套接口数。此配置会避免出现一个读取器线程必须为多个套接口提供服务的情况,从而确保立即读取套接口数据。
要确定群集中服务器实例的适当读取器线程数,请参阅下面部分,确定可能的套接口使用情况。
有关如何配置套接口读取器线程的说明,请参阅在承载服务器实例的计算机上设置读取器线程数。
每个 WebLogic Server 实例都有可能为群集中任何其他的服务器实例打开一个套接口。但是,在某个给定时间使用的实际最大套接口数取决于群集的配置。实际上,群集系统通常不会为任何其他服务器实例打开套接口,因为对象是均匀部署到群集中每个服务器实例的。
如果群集使用内存中 HTTP 会话状态复制,并且对象是均匀部署的,则每个服务器实例可能最多只会打开两个套接口,如下图所示。

此示例中的两个套接口用于在主服务器实例和次级服务器实例之间复制 HTTP 会话状态。因为 WebLogic Server 使用分配优化来访问群集对象,所以对于访问这些对象来说套接口不是必需的。(这些优化在共存对象的优化中进行了描述。)在此配置中,默认套接口读取器线程配置就足够了。
“固定”服务(在某一时间仅在一个服务器实例上处于活动状态的服务)的部署可能会增加套接口的使用量,因为服务器实例可能需要打开附加的套接口来访问固定的对象。(这种可能性仅在某个远程服务器实例真正访问该固定对象时才会消失。)下图显示了将非群集 RMI 对象部署到服务器 A 的可能结果。

在此示例中,每个服务器实例在某个给定时间最多可能会打开三个套接口,以允许 HTTP 会话状态复制和访问服务器 A 上的固定 RMI 对象。
| 注意: | 对于多层群集架构中的 Servlet 群集,可能还需要附加套接口,如多层架构的配置注意事项中所述。 |
WebLogic Server 允许您配置服务器关系负载平衡算法,这些算法会减少 Java 客户端应用程序打开的 IP 套接口数。访问一个服务器实例上多个对象的客户端将使用一个套接口。如果某个对象失败,该客户端将故障转移到已经对其打开套接口的服务器实例(如果可能)。在较旧版本的 WebLogic Server 中,在某些情况下,客户端可能会对群集中的每个服务器实例都打开一个套接口。
为了获得最佳的性能,请在运行客户端的 Java 虚拟机 (JVM) 中配置足够的套接口读取器线程。有关说明,请参阅在客户端计算机上设置读取器线程数。
非群集 WebLogic Server 服务器实例的客户端使用兼容 JNDI 的命名服务访问对象和服务。JNDI 命名服务包含服务器实例提供的公共服务的列表,该列表以树结构组织。WebLogic Server 实例通过将代表某项服务的名称绑定到 JNDI 树来提供新服务。客户端通过连接服务器实例并查找服务的绑定名称来获得服务。
群集中的服务器实例使用群集范围的 JNDI 树。从包含可用服务列表这个层面来看,群集范围的 JNDI 树与单个服务器实例的 JNDI 树相似。但除了存储本地服务的名称之外,群集范围的 JNDI 树还存储着群集中其他服务器实例中的群集对象(EJB 和 RMI 类)提供的服务。
群集中的每个 WebLogic Server 实例都会创建并维护逻辑群集范围 JNDI 树的本地副本。下列部分描述了如何维护群集范围的 JNDI 树,以及如何避免在群集环境中可能发生的命名冲突。
| 警告: | 不要将群集范围的 JNDI 树用作应用程序数据的持久性机制或缓存机制。尽管 WebLogic Server 会将群集服务器实例的 JNDI 条目复制到群集中的其他服务器实例,但如果原始实例失效的话,这些条目将从群集中删除。另外,在 JNDI 树中存储大量对象可能会使得多播流量超载,并且会干扰群集的正常运行。 |
群集中的每个 WebLogic Server 都会生成并维护它自己的群集范围 JNDI 树本地副本,其中列出了群集的所有成员提供的服务。群集范围 JNDI 树的创建首先从每个服务器实例的本地 JNDI 树绑定开始。当服务器实例启动时(或新服务动态部署到正在运行的服务器实例时),该服务器实例首先会将这些服务的实现绑定到本地 JNDI 树。仅当不存在任何同名的其他服务时,实现才会绑定到 JNDI 树。
| 注意: | 当您启动群集中的受管服务器时,服务器实例会在 ClusterMBean 中的 MemberWarmupTimeoutSeconds 参数指定的预热时间过后,通过监听心跳来标识群集中正在运行的其他服务器实例。默认预热时间为 30 秒。 |
服务器实例将服务成功绑定到本地 JNDI 树后,将针对使用副本感知存根控件的群集对象执行其他步骤。将群集对象的实现绑定到本地 JNDI 树之后,服务器实例会将该对象的存根控件发送到群集的其他成员。群集的其他成员监视多播地址,以检测远程服务器实例何时提供新服务。

在上图中,服务器 A 已将群集对象 X 的实现成功绑定到其本地 JNDI 树中。因为对象 X 加入了群集,所以它会向群集的所有其他成员提供此服务。服务器 C 仍然在绑定对象 X 的实现。
群集中监听该多播地址的其他服务器实例注意到,服务器 A 提供了一项群集对象 X 的新服务。然后这些服务器实例更新它们的本地 JNDI 树以包括该项新服务。
按照上述方式,群集中的每个服务器实例都创建了自己的群集范围 JNDI 树副本。当服务器 C 公告对象 X 已经绑定到其本地 JNDI 树时,将使用同样的过程。收到所有广播消息之后,群集中的每个服务器实例将具有相同的本地 JNDI 树,该树指示服务器 A 和 C 上存在可用的对象,如下所示。

| 注意: | 在实际的群集中,对象 X 将均匀部署,可以调用该对象的实现将在所有四个服务器实例中都可用。 |
当服务器实例尝试绑定某项非群集服务,而该服务使用的名称与已绑定到 JNDI 树的某项非群集服务相同时,则会发生简单 JNDI 命名冲突。当服务器实例尝试绑定某个集群对象,而该对象使用的是已绑定到 JNDI 树的某个非群集对象的名称时,则会发生群集级别的 JNDI 冲突。
当(非群集)服务绑定到本地 JNDI 树时,WebLogic Server 会检测这些服务的简单命名冲突。当通过多播通告新服务时,可能会发生群集级别的 JNDI 冲突。例如,如果您在群集的一个服务器实例上部署固定的 RMI 对象,则不能在另一个服务器实例上部署同一对象的副本感知版本。
如果群集中的两个服务器实例尝试绑定使用相同名称的不同群集对象,两个实例则都会成功本地绑定该对象。但是,由于 JNDI 命名冲突,每个服务器实例都无法将另一个服务器实例的副本感知存根控件绑定到 JNDI 树中。在两个服务器实例的其中一个关闭之前,或者其中一个服务器实例取消部署该群集对象之前,这种类型的冲突将一直存在。如果两个服务器实例尝试部署具有相同名称的固定对象,也可能发生同样的冲突。
要避免群集级别的 JNDI 冲突,必须将所有副本感知对象均匀部署到群集中的所有 WebLogic Server 实例。各 WebLogic Server 实例的部署不平衡现象将增加启动或重新部署期间发生 JNDI 命名冲突的概率。这样可能会导致群集中不平衡的负载处理。
如果必须将特定的 RMI 对象或 EJB 固定到单个的服务器实例,则不要在群集中复制该对象的绑定。
删除群集对象(从服务器实例取消部署)时,JNDI 树的更新处理方式与添加新服务时执行更新的方式相似。在其中取消部署服务的服务器实例将广播消息,表明它不再提供该服务。同样,群集中观测该多播消息的其他服务器实例会更新其本地的 JNDI 树副本,以表明该服务在取消部署该对象的服务器实例上不再可用。
客户端获得副本感知存根控件之后,群集中的服务器实例即可以继续添加和删除群集对象的主机服务器了。当 JNDI 树中的信息发生变化时,客户端的存根控件可能也会更新。后续的 RMI 请求包含了确保客户端存根控件保持最新状态所需的信息。
连接 WebLogic Server 群集并查找群集对象的客户端获得对象的副本感知存根控件。此存根控件包含了承载该对象的实现的可用服务器实例的列表。该存根控件还包含了用于将负载在其主机服务器中进行分布的负载平衡逻辑。
有关 EJB 和 RMI 类的副本感知存根控件的详细信息,请参阅 EJB 和 RMI 的复制和故障转移。
有关如何在群集环境中实现 WebLogic JNDI,以及如何使您自己的对象可用于 JNDI 客户端的更多详细讨论,请参阅“WebLogic JNDI 编程”中的使用群集环境中的 WebLogic JNDI。
|