日期:2014-05-19  浏览次数:20834 次

j2ee集群的面纱
对于理解J2EE集群技术不错的文章,虽然是Sun的技术人员撰写的,基本观点还算客观,内容深浅恰当,非常适合刚刚接触集群的朋友阅读,故此大胆翻译过来,放在这里和大家共享,错误难免,欢迎指正。

原链接
Uncover the hood of J2EE Clustering

1 前言

越来越多的关键任务和大型应用正运行在J2EE平台上,象银行之类的应用要求很高的可用性(HA),大型系统比如 google和Yahoo则要求更好的伸缩性。今天高可用性和伸缩性的重要性对于互联世界日益增长,最著名的证明是1999年eBay中断了22小时的服 务,原因是超过230万次的拍卖,最终导致 eBay股票下跌了9.2个百分点。

J2EE集群是最常用的技术,用来提供高可用性和伸缩性的容错服务。但由于缺乏J2EE规范的支持,J2EE提供厂商实现的集群尽不相同,引起许多J2EE架构师和开发者的麻烦,比如下面:

1. 为什么附带集群能力的商业J2EE服务器如此昂贵?(比不带集群能力的贵10倍)
2. 为什么我在单机上创建的应用无法运行在集群模式?
3. 为什么我的应用在集群时运行缓慢但不集群时却很快速?
4. 为什么我的集群应用不能与其他提供商的服务器通信?

2 基本术语

讨论不同实现之前,理解集群技术的概念是很有意义的,我希望不仅能给你提供关于J2EE集群产品基本的设计理念和概念,还可以概括性的描绘不同的集群实现,使它们更容易被理解。

2.1 伸缩性(Scalability)

大型系统很难预测终端用户的数量与行为,伸缩性是指系统可以支持用户的快速增长。提高服务器同时处理并发会话的最直觉的方式就是增加服务器资源(内存, CPU,或硬盘),集群是解决伸缩性的另一种可选方式。它允许一组服务器分担处理繁重的任务,而逻辑上就象一台服务器一样。

2.2 高可用性(High Availability)

提高伸缩性的单服务器解决方案(添加内存和CPU)是并不强壮的办法,因为单点失效原因。关键任务应用不能容忍服务中断哪怕一分钟。它要求任何时候都可以合理地可预期的响应时间访问这些服务,集群可以通过提供额外的服务器使其在一台服务器实效时提供服务,从而提高可用性。

2.3 负载均衡(Load balancing)

负载均衡是集群技术之后的一个关键技术,通过分发请求到不同的服务器来提高可用性和更好的性能。负载均衡器可以是一个Servlet或插件(例如a linux box using ipchains),除分发请求之外,负载均衡器应负责其他一些重要的任务,例如“会话黏附”,使得某个用户会话始终在一台服务器上存活,还有“心跳检测”,防止分发请求到失效的服务器。有时候负载均衡器也参与到“失效转移”处理。

2.4 容错(Fault Tolerance)

高可用性数据不必是严格正确数据.在J2EE集群中,当一个服务器实例失效时,服务仍然可用,因为新的请求可由其他冗余的服务器实例处理。但如果请求正在处理当中时服务器实例失效,则不能能得到正确的数据。然而容错服务则总是保证严格正确的行为。

2.5 失效转移(Failover)

失效转移是另一项使得集群实现容错的关键技术。通过选择集群中另一个节点,原始节点失效时处理将继续下去。失效转移可以显式地编码也可以由低层平台自动执行。

2.6 等幂方法(Idempotent methods)

可以用相同的参数重复调用的方法,并且总是得到相同的结果。这些方法不应该影响系统状态,可以被重复地调用而不必担心改变系统。例如, “getUsername()” 是等幂方法,而“deleteFile()” 就不是等幂方法。等幂是HTTP会话和EJB失效转移的重要概念。

3 J2EE集群是什么?

一个幼稚的问题,不是吗?但我仍然用一些话语和图表来回答它。通常J2EE集群技术包括“负载均衡”和“失效转移”。



图1 负载均衡

如图1所示,有很多客户端对象并发发送请求到目标对象。负载均衡器则位于调用者和被调用者之间,分发请求到冗余的拥有同样功能的对象上。用此方法可以实现高可用性和高性能。




图2:失效转移

如图2所示,失效转移与负载均衡不同。有时候,客户端对象对目标对象发起连续的方法请求。如果目标对象在请求之间失效,失效转移系统应该检测到并将后续请求转向导另一个可用的对象,容错也可用此途径实现。

如 果想了解更多J2EE集群,你应该问更多的基本问题,例如:“什么类型的对象可以被集群?”,“在我的J2EE代码中什么地方出现负载均衡和失效转 移?”,对于理解J2EE集群的原理,这些都是非常好的问题。实际上,不是所有对象可以被集群,也不是任何地方都可以负载均衡和失效转移!看看下列代码:




图3:代码例子

当“instance1” 失效时,“Class A”的“business()”方法会负载均衡和失效转移到另一个B实例吗?不,不会。对于负载均衡和失效转移,必须要在调用者和被调用者之间存在一个拦 截器,用来分发或者转向方法调用到不同的对象上。A和B的实例对象运行在同一个JVM上,并紧密耦合。很难在方法调用之间添加分发逻辑。

所以,什么类型的对象可以被集群?---只有发布在分布式结构的对象。

所以,什么地方会发生负载均衡和失效转移呢?--只有在调用一个分布式对象的方法时。




图4:分布式对象

在分布式环境,如图4所示,调用者和被调用者被分离为不同边界的运行容器,边界是JVM,进程或机器。

当客户端调用目标对象时,在目标对象容器内执行功能。客户端和目标对象通过标准的网络协议通信。利用这些特性添加机制到方法调用路由中,以实现负载均衡和失效转移。

如 图4所示,浏览器可以通过HTTP协议调用远程JSP对象。JSP在Web服务器上执行,浏览器不关心执行过程,它只需要结果。在这样的场景中,有些东西 可以位于浏览器和web服务器之间用来实现负载均衡和失效转移功能。在J2EE中,分布式技术包括:JSP(Servlet),JDBC ,EJB,JNDI,JMS,Webservices和其他。当分布式方法被调用时可以发生负载均衡和失效转移。下面我们会讨论细节。

4 web层集群实现
web层集群是J2EE集群中最重要和基础的功能。web层集群技术包括:Web负载均衡和HTTPSession失效转移。

4.1 web负载均衡
J2EE提供商有很多方法实现web负载均衡,基本的,在浏览器和web服务器之间放置负载均衡器。




图5:web负载均衡

负载均衡器可以是硬件产品如F5 负载均衡器,也可以是另一个带有负载均衡插件的web服务器。简单的带有ipchains的linux box也可以执行负载均衡的功能。无论何种技术,负载均衡器通常有以下特性:

*实现负载均衡算法
当 客户端请求达到时,负载均衡器决定如何分发请求到后端服务器实例。通常的算法包括Round-Robin,(指的是使组中所有成员都能均等地以某种合理的 顺序被选择到的一种安排方式, 通常是从列表的头至尾,而后周而复始),随机和基于权重。负载均衡器试图使每个服务器实例完成相同的工作量,但以上算法都不能真正达到理想的等量,因为他 们只是基于分发到某个服务器实例请求的数量来计算。一些聪明的负载均衡器实现特别的算法,他们会测试每个服务器的工作负载来决定分发请求。

*心跳检测
当一些服务器实例失效时,负载均衡器应该检测到失效,并不再分发请求到失效的服务器上。负载均衡器也需要监视服务器恢复状况,并给它重新分发请求。

*会话粘连