WebLogic 集群中的通讯(二)

文章参考Oracle官方文档。 https://docs.oracle.com/middleware/1213/wls/CLUST/features.htm#CLUST697

使用IP套接字的对等通信
IP套接字提供了一种简单的高性能机制,用于在两个应用程序之间传输消息和数据。群集的WebLogic Server实例将IP套接字用于:
访问部署到另一台计算机上另一个群集服务器实例的非群集对象。
在主服务器实例和辅助服务器实例之间复制HTTP会话状态和有状态会话EJB状态。
访问驻留在远程服务器实例上的群集对象。

正确的套接字配置对于WebLogic Server群集的性能至关重要。两个因素决定了WebLogic Server中套接字通信的效率:
-服务器实例主机系统是使用本机套接字还是纯Java套接字读取器实现。
-对于使用纯Java套接字读取器的系统,是否将服务器实例配置为使用足够的套接字读取器线程。

纯Java与本机套接字读取器实现
尽管套接字读取器线程的纯Java实现是对等通信的可靠且可移植的方法,但是对于WebLogic Server群集中的重型套接字使用,它不能提供最佳性能。使用纯Java套接字读取器,线程必须主动轮询所有打开的套接字,以确定它们是否包含要读取的数据。换句话说,套接字读取器线程始终是“繁忙”的轮询套接字,即使套接字没有要读取的数据也是如此。这种不必要的开销会降低性能。

服务器实例的开放套接字数多于套接字读取器线程数时,性能问题会放大—每个读取器线程必须轮询多个打开的套接字。当套接字读取器遇到无效的套接字时,它将等待超时,然后再为另一个套接字服务。在此超时期间,活动套接字可能不被读取,而套接字读取器轮询不活动的套接字,如图

WebLogic 集群中的通讯(二)

为了获得最佳的套接字性能,请将WebLogic Server主机配置为对您的操作系统使用本机套接字读取器实现,而不是纯Java实现。本机套接字读取器使用效率更高的技术来确定套接字上是否有要读取的数据。使用本机套接字读取器实现,读取器线程不需要轮询不活动的套接字,它们仅服务于活动的套接字,并且当给定的套接字变为活动状态时,会立即(通过中断)通知它们。

Applet无法使用本机套接字读取器实现,因此套接字通信效率有限。

配置Java套接字实现的读取器线程
如果确实使用纯Java套接字读取器实现,则仍可以通过为每个服务器实例配置适当数量的套接字读取器线程来提高套接字通信的性能。为了获得最佳性能,WebLogic Server中的套接字读取器线程数应等于潜在的最大已打开套接字数。此配置避免了读取器线程必须为多个套接字提供服务的情况,并确保立即读取套接字数据。

要确定群集中服务器实例的读取器线程的正确数量,请参阅以下部分,确定潜在的套接字使用情况。
确定潜在的套接字使用量
每个WebLogic Server实例都可以为群集中的每个其他服务器实例打开一个套接字。但是,在给定时间使用的实际最大套接字数取决于群集的配置。实际上,集群系统通常不会为每个其他服务器实例打开套接字,因为对象是均匀部署到集群中的每个服务器实例的。

如果您的集群使用内存中的HTTP会话状态复制,并且您均匀地部署了对象,则每个服务器实例最多只能打开两个套接字,如图

WebLogic 集群中的通讯(二)

通过套接字进行客户端通信
集群的客户端使用套接字读取器线程的Java实现。

WebLogic Server允许您配置服务器关联负载平衡算法,以减少Java客户端应用程序打开的IP套接字的数量。客户端访问服务器实例上的多个对象将使用单个套接字。如果对象失败,则客户端将故障转移到已具有打开套接字的服务器实例(如果可能)。在旧版本的WebLogic Server中,在某些情况下,客户端可能会打开群集中每个服务器实例的套接字。
为了获得最佳性能,请在运行客户端的Java虚拟机(JVM)中配置足够的套接字读取器线程。

群集范围内的JNDI命名服务
非群集WebLogic Server服务器实例的客户端通过使用符合JNDI的命名服务来访问对象和服务。JNDI命名服务包含服务器实例提供的公共服务列表,以树结构组织。WebLogic Server实例通过将代表服务的名称绑定到JNDI树中来提供新服务。客户端通过连接到服务器实例并查找服务的绑定名称来获取服务。

群集中的服务器实例利用群集范围内的JNDI树。群集范围内的JNDI树类似于单个服务器实例JNDI树,只要该树包含可用服务列表即可。但是,除了存储本地服务的名称之外,整个集群范围的JNDI树还存储由集群中其他服务器实例的集群对象(EJB和RMI类)提供的服务。

群集中的每个WebLogic Server实例都创建并维护逻辑范围内的JNDI树的本地副本。以下各节描述如何维护整个集群范围的JNDI树,以及如何避免在集群环境中可能发生的命名冲突。

WebLogic Server如何创建群集范围的JNDI树
群集中的每个WebLogic Server都构建并维护其自己的群集范围的JNDI树的本地副本,该副本列出了群集中所有成员提供的服务。创建集群范围内的JNDI树的起点是每个服务器实例的本地JNDI树绑定。随着服务器实例启动(或将新服务动态部署到正在运行的服务器实例中),服务器实例首先将这些服务的实现绑定到本地JNDI树。仅当不存在其他同名服务时,该实现才绑定到JNDI树中。

服务器实例成功将服务绑定到本地JNDI树后,将对使用复制感知存根的群集对象执行其他步骤。将群集对象的实现绑定到本地JNDI树之后,服务器实例将对象的存根发送到群集的其他成员。群集的其他成员监视多播或单播地址,以检测远程服务器实例何时提供新服务。

WebLogic 集群中的通讯(二)

更新本地JNDI绑定的方式有以下两种:

-如果群集服务尚未绑定在本地JNDI树中,则服务器实例将一个新的副本感知存根绑定到本地树中,以指示对象X在服务器A上的可用性。服务器B和D将在以下位置更新其本地JNDI树:之所以采用这种方式,是因为群集对象尚未部署在那些服务器实例上。

-如果服务器实例已经具有可识别群集的服务的绑定,它将更新其本地JNDI树,以指示该服务的副本在服务器A上也可用。服务器C将以这种方式更新其JNDI树。已经对集群对象X具有绑定。

通过这种方式,集群中的每个服务器实例都会创建自己的集群范围的JNDI树副本。当服务器C宣布对象X已绑定到其本地JNDI树中时,将使用相同的过程。接收到所有广播消息之后,集群中的每个服务器实例将具有相同的本地JNDI树,这些树指示对象在服务器A和C上的可用性,

WebLogic 集群中的通讯(二)

JNDI命名冲突是如何发生的
当服务器实例尝试绑定使用与JNDI树中已经绑定的非集群服务同名的非集群服务时,会发生简单的JNDI命名冲突。当服务器实例尝试绑定使用已在JNDI树中绑定的非群集对象的名称的群集对象时,就会发生群集级JNDI冲突。

当这些服务绑定到本地JNDI树时,WebLogic Server会检测到(非集群服务的)简单命名冲突。通过多播或单播发布新服务时,可能会发生群集级JNDI冲突。例如,如果将固定的RMI对象部署在群集中的一个服务器实例上,则不能在另一个服务器实例上部署同一对象的副本感知版本。

如果群集中的两个服务器实例尝试使用相同的名称绑定不同的群集对象,则这两个实例都将成功在本地绑定对象。但是,由于JNDI命名冲突,每个服务器实例都将拒绝将另一个服务器实例的副本感知存根绑定到JNDI树中。这种类型的冲突将一直存在,直到关闭两个服务器实例之一,或者直到其中一个服务器实例取消部署群集对象为止。如果两个服务器实例都尝试部署具有相同名称的固定对象,也可能发生相同的冲突。

均匀部署以避免集群级JNDI冲突
为避免群集级JNDI冲突,必须将所有可感知副本的对象均匀地部署到群集中的所有WebLogic Server实例。在WebLogic Server实例之间进行不平衡的部署会增加启动或重新部署期间JNDI命名冲突的可能性。它还可能导致集群中的处理负载不平衡。

如果必须将特定的RMI对象或EJB固定到单个服务器实例,请不要在整个集群中复制该对象的绑定。

WebLogic Server如何更新JNDI树
当删除群集对象(从服务器实例取消部署)时,对JNDI树的更新的处理与添加新服务时执行的更新类似。取消部署该服务的服务器实例将广播一条消息,指示它不再提供该服务。同样,群集中观察到多播或单播消息的其他服务器实例将更新其JNDI树的本地副本,以指示该服务在取消部署对象的服务器实例上不再可用。

一旦客户端获得了副本感知存根,群集中的服务器实例就可以继续添加和删除群集对象的主机服务器。随着JNDI树中的信息发生变化,客户端的存根也可能会更新。随后的RMI请求包含必要的更新信息,以确保客户端存根保持最新状态。

客户端与群集范围内的JNDI树的交互
连接到WebLogic Server群集并查找群集对象的客户端将获得该对象的副本感知存根。该存根包含承载对象实现的可用服务器实例的列表。存根还包含用于在其主机服务器之间分配负载的负载平衡逻辑。