? JNDI集群
Jndi集群对于EJB也是非常重要的,因ؓ几乎所有的EJB都是从JNDI调用开始的
I. ׃n全局JNDI?/strong>
Weblogic和JBOSS都用一个全局的、共享的、分布在整个集群pȝ的JNDI树,对象被绑定到全局上下文,使用ip多播方式拯JNDI数据
aaaaa
囑֍四:全局׃nJNDI
集群中的每个节点都有自己的命名服务器Qƈ且自动保存其他所有节点的JNDI数据Q因此这U结构具有高度可靠?
实际中,集群JNDI树主要有两个用途:一是用于部|Ԍ你只需要将某个EJB部vC台服务器上,pȝ会自动将其拷贝到其他节点。二是在q行中你可以用JNDI存取自己的对象,q些自定义对象同样会被自动拷贝到其他节点?
II.独立的JNDI?/strong>
Sun JES, IBM Websphere和其他厂商用的是独立的JNDI树,各个节点拥有自己独立的JNDIQ而不会关心其他节点的JNDI。但qƈ不意味着它们不能实现集群Q关键是每台服务器上的配|要相同Q应用也要相同,q样的话通过代理agentp实现高性能的集了
Sun JES ?IBM Websphere都在每个节点处安装了一个agentQ由console负责协调各个agent
但这U方式不支持动态绑定运行时生成的对象,设计者的理由是:JNDI本n是作ؓ理外部资源的中间层Q运行时对象l定不在JNDI的职责范围内Q如果真的有q种需要,可以使用LDAP或者具有HA功能的数据库。Sun和IBM都有自己的LDAP实现
III. 中央型JNDI?/strong>
数厂商采用中央型的JNDIQ所有节炚wM个某个指定的JNDI服务器上获取资源Q当然这对于客户端来说是透明的。不q这U方式会大大增加安装和管理的复杂性,因此被大部分厂商攑ּ
怎样开始连接JNDI?/strong>
使用JNDIQ你必须知道提供JNDI服务的域名或IP以及端口Q在全局和独立型JNDI树中Q都存在着多个JNDI服务器,客户端要q接哪一个呢Q负载均衡和p|恢复又是如何实现的呢Q?
技术上来说Q可以在客户端和JNDI服务器之间放一个硬件或软g实现的负载均衡器Q来实现上述要求Q不q大部分厂商都有更加单的ҎQ?
* SUN JES 和JBOSS 能够?#8220;java.naming.provider.url”q一JNDI属性支持用逗号分隔多个地址Q例如,“java.naming.provider.url=server1:1100,server2:1100,server3:1100,server4:1100”Q客L会逐个搜烦Q直到找C个可用的为止
* JBOSSq支持自动找d能,即o“java.naming.provider.url”属性ؓI,客户端会自动以网l多播的方式L一个JNDI服务器作为查询的起始?
? EJB集群原理
EJB衍生自分布式计算技术,服务器组件或富客L都能够以标准协议QRMI/IIOPQ调用远E的EJBQƈ且RMI/IIOP技术能够屏蔽底层网l,使得EJB的调用对客户透明?
图:EJB调用原理
如图Q客L不是直接和EJB打交道,而是通过stub来代理。Stub负责利用RMI扑ֈq程的EJBq进行调用。EJB的调用过E分Z面三步(EJB2.0Q?
1.从JNDI中查找EJBHOME stub
2.利用home stub创徏一个EJB Object stub
3.利用EJB Object stub调用EJB的方?
在JNDI查找Ӟ可以利用上文说到的方法进行负载均衡;各厂商也会有自己专门的技术对stub的用进行负载均衡,一般有以下三种方式Q?
Smart stub
我们知道Qstub可以通过JNDI来获得和创徏Q甚臛_以直接下载相应的class文g来在q行时动态生成,而无d客户端本地的classpath中声?
囑֍七:smart stub
如图十七QWeblogic 和JBOSS通过在stub的代码中嵌入Ҏ的代码来实现集群Q这个stub的确相当smartQ它包含了所有能够访问的集群服务器节炏V内|了专门的集算法来军_把请求发l何处,甚至当集的拓扑有变Ӟ比如增加了节点)Q能动态改变自w来适应新的l构Q无L工干?
Smart stub有以下几个好处:
1.节省大量服务器资?
2.׃负蝲均衡是由客户端处理,因此可以防止在服务器端放|负载均衡器而可能导致的单点p|
3.Stub可以动态下载安装,意味着无须手工l护
IIOP Runtime Library
Sun JES采用另一U方法,它直接修改客L的IIOPq行时库
囑֍八:IIOP Runtime
如图十八Qsun直接把负载均衡逻辑转移CIIOP库中Q从而stub能够保持“而轻”Q同时由于IIOP是底层库Q能够更加有效地获取和用JVM提供的资源。但正是׃底层库有所不同Q得JES与其?span class="hilite1">J2EE服务器打交道时可能会出现一些问?
Interceptor Proxy
IBM Websphere使用Location Service Daemon (LSD)作ؓ一个拦截器代理来实现EJB集群
Figure 19: Interceptor Proxy
使用q种机制Qstub中包含至LSD的\׃息,而不是直接去找服务器节点Q这样LSDp获得所有请求ƈq行负蝲均衡了,不过q样会大大增加管理和l护的成?
EJB的集支?/strong>
调用EJBҎ的过E中我们要和两个stub打交道,一个是home stubQ另一个是object stubQ因此可以在两个层面上实现负载均衡和p|恢复
1.EJBHOME STUB的集实?
׃EJBHOME STUB本n不包括Q何客L信息Q无Z哪个服务器上获得的EJBHOME STUB都是一LQ因此当客户端调用EJBHOME STUB的create{方法时Q就能利用一些负载均衡的法选择合适的服务器节?
2.EJBOBJECT STUB的集实?
EJBOBJECT STUB包含业务接口Q而且其本w也能够含有集群节点的信息,但也不是所有的Ҏ调用都能够进行负载均衡式的\由,得看EJB的类型是什?
无状态会话bean最Ҏ实现负蝲均衡了,因ؓ它本w不包含特定的客户信?
有状态会话bean略有不同Q因为它本n包含客户端的会话信息Q因此有状态bean的集实现本质上和HTTP session 无异Q一般情况下客户端的stub都是一直与某个节点上的EJBlg打交道的Q除非中途出问题了才会将h转发到备用的节点?
实体bean本质上也是无状态的。表面上看可以采用和无状态会话bean一L方式集群Q但实际上很厂商会对实体bean做集。因为实体bean一般都是被其他会话bean调用的,因此通常都用本地接口通讯Q实在没有集的必要
?JMS和数据库q接的集?/strong>
目前一些数据库产品已经可以集群了,你可以部|成多䆾Q每个节点之间可以同步。但是JDBC本质上是有状态连接,和底层的socket紧密l定。当某个JDBCq接H然中断了,与之相关的对象也p了,因此很难对JDBC集群。Weblogic使用一UJDBC multipoolQ可以在JDBC断开情况下,方便地进行重新连?
JMS的负载均衡和p|恢复只在JMS broker上有实现Q很有厂商在JMS destination 的消息上实现了负载均?
?关于J2EE集群的神?/strong>
p|恢复能够防止所有错误吗Q——错Q?/strong>
JBOSS的文档花了整整一章的内容来提醒你Q?#8220;你真的需要HTTP SESSION复制?#8221;Q有时候不用失败恢复也能以l济的方式获得高可靠性。更何况Q失败恢复ƈ没有你想象中的那么可?
你也许认为失败恢复能够在节点宕机时保护你的session数据Q但你得清楚Q这U保障是有代L?
回想一下作者在定义“p|恢复”Ӟ前提条g?#8220;在两个方法调用之?#8221;Q也是说只有在W一个方法成功返回之后、第二个Ҏ调用开始之前,p|恢复才能起作?
假设某个Ҏ处理C半时服务器不q挂掉了Q客L一般只能收到错误消息。除非你q个Ҏ恰好?#8220;idempotent”的(卛_ơ调用的l果都能保持一_不会对环境造成M改变Q比如getterҎQ,那么有些聪明的负载均衡器会尝试找其他节点去调用这个方?
所以说“idempotent”q个概念非常重要Q因为客L压根不知道是在什么地方失败的Q而如果这个方法不是idempotentQ那么系l就可能处于一U不一致的状态,很危?
你也许认Z务性的Ҏ是idempotent的,毕竟事务可以回滚。但其实事务q远不能늛整个q程调用的范_比如服务器成功执行某事务性方法后Q返回结果的q程中网l崩溃了呢?
在比较严格的pȝ设计中,你根本不能o所有方法都idempotentQ你能做的就是利用failoverQ尽可能减少错误而不是彻底杜l错误。以某个|上商城ZQ每台服务器都同时处?00个用戯求,当某台服务器崩溃Ӟ如果没有p|恢复Q那么你会得|一百个用户Q而如果有p|恢复Q可能只有不?0个用户会发飙。你自己要权衡:
1.是得|一百个客户q是得罪20个客P
2.有没有失败恢复的服务器的h差别
独立的应用程序可以无~地q移到分布式q_上?——错Q?/strong>
q只是某些厂商的q告而已Q不可轻信。如果是大型pȝQ那么设计之初就应该全盘考虑集群可能造成的媄?
HTTP SESSION
正如前文所qͼHTTP SESSION的集会受到你用的服务器的诸多限制。首先是可序列化的要求,在很多MVC架构中,session被用来存储一些不可序列化的对象(比如servlet contextQ;其次Q序列化、特别是数据库方式的序列化非常耗费资源Q因此要集群尽量不要用session存储大对象。如果是内存拯的方式,那么p考虑内存的限制和交叉引用的问题(交叉引用请参考前文)Q最后,你在集群环境下改变session的属性时Q必M?#8220;setAttribute”ҎQ而在单机环境下却没这个限制。这么做的主要原因是让你的应用服务器能够到属性改变,及时地备份已修改的属?
~存
大部分流行的应用服务器都会用缓存来提升性能Q但~存一般都是ؓ单机环境设计的。集环境下如果使用~存Q那么缓存之间的拯p的性能比~存带来的好处还多,适得其反
静态变?/strong>
有一U很行?span class="hilite1">J2EE设计模式“singletonQ单体)”Q是使用静态变量的Q这在单机环境下适用Q但C集群׃行了Q道理很单,每个JVM都有自己的静态对象,“单体”也就失去意义了。比如要l计在线用户数时Q经常用一个静态变量来存储Q但是在集群环境下这U方法显然失M用。要使用静态对象,最好把它放C个数据库中,才能实现全局?#8220;单体”
外部资源
管J2EE规范q不推荐Q但外部IO操作q是有用的,比如用来存放用户上传的文件。在集群中,服务器是不能通过另一台服务器把本地文件直接存攑ֈ别的机器上的Q那么还是要依靠数据库来l一存放文gQ或者你可以使用SANq种集中式文件仓?
专有服务
有些专有服务是只限于单机环境的,比如定时器服务(timerQ;再比如某些事件触发类型的服务Q如初始化服务,邮g提醒服务也属于此列。这些服务一般针对一个特定条件只发生一ơ,拿去集群没什么意义。JBOSS?#8220;clustered singleton facility”是用来保证所有服务器q行且只q行一ơ某U服?
分布式系l比q列式系l更灉|Q——未?/strong>
管EJB生来是Z分布式、解耦合Q但很多框架认ؓ把EJB层和web层放在一起也未尝不是好事Q或许更?
?0Q分布式架构
如图20Q负载均衡器先将h分发到适当服务器的web层,web层进一步判断调用何处的EJBQ这{于是做了两ơ的负蝲均衡和失败恢复。很多h认ؓq种设计q不好:
1. 首先Q第二次的{发根本没有必要,每个服务器都有自qweb和ejb层,比v只调用内部的ejbQweb层调用其他ejb层没有Q何的好处
2. W二ơ的p|恢复也是没有必要的,大部分厂商都把web容器和ejb容器实现为在同一个jvm上跑Q那样一旦web容器挂了Qejb容器很难独善其n
3. 损失性能Q这个不必解释了Q大量的服务器之间的调用Ҏ能肯定有媄响?
实际上,大部分厂商都让web容器优先选择同一个服务器上的ejb容器Q这U方式称?#8220;q列?#8221;Q是分布式的一U特例,如下?
?1Qƈ列式
q样引出一个有的问题Q既焉放一块了Qؓ什么不直接用ejb的本地接口呢Q虽然本地接口可以提高性能Q但它却把web和ejb紧耦合在一起了Q负载均衡机制也没有办法对其进行优化,特别是当你要变成分布式的时?
此外很不q的是,在集环境下本地接口的用经常受到限Ӟ因ؓ有本地接口的ejb通常是不可序列化的。所以有些应用服务器Q比如sun JESQ对本地接口的ejb做了Ҏ处理使其可以被序列化Q从而保存到诸如session中去
q有一个问题是Q既然大部分情况下ƈ列式的性能都比较好Q那q要分布式干什么呢Q其实在某些情况下还非得用分布式不可Q?
1. 除了web容器Q富客户端也要调用ejblg
2. Web容器和ejb容器所处的安全U别不同Q它们物上也被攑֜不同的地方,中间加上一个防火墙
3.Ejb和web层的极度不对U。指的是复杂度的不对Uͼ比如ejb层有大规模的q算Q那放在一台高U的服务器上Q而web容器只需攑֜一台pc上即?
?l论
集群与单机环境是有很大不同的Q各厂商的集实C不同。最好在目开始就考虑到集,使得你的pȝ更有扩展性,Ҏ自n的需求选择最合适的应用服务器,q且选购W三方Y件时也要考虑到对集群的支持。最后,合适的架构可以让你受益于集而不是让集群成ؓ你的噩梦
关于原作?
引用
Wang Yu presently works for GPE group of Sun Microsystems as a Java technology engineer and technology architecture consultant. His duties include supporting local ISVs, evangelizing and consulting on important Java technologies such as J2EE, EJB, JSP/Servlet, JMS, Web services technologies. He can be reached at yu.wang@sun.com.