摘要: 如果想要建立一个可伸缩的高可靠性的网站,就需要了解集群技术(clustering).本文中,Abraham Kang介绍了J2EE集群,怎样实现集群, 并列出Bluestone Total-e-server, Sybase Enterprise Application Server, SilverStream Application Server 和WebLogic Application Server在集群技术上有什么区别.基于这些知识,你就能够设计自己有效且高效的J2EE applications.
企业越来越多地选择Java 2, Enterprise Edition (J2EE)来开发它们基于任务的网上应用.在J2EE framework中, 集群技术能保证最少的downtime,最大的伸缩性.一个集群就是一组application servers透明地运行J2EE应用服务,就好像它们是一个整体. 在集群中必须提供额外的机器.若要将服务是健降至最短,其中的每个组件都必须是冗余的.
在本文中,我们将获得关于集群的基本知识和集群的方法,以及重要的集群服务.由于业内集群技术差别很大,我们将比较每种技术的优劣.更进一步的,我们将讨论与集群有关的application server将要实现的特性.
为联系实际应用,我们将看一看HP Bluestone Total-e-Server 7.2.1, Sybase Enterprise Application Server 3.6, SilverStream Application Server 3.7, 和BEA WebLogic Server 6.0 各是怎样实现集群的.
本文的第二部分中,我们的讨论将涉及集群的编程和差错恢复策略,并测试我们所提到的4种application server产品是怎样伸缩规模和进行差错恢复的.
集群的定义
<div>J2EE application server的供应商把集群定义为一组计算机一起工作,提供透明的企业级服务(支持JNDI, EJB, JSP, HttpSession,组件差错恢复等).他们故意定义得很模糊,因为他们对它的实现各不相同.一部分开发商在一组互相独立的机器前端放置一个dispatcher,dispatcher接受用户的请求,然后用HTTP redirect header将请求转到集群中一台特定的server上.另一部分开发商则实现了一个紧密集成在一起的机器联合,每台机器能完全感知它周围其它机器的存在,连同驻在它们之上的对象.
除了机器方面的集成,集群还包含冗余和出错恢复:
负载平衡器:进入集群的单一的入口点,站点或application server的流量指示器
网关路由器:内部网络的出口点
多层交换器:包过滤或帧过滤,确保每台机器仅收到和自己相关的信息
防火墙:端口级别过滤,防止hacker进入集群或内部网络
SAN (Storage Area Networking)控制器:把application servers, Web servers和databases连接到后端存储介质,管理数据该写到哪个硬盘;以及出错备份
数据库
无论怎样实现,集群都提供两大主要功能:可伸缩性和高可靠性(HA).
可伸缩性
可伸缩性是指一个应用程序能支持不断增长的用户数量的能力.集群通过增加server来提供额外的工作能力,从而保证了可伸缩性.
高可靠性
HA可用一个词概括:冗余(redundancy).一个集群用很多机器服务请求, 因此,即使一台机器崩溃了,其它机器也可透明地接过任务.
集群仅在application server层提供高可靠性. 对一个网络系统来说,要表现真正的HA,必须像诺亚方舟(Noah's ark)一样每种东西提供两件,包括Web servers,网关路由器,交换结构等.
集群种类
J2EE集群通常采取两种方法: 不共享集群(shared-nothing cluster),和共享存储集群.在不共享集群中,每个application server有自己的文件系统和在集群中运行的应用的copy.应用程序的升级需要更新集群中的每个节点.这种设置对大的集群而言,维护就像一场噩梦,尤其是当代码需要更新时.
相反,共享存储集群公用一个存储设备,每个application servers从那里获得运行的application.更新只在一个文件系统中进行,所有机器能访问到这些变化.直到现在,单点失败(single-point of failure)仍是它的弱点.然而,SAN提供一个到冗余存储介质的单一的逻辑接口,以便进行出错恢复, 出错回退和可伸缩性.(欲详细了解SAN, 参见Storage Infrastructure.)
比较J2EE application server的集群技术实现,最重要的是考虑一下因素:
集群的实现
集群和组件的出错恢复
HttpSession的出错恢复
集群拓扑的单点失败
可变的拓扑结构
维护
以后我们将在不同的方面比较四个流行的application server的集群技术,但首先,我们先仔细探讨一下各要素.
集群的实现
J2EE application server在实现JNDI(Java Naming and Directory Interface)的基础上实现集群.尽管JNDI是J2EE应用程序依赖的核心,在集群中却很难实现,因为不能把多个对象bind到一个JNDI名字上.依据不同application server JNDI的实现,有三种集群的方法:
独立的(Independent)
集中的(Centralized)
全局共享(Shared global)
独立的JNDI tree
HP Bluestone Total-e-Server和SilverStream Application Server在每个application server中使用独立的JNDI tree.JNDI tree的server成员并不知道和关心集群中其它server的存在.因此,差错恢复要么不支持,要么通过一个重定向HTTP或EJB request的中间服务支持.这些中间服务经过配置可知道每个组件在集群中的位置,并知道万一出现错误哪里有替代品.
独立JNDI tree集群的一个优点是: 集群集中度(convergence)更短,伸缩简便.集群集中度衡量的是集群完全感知所有成员和其上的对象的时间指标.然而,集中度在独立JNDI tree集群并不是问题,一旦两台机器启动起来,集群就能获知集中度. 另一个优点是: 可伸缩性只要额外的机器参与就行.
但是,也存在着缺点.首先,出错恢复通常是开发者的责任.故,由于每种application server的JNDI tree是独立的,通过JNDI查询得到的remote proxy被绑定到查询发生时的那台server上,这样,如果EJB的这次调用失败了,开发者需要写额外的代码连接dispatcher,获取另一台有效的server的地址,再进行一次JNDI查询,重新调用刚才失败的方法.Bluestone实现了一种更为复杂的形式,每个请求都通过一个EJB proxy服务,称作Proxy LBB (Load Balance Broker).EJB proxy服务保证每个请求都发往活动的UBS实例.这样引入了额外的延迟,但是自动执行了出错恢复.
集中式JNDI tree
Sybase Enterprise Application Server实现的就是集中的JNDI tree集群.集中的JNDI tree集群对JNDI采用CORBA的CosNaming服务.Name server中驻有集中式JNDI tree,跟踪哪个server启动了.每个server在启动时,把object bind到自己的JNDI tree中,同时也bind到所有的name server中的JNDI tree.
这种模式下获得EJB的引用分两个步骤.首先,用户从name server查询home object, 前者返回一个可互作用的对象引用(interoperable object reference IOR). IOR指向几个活动的含有该home object的server. 然后,用户用第一个server获得home和remote.如果EJB方法调用中出现错误,CORBA stub负责实现获得另一台机器(列于IOR中)上的逻辑.
name server本身是这种方式下的一个弱点.举例来说,如果一个集群中有50台机器,其中5台为name server. 如果每个name server都不可用的话,集群就没用了.实际上,另45台机器都是好的,但整个集群将不处理任何EJB 请求.
当集群中所有的name server都崩溃了,就需要另一台机器马上扮演name server的角色,由此产生了另一个问题.这种情况下,新的name server要求集群中所有活动的机器把自己的对象bind到其上的JNDI tree.尽管bind 过程中接受请求未尝不可,但建议不要这样.binding过程延长了集群的恢复时间.而且,每个JNDI查询实际上代表两个网络调用,一个从name server获取IOR,而第二个从IOR指定的server获取object.
最后,当集中式JNDI tree集群扩大规模时,它的集中度时间也越来越长.扩大规模时,必须增加越来越多的name server. 记住name server和整个集群机器的一般可接受比例是1:10, 且至少有两台name server.因此,如果你的集群有10台机器,两台为name server,总共就有20个bind. 40台机器的集群,有4台name server, 就有160个bind. 每个bind代表一台成员server把它上面所有对象bind到name server的JNDI tree上的一个过程.这样,集中式JNDI tree集群的集中度在所有实现中是最差的.
全局共享式JNDI tree
最后, BEA WebLogic实现的是全局共享式JNDI tree. 这种方式下,当集群中的一台机器启动时,它通过IP组播宣布它的存在和它的JNDI tree.每台server把对象bind到自己本地的JNDI tree的同时,还bind到一个共享的全局JNDI tree.
把JNDI tree分为全局的和本地的,生成的home和remote stub就能出错恢复,并提供快捷的过程中(in-process)JNDI查询.全局JNDI tree在每个成员中共享,每个成员都能知道集群中每个对象的确切地址.如果哪个对象在两台以上的机器上,一个特殊的home object被bind到全局JNDI tree上.这个home知道它关联的所有 EJB object的位置,生成的remote object也同样知道所有的位置.
全局共享的主要缺陷在于:网络流量在server启动初始化时非常大,集群集中度也很大.相反,在独立的JNDI tree集群中,这并不是问题,因为没有JNDI信息共享.而全局共享式或集中式集群在简历共享或集中式JNDI tree时要花费时间.实际上,由于全局共享集群采用组播传递JNDI信息,建立全局JNDI tree的时间是随server线性增长的.
全局共享式较集中式JNDI tree而言,主要的优势在于:集群实现主要致力于伸缩的易实现性和更高的可靠性. 通过全局共享,你不必改动name server的CPU和RAM,或者调节集群中的name server数量.想扩展应用规模,增加server就行.而且,如果哪台崩溃了,集群仍能很好地工作.最后,每个远程查询只要一个网络调用就完成了,相比集中式的两个而言就省多了.
由于JSP,servlet,EJB和JavaBean最好能同时驻扎在一台application server上, 它们总是使用进程中JNDI查询.记住如果你仅仅运行服务器端的应用,三种方式没什么区别. 事实上,每个HTTP请求在application server中做进程中JNDI查询,返回应用中调用的对象.
接着,我们将注意力集中到J2EE application server的第二大考虑因素:集群和出错恢复服务.
集群和出错恢复服务
在一台server上提供J2EE服务相比在整个集群中提供来说是微不足道的.鉴于集群技术的复杂性,每个application server有自己独到的实现方式.你应该向供应商了解他们怎么实现集群和entity bean, stateless session bean, stateful session bean以及JMS的出错恢复.许多供应商宣称自己支持集群化组件,但他们对此的定义经常牵涉到集群中的组件.例如,BEA WebLogic Server 5.1支持集群化的stateful session bean,但如果server本身崩溃了,其上所有状态也丢失了.客户只得重新创建stateful session bean,使得原来的在集群中就不可用了. 直到BEA WebLogic 6.0发布,stateful session bean才实现内存复制来集群化和出错恢复.
所有application servers支持EJB clustering,但对可以配置的自动出错恢复的支持有很大的不同. 事实上.有些application servers并不支持EJB client的自动出错恢复.例如,Sybase Enterprise Application Server支持stateful session bean出错恢复, 前提是你从数据库或通过序列化load bean的状态.如前面所提到的,BEA WebLogic 6.0通过内存复制bean的状态来支持stateful session bean的差错恢复.大多数application server可以在集群中运行JMS,但对个人命名的Topics和Queues不提供负载均衡和出错恢复.这样,你可能就需要购买可集群的JMS产品,如SonicMQ,来获得Topics和Queues的负载均衡.
另一个很重要的考虑因素,我们现在要提到的是:HttpSession出错恢复.
HttpSession出错恢复
当原先为用户创建session的服务器崩溃了,HttpSession出错恢复允许用户无缝地从另一台server上获得session信息.BEA WebLogic Server实现了session信息内存复制,而HP Bluestone Total-e-Server采用集中式session server,它带有HA的备份. SilverStream Application Server和Sybase Enterprise Application Server采用集中式数据库或文件系统,每个application servers都从中读写.
用数据库/文件系统实现的session持久性的主要缺点在于:当存储大的或很多对象在session中时有限的伸缩性.用户每次向HttpSession增加一个对象,session中所有的对象都要序列化并写入数据库或共享的文件系统.大多数用数据库实现session持久化的application server都主张尽量少用session存储object, 但这会限制Web application的结构和设计,特别是用HttpSession存储用户数据时.
基于内存的session持久性把内存中的session信息写到一个备份服务器上,有两种做法.第一种把HttpSession信息写到一个集中式状态服务器(centralized state server). 集群中的所有机器都把HttpSession objects写到这台server上. 第二种方法,集群中每个节点任意地选择一个节点存储内存中的session信息.每个用户向HttpSession增加object,该object被单独序列化在写入那台backup server.
上面两种方法中,如果集群中的机器数较少,用专门的state server比任意指定backup server要好,这样可以节省CPU来处理transaction和动态网页的生成.
另一方面,当集群的机器数很大时,专门的state server就成为瓶颈,而向任意指定的backup server复制内存的消耗将随着机器数的增长而线性增长.当增加机器时,用专门的state server,你需要为它加上更多的RAM和CPU.用任意指定的backup server, 你仅仅增加机器而已,session会平均地分布在所有机器之间.基于内存的持久化提供了灵活的Web application设计,规模和高可靠性.
现在我们将检查一下单一点失败.
单一点失败
未提供备份的集群服务会造成单一点失败,他们会造成整个集群或部分应用崩溃.例如,WebLogic JMS在集群中仅能有一个Topic运行在一台机器上.如果那台机器碰巧崩溃了,那应用中依赖JMS Topics的部分就不能工作,直到另一个WebLogic instance启动起来(注意只有durable message才能在新的server instance启动时被发送.)
检查一下你的集群是否存在单一点失败.如果有,你得估计一下这样是否能满足应用需求.
下面提及伸缩拓扑.
灵活的伸缩拓扑
集群还需要灵活的拓扑布局.大多数application server还可以充当HTTP server,见图1.
图1. 多合一拓扑
当你的website大多数是动态网页时,这种结构不错.然而,当大多数是静态页面时,要扩展网站的代价就非常昂贵了,因为你要增加application server用于静态HTML页面请求.所以,适当的做法是:要扩展静态部分,增加Web server, 要扩展动态部分,增加application server,如图2.
图2. 分隔的拓扑
上图的结构主要的缺陷在于:增加了动态页面请求延迟.但是相比灵活的独立扩展而言,微不足道.
最后,对application server的讨论终止于维护性.
维护性
集群中大量机器总避免不了维护问题:维持集群运行,通知应用的改变.Application servers应该提供agent来感知主要服务的崩溃,然后重新启动它们.或者激活backup server. 更进一步,application server应该提供一个简便的方法来更新和同步集群中所有的server.
Sybase Enterprise Application Server和HP Bluestone Total-e-Server提供文件和配置同步服务. Sybase Enterprise Application Server在主机, 组和集群level上提供这些服务.Bluestone则仅提供主机level的. 如果要deploy大的application或很多application, 就要花很长的时间. BEA WebLogic Server 仅提供配置同步. 这两者中,配置同步加上storage area network更能较好地工作,因为可以把变化写入一个逻辑存储介质, 这样所有的机器就能接收到application file的变化. 每台机器只需要从一台集中式configuration server上接收配置变化就可以了. SilverStream Application server用dynamic class loader从数据库中载入application files和configuration. dynamic class loader使得运行中的application server接收变化更方便.
我们已经讨论了application server需要考虑的重要特征.下面就根据我们的准则比较一下4个流行的application server.
Application Server比较
既然我们学习了关于集群的一般知识,让我们把注意力集中在各个application server上,把所学的和现实世界联系起来.我们要比较的是:
HP Bluestone Total-e-Server 7.2.1
Sybase Enterprise Application Server 3.6
SilverStream Application Server 3.7
BEA WebLogic Server 6.0
每个application server的讨论都包含一张HA结构图,接着是它的重要特征的小结.
HP Bluestone Total-e-Server 7.2.1
图3. HP Bluestone 7.2.1拓扑
集群一般特性小结:
Bluestone实现的是独立的JNDI tree集群.作为plug-in运行在Web server中的LBB,提供HTTP请求的负载平衡和出错恢复服务.LBB知道哪台UBS(universal business server)上运行着什么application,可以正确地定向流量.通过EJB Proxy Service和Proxy LBB支持对stateful,stateless session bean和entity bean的方法间出错恢复. EJB Proxy Service的主要缺点在于增加了每个EJB请求的延迟,而且它同UBS运行在同一机器上.EJB Proxy Service和UBS stub支持UBS崩溃的情况下的出错恢复,但是不支持硬件崩溃的出错恢复.后者出现的情况下,出错恢复是通过客户端配置apserver.txt或Proxy LBB对apserver.txt配置.客户端的apserver.txt里面列出了集群中所有的组件.当有新的组件加入时,所有客户需要用BAM (Bluestone Application Manager)更新该文件或手工逐个主机地更新.在Proxy LBB处配置apserver.txt将用户和集群中的变化隔离,但为EJB请求引入了新的延迟.HP Bluestone是唯一的一个提供集群化和负载均衡JMS的application server.
集群集中时间:
相对集中式和全局共享式JNDI tree而言,最少.
HttpSession出错恢复:
集中式state server和backup state server或数据库,内存复制.
单一点失败:
无
灵活的集群拓扑:
支持所有集群拓扑.
维护:
Bluestone在维护方面胜过其它server.Bluestone提供一个动态应用加载器(dynamic application launcher DAL), 供LBB在应用程序或机器崩溃时调用. DAL能够在主机或备份机上重启应用程序.另外,Bluestone还提供一个配置和发布工具,叫Bluestone Application Manager (BAM), 用来deploy application package和它们的相关文件.这个工具唯一的缺点是一次只能配置一台机器--对大型集群用起来就不方便了.
Sybase Enterprise Application Server 3.6
图4 Sybase Enterprise Application Server 3.6 拓扑
集群一般特性小结:
Enterprise Application Server实现的是集中式JNDI tree集群,用硬件负载平衡器来完成HTTP请求的负载均衡和出错恢复.一个集群中的两台name servers各自可以单独处理HTTP request,但是为性能考虑,最好还是专门处理JNDI request.
Enterprise Application Server 3.6没有Web server plug-in,但到二月的3.6.1 EBF (Error and Bug Fixes)版就会有了.它支持stateful, stateless session bean和entity bean的方法间出错恢复.记住Enterprise Application Server病危提供任何监视代理或动态应用程序加载器,你需要为单一点失败或自动server重启购买第三方产品,如Veritas Cluster Server.Enterprise Application Server不支持JMS.
集群集中时间:
集中时间取决于name server的数量和成员server的数量.在三种集群实现方式中,集中式JNDI tree集群的集中度是最差的.尽管集中时间指标很重要,server可以在把对象bind到name server的同时就开始接收请求(当然,推荐最好不要这样做).
HttpSession出错恢复:
HttpSession出错恢复用集中式数据库实现,不支持内存复制.
单一点失败
如果运行多台name server,则没有单一点失败.
灵活的集群拓扑:
拓扑结构受限于没有Web server plug-in.
维护:
Sybase使用文件和配置同步,为application deployment提供了最好的选择.它可以在component,package, servlet,application,甚至Web application level上同步.你还可以选择同步整个集群,一组机器或单个主机. 很棒的功能!但是如果集群中的机器太多,同步就要持续相当长一段时间.它的一个弱点是没有动态应用程序加载服务, 这意味着你必须购买第三方产品,如Veritas Cluster Server.
SilverStream Application Server 3.7
图5. SilverStream Application Server
dispatcher 拓扑.
图6. SilverStream Application Server
WSI拓扑
集群一般特性小结:
当设置SilverStream集群时,有两种配置方案:基于dispatcher的和基于Web server集成模块(Web server integration-module WSI)的.在基于dispatcher的集群中,用户连接dispatcher或基于硬件的dispatcher -- 例如Alteon 180e,然后dispatcher将HTTP重定向到及群众的一台机器上.从那个时刻起,用户与那台server就在物理上绑定了.故这种方式下,一个集群和一台server没有区别.主要的缺点在于:静态部分和动态部分不能独立地扩展.
在基于WSI的集群中,用户先连接dispatcher,后者控制web server的负载平衡和HTTP请求差错恢复. 每个Web server有一个plug-in指向一个位于集群前端的负载平衡器.WSI集群不使用重定向,每个HTTP请求可以在任何一台机器上被平衡负载.副负载平衡器仅当application server层崩溃时用. A WSI结构优于dispatcher结构:能独立扩展静态和动态部分.但是,主要缺点是需要ArgoPersistenceManager作HttpSession出错恢复.在任何一种方式中,用户都不能得到方法间的差错恢复.EJB出错恢复完全成为程序员的责任.最后,SilverStream不支持集群化JMS.
HttpSession出错恢复:
SilverStream用集中式的数据库和ArgoPersistenceManager提供HTTPSession出错恢复.不幸的是,这个解决方案具有所有权问题.不使用常规的把session信息存入数据库的方法,而使用一个产品的 ArgoPersistenceManager class -- 一大缺憾.
集群集中时间:
相对集中式和全局共享式JNDI tree集群,最少.
单一点失败:
以上结构皆没有.
灵活的集群拓扑:
支持所有集群拓扑.
维护:
缓存管理器和动态class-loader为deploy和更新运行着的应用程序提供了方便的途径,基本不打扰当前活动的client. 当集群中的一台server上的应用更新时,更新的部分写入数据库,然后缓存管理器把所有机器上的缓存设为无效,强迫它们下次重新获取新的application.只有一个缺点,就是要花时间把应用从数据库中取出,调入内存中.
BEA WebLogic Server 6.0
图7. BEA WebLogic Server 6.0
集群一般特性小结:
WebLogic Server实现的是全局共享式的JNDI tree集群.这种工作方式下,当一台server启动时,把自己的JNDI
tree写入全局共享的JNDI tree.然后server用这个全局的tree的备份来提供服务,使用户能感知集群中的所有对象.用户用的stub能感知整个集群,意味着它们向原定的server请求,但同时拥有其它application server上复制品的信息. 正是由于这点,stub可以透明地进行差错恢复.WebLogic Server的一个独一无二的特性就是stateful session bean的内存复制和可配置的EJB remote objects自动出错恢复. WebLogic把clusterable定义为一个在集群中的服务.JMS就是这样一个服务,但是每个Topic or Queue仅在一台server上运行,所以不能负载均衡和出错恢复-- WebLogic JMS实现的一大缺点.
HttpSession出错恢复:
WebLogic Server通过向任意指定的backup server或database server复制内存中状态来实现HttpSession出错恢复.集群中地每台机器挑选一台不同的机器.如果主server崩溃了,backup server变成主server,再重新挑选一台backup server. WebLogic有一个唯一的特性:cookie的独立性. HP Bluestone和Enterprise Application Server都需要cookie 才能进行HttpSession出错恢复,但是WebLogic可以使用URL中加密的信息,把用户定向到backup server上.
单一点失败:
JMS和Administration server.
灵活的集群拓扑:
支持所有集群拓扑.
维护:
WebLogic的弱势在于维护.尽管BEA已经在配置同步方面采取了积极的措施,WebLogic Server还是没有任何监视代理,动态应用加载器,或文件同步服务.所以你需要为单一点失败或HA购买第三方方案.如果你采用了SAN,你就不必文件同步服务了,但大多数开发者才刚刚开始认识到SAN的好处.
分析
总体来说BEA WebLogic Server 6.0最为强壮,集群实现得最彻底.HP Bluestone Total-e-Server 2.7.1, Sybase Enterprise Application Server 3.6, SilverStream Application Server 3.7 依次排列.
选择正确的application server需要权衡折衷.如果你的应用中有EJB clients (applet和applications), Web clients, 对HttpSession大量使用(为了caching), 要求扩展简易和出错恢复,你需要BEA WebLogic 6.0.如果你的application需要大量使用JMS,绝大多数client是Web client, Bluestone可能更好一些.从集群地角度说,Sybase Enterprise Application Server 3.7缺少重要的集群特性,例如JMS,HttpSession内存复制,Web server plug-in等. 但是,Sybase Enterprise Application Server 3.7的确带来了文件和配置同步服务.如果你使用SAN,这些有点就微不足道了.SilverStream Application Server的集群实现得最不彻底, 缺少集群化的 JMS,HttpSession内存复制和出错恢复等.
结论
在本文中你获得了集群的一般认识,集群的方法和重要的集群服务.我们审视了每个application server的优缺点,讨论了和集群有关的特性.有了这些知识以后,你就懂得如何建立高可靠性和伸缩性的集群.但这仅仅是学习的开始,到外面找一些evaluation clustering license, 和application server,验证一下.
第二部分中,我们要开始写代码,验证application server供应商的承诺.我们还将用J2EE Java Pet Store例程做负载和集群集中度测试.