Web
层集群实现
Web
层的集群技术是
Java EE
集群技术中最基础且最重要的部分。
Web
集群技术包括:
Web
负载均衡与
HTTPSession
失败转移。
Web
负载均衡
Java EE
的供应商通过多种方式实现
Web
负载均衡。总的来说,负载均衡器在浏览器和
Web
服务器之间进行监听,如下图:
诸如
F5
负载均衡器这样的硬件产品可以担当这个工作,也有可能是一个有负载均衡插件的另一个
Web
服务器。无论使用什么技术,负载均衡器通常具有以下特点:
- 实现了负载均衡的算法
当客户端请求到来时,负载均衡器决定将此请求分发到后端的哪台服务器实例上。经常使用的算法包括轮询、随机和基于权重的算法。负载均衡器试图均衡每个服务器实例上的工作负载,但上述算法都不可能真正实现理想的均衡,因为他们仅仅考虑到了分发到特定服务器实例的请求数量。使用复杂算法的负载均衡器通过特殊算法在分发请求之前将探测每台服务器的工作负载。
- 心跳线检查
当某个服务器实例失败时,负载均衡器需要检测到该失败并取消分发到该实例的请求。负载均衡器也需要监控失败的服务器何时重新开始服务,并开始对其分发请求。
- 会话持久
几乎所有的
Web
应用都使用会话状态来记录诸如登录、购物车等信息。因为
HTTP
协议本身是无状态的,会话状态需要保存起来并与浏览器会话关联。在负载均衡的状态下,最佳选择是将请求分发到与该浏览器会话的上次请求同一的服务器实例上。否则,可能会导致应用工作不正确。
因为会话状态是在
Web
服务器实例的内存空间中存储的,所以
“
会话持久
”
就相当重要了。但当一个服务器实例失败后,所有该实例中的会话信息就会丢失。所以,我们即需要会话的失败转移。
HTTPSession
失败转移
主流的
Java EE
供应商都实现了
HTTPSession
失败转移。如下图,当浏览器在第一和第二步访问有状态的
Web
应用时,在该服务器的内存中会创建会话对象。与此同时,在第三步将能唯一确定会话对象的
HTTPSession ID
发送至浏览器。浏览器将该
ID
作为
cookie
存储,并在下次请求该
Web
应用时将此
cookie
发送至
Web
服务器。为了支持会话失败转移,
Web
服务器中的会话对象将被备份下来
(
第四步
)
,以备服务器失败时防止会话信息丢失。负载均衡器将检测到实例的失败
(
第五步和第六步
)
,并将后续请求分发到其他服务器实例上
(
第七步
)
。由于会话对象已经被备份下来了,处理请求的新服务器实例就能恢复该会话的信息,继续正确处理会话。
要实现上述功能,需要引入以下内容:
- 全局HTTPSession ID
上面已经讲过,
HTTPSession ID
用来标识特定服务器实例中的内存会话对象。在
Java EE
中
,
HTTPSession ID
根据
JVM
实例来产生。每个
JVM
实例能驻留多个
Web
应用,每个应用能为不同的用户保存
HTTPSession
。
HTTPSession ID
是在当前
JVM
实例中访问相关会话对象的关键。在会话失败转移的实现中,不同的
JVM
实例不能生成相同的
HTTPSession ID
。如若不然,在失败转移发生时,就不知道哪个对象是应该恢复的对象。所以,需要引入全局
HTTPSession ID
机制。
- 备份会话状态的机制
后续的描述中会有这方面的内容。将来我还着手写一片比较各主流服务器中会话备份机制的具体实现的文章。
- 备份频率和粒度
HTTPSession
状态的备份会造成额外开销,比如
CPU
时间周期、网络带宽和磁盘或数据库
I/O
。备份操作的频率和粒度的选择都可能影响集群的性能。
数据库持久化办法
一些的
Java EE
集群产品都支持使用
JDBC
通过关系型数据库备份会话状态。在下图中,显示了该方法仅需让服务器实例序列化会话内容并在适当的时候将他们保存在数据库中。当失败转移发生时,另一可用的服务器实例接管失败的服务器实例,并从数据库中恢复所有的会话状态。对象的序列化是其中的一个关键点,这样内存中的会话数据就可以得到持久化并可进行移植。
通常,执行数据库的事务会造成一些额外的开销,所以本方法的主要缺陷在于当并发数据量较大时可能无法提供需要的可扩展性。大部分采用数据库会话持久化方法的应用服务器供应商都建议尽量减少
HTTPSession
存储的对象,但这又可能影响到
web
应用的架构和设计,尤其是在需要使用
HTTPSession
存储用户数据的时候。
采用数据库持久化方法的优点在于:
- 易于实现。
- 由于数据库对集群中的所有节点都共享,所以,可以实现对会话数据的失败转移。
- 即使在集群的所有节点都瘫痪的情况下,会话数据依然能够得到保留。
内存复制办法
Tomcat
、
JBoss
、
WebLogic
、
Websphere
之流的
Java EE
服务器都提供了另一种实现:内存复制。
在上图中描述了使用内存复制技术来实现会话状态备份的场景。本方法的性能很好。之余数据库持久化技术,在原服务器和一台或多台备份服务器之间进行直接内存复制对网络通信的影响很小。但是,不同厂商的服务器对内存复制技术的应用方式不同
(
在下面有具体描述
)
,有的厂商采用的技术就不再需要
“
恢复
”
的过程了,即会话数据备份时已驻留在备份服务器的内存中,当备份服务器接管时,所有的数据已经存在。