您的位置:首页 > 编程语言 > Java开发

Java EE集群技术初探——第七部分(EJB集群的实现)

2008-05-15 13:28 211 查看
EJB集群的实现
EJB是Java EE重要的组成部分,实现EJB的集群也是最具挑战的部分。

EJB技术也来源于分布式计算,可在独立的服务器上运行。Web服务器组件或胖客户端能从其他计算机通过标准RMI/IIOP协议访问EJB组件。调用远程EJB的方法和调用本地Java对象的方法一样。实际上,RMI-IIOP完全实现了对本地/远程调用的透明性。



上图展示了调用远程EJB的机制。当客户端要调用EJB时,不能直接调用EJB,它需要调用称为“存根(stub)”的本地对象,其接口与远程对象一致,充当着远程对象代理作用。Stub负责本地接收方法调用并将其传递到网络另一端的远程EJB上去。Stub在客户端JVM中运行,并通过RMI/IIOP向远程网络查找真实对象。

我们通过了解如何在代码中调用EJB来解释EJB集群的实现。如欲调用EJB,需要:

从JNDI服务器中查找EJBHome存根。

通过EJBHome存根查找或创建EJB对象,返回EJBObject存根。

通过EJBObject存根调用EJB方法。

负载均衡和失败转移可在JNDI查找的时候发生。当通过EJB存根(无论EJBHome还是EJBObject)调用方法时,厂商已通过不同的方法实现了EJB的负载均衡和失败转移。

智能存根
由于客户端通过存根对象访问远程EJB,存根对象可通过检索JNDI树获得,甚至可能让客户端透明地通过下载任意一台web服务器上的类文件也可获得。所以,存根的特点有:

存根可以在运行时动态地或通过编程的手段生成。存根的定义,即类文件并不需要在客户端环境的classpath下,也不需要包含在客户端运行时的JAR包中(因为可通过下载的方法获得)。



如上图,BEA WebLogic和JBoss采用在存根代码中添加特定功能来实现EJB的集群。这些代码透明运行在客户端。这种技术称之为智能存根技术。

智能存根之所以智能是因为它包含了能访问的目标实例。它能侦测到目标实例的失败,并使用复杂的负载均衡和失败转移的逻辑将请求转发至其他目标。此外,如果集群的拓扑图发生了变化(例如,有新实例加入或实例移除),存根能自动更新目标列表来反映最新的变化情况。

在存根中实现集群的优点如下:

因为EJB存根运行在客户端,所以节省了很多服务器端的资源。

负载均衡器整合在了客户端代码中,并与客户端生命周期息息相关。这就避免了单点负载均衡器失败的情况。如果负载均衡器失败了,客户端也极有可能失败,所以对系统并没有太大影响。

存根能自动动态下载更新,最大程度降低了维护量。

IIOP运行时库
Sun JES应用服务器通过另一途径实现EJB集群。负载均衡和失败转移逻辑在IIOP运行时库中实现。例如,JES修改了ORBSocketFactory的实现,让其支持集群,如下图。



修改过的ORBSocketFactory拥有执行负载均衡和失败转移的所有逻辑和算法,同时也保持了存根的简洁。因为实在运行时库中实现的,所以比起在存根中实现的办法来说它能更容易获取系统资源。但是这种方法在客户端需要指定的运行库,在与别的Java EE产品整合时可能会有一些麻烦。

监听代理(Interceptor Proxy)
IBM WebSphere引入了位置服务后台线程(LSD, Location Service Daemon),其作为EJB客户端的监听代理,如下图所示。



在这种方法中,客户端从JNDI中查找并获得存根。存根包含了通向LSD的路由信息而不是直接到EJB驻留的应用服务器。LSD接收所有的请求并根据负载均衡和失败转移策略来决定将它们分别发送至哪台实例中。本方法使集群的安装和维护工作量加大。

EJB的集群支持
要调用EJB的方法,需要两种类型的存根对象:一个是EJBHome接口另一个是EJBObject接口。这就意味着对EJB的负载均衡和失败转移可能在两个阶段发生:

当客户端使用EJBHome存根创建并查找EJB对象时

当客户端使用EJBObject存根来调用EJB方法时

EJBHome存根的集群支持
EJBHome接口用来创建或查找在EJB容器中的EJB实例,EJBHome存根是EJBHome接口的客户端代理。EJBHome接口不保持客户端的任何状态。所以,不同EJB容器的EJBHome接口对客户端来说都是相同的。当客户端调用create()或find()方法时,home存根根据负载均衡和失败转移算法从复制列表中选择一个服务器,并把对home接口的调用传递到那台服务器上。

EJBObject存根的集群支持
当EJBHome接口创建EJB实例时,它将EJBObject存根返回客户端让用户调用EJB方法。系统已经有了一个集群中可用服务器的列表,在这些服务器上都部署了EJB组件,但是根据EJB的类型,不能将由EJBObject存根发起的方法调用发送至判断服务器实例的EJBObject接口。

无状态的会话bean是情况最简单的:正因为没有保存状态,所有EJB实例都可考虑为相同的,所以从EJBObject来的方法调用可被负载均衡或失败转移至任何参与的服务器实例上。

有状态的会话bean就不太一样了。有状态的会话bean需要保持特定客户端连续请求时的会话状态信息。总的来说,对有状态的会话bean实施集群和对HTTPSession实施集群差不多。通常,EJBObject存根不会将请求转发至之前服务的实例之外的其他实例;它们通常会一直使用EJBObject创建时的实例,可以称之为“主实例”。在处理过程中,状态信息需要从主实例备份至其他服务器。如果主实例失败了,其他备份服务器将进行接管。

实体bean从根本上说还是无状态的,尽管它也处理有状态的请求。实体bean本身将所有信息数据备份至数据库中。感觉好像对于实体bean来说,负载均衡和失败转移都较容易实现。但实际上,实体bean不是总能得到负载均衡和失败转移的。正如设计模式中的建议,实体bean总是被包装在会话bean后。因此,大多数对实体bean的访问发生在正在处理的会话bean的本地接口中,而不是远程客户端。这就让负载均衡和失败转移失去了意义。

JMS和数据库连接的集群支持
在Java EE中,除了JSP、Servlet、JNDI和EJB之外还有其他的分布式对象。这些对象可能不能在集群实施中得到全面支持。

现在,一些数据库产品,例如Oracle RAC和Sybase SDC支持集群环境并可部署成多点同步的数据库实例。但是,JDBC是高度有状态的协议,其需要保存事务状态并紧密维护客户端和服务器的socket连接。所以,比较难实现集群。如果JDBC连接失败了,所有与连接相关的JDBC对象都会失败,而重新连接需要客户端代码的支持。BEA WebLogic使用JDBC连接池来降低重新连接的复杂度。

JMS在大多数Java EE服务器中都支持,但不是完全支持。负载均衡和失败转移只在JMS broker上实现了,一些产品还支持JMS消息目的地的失败转移功能。

Java EE集群技术参考文档下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐