性能问题


考虑一下这样的场景:一台 Web 服务器可能驻留了很多 Web 应用,每个 Web 应用都同时有几百个并发用户,每个用户将生成特定的浏览器会话。所有这些会话信息都将被备份下来以防服务器实例失败。更有甚者,会话时时刻刻都在改变:会话创建、过期;会话中的属性添加、修改与移除;为了判断会话何时过期,会话最后修改时间也随着访问时间而改变。所以性能就成为会话失败转移解决方案中的关键问题。厂商总会为你提供一些可调参数来对服务器行为进行调节来满足系统性能的需求。


 


何时备份会话


当客户端处理请求时,会话数据每次都会改变。由于性能因素,并不能对会话进行实时备份。选择备份频率是相互权衡的结果。如果备份动作过于频繁,性能就会受到很大影响;但是如果备份动作的间隔时间太长,则当服务器失败发生时就可能丢失更多会话信息。对于所有的备份方案,包括数据库和内存复制方案,都可采用以下几种常用的选项来决定备份频率:


  • 根据Web方法。

会话状态是在每个 Web 请求的最后,在向客户端返回应答前备份的。这种模式最大程度保证了在失败时的会话信息是最新的。


  • 定期

会话状态定期进行备份。这种模式不能保证会话信息处于最新状态。虽然如此,这种方法能提供卓越的性能提升因为并不是每个请求都对状态进行备份。


 


备份粒度


 


在备份会话时,也需要决定到底保存多少会话信息。不同产品采用的办法通常有:


  • 全会话

每次都备份整个会话状态。这种模式提供了对会话数据正确备份与分布式 Web 应用的最佳保证。这种方法简单易行,在内存复制方案和数据库持久化方案中都是缺省选项。


  • 修改过的会话

如果会话修改了,就备份整个会话。如果调用了 HTTPSession.setAttribute() 或 HTTPSession.removeAttribute() 方法,则就会话就被修改了。虽然 Java EE 的规范没有明确规定一定要使用这两个方法对会话进行修改,但为了保证集群工作正确,必须确保用这两个方法去修改会话。只备份修改过的会话降低了会话备份的数量。在备份间隔期间只进行了读操作的会话并不进行重新备份,这就比全会话备份模式的性能更好。


  • 修改过的属性

这种情况只备份修改过的会话属性。这就进一步将备份的会话数据降低到了最小程度。本方法是网络通信量最小,性能最好的方法。为了让采用本方法的集群工作正常,必须遵循一些规则。首先,每次对会话状态的修改都要调用 setAttribute() 方法,仅仅是被修改的对象被序列化并备份。其次,确保属性之间没有交叉引用。每个键 (key) 对应的不同对象是分别被序列化和备份的。如果交叉引用的情况存在,序列化和反序列化的可能错误。例如,在下图中所示的内存复制集群中有一个 “school” 对象和 “student


” 对象在会话中,并且 school 对象有一个针对 student 对象的引用。 School 对象在某时刻被修改并被备份到备份服务器。在序列化和反序列化后,恢复了的 school 对象将保存引用到 student 对象的引用。但是 student 对象和 school 对象是分开修改的,当 student 对象被恢复到备份服务器的内存中后,它也失去了和 school 对象的连接。虽然本方法带来了最佳的性能,上述的局限性对 Web 应用架构和设计的影响相当大,尤其是如果需要使用会话存储复杂结构的数据。


 






 


其他失败转移的实施方法


 


在我上一部分的描述中,备份的粒度对于性能是非常重要的。然而,现在的实施办法 ( 数据库持久化和内存复制的方案 ) 都是使用 Java 对象序列化技术来传输 Java 对象。这种方法是重量级的,会影响系统性能并局限 Web 应用的架构和设计。一些 Java EE 的厂商在寻找特殊的途径来实现轻量级的,小如指印的模式,并同时提供合理粒度的分布式对象共享机制来提升集群的性能。


 


JRun Jini


JRun 4 使用 Jini 技术提供了内置的集群解决方案。 Jini 是分布式计算的产物,它支持创建在单一分布式计算空间中设备和软件组件的 “ 联邦 ”(federation) 。 Jini 提供了如查找、注册和租借的分布式系统服务,在集群环境下非常有用。另一种叫 JavaSpace 的技术也构建于 Jini 上提供诸如处理、共享和移植的功能,同样在集群实现中具有相当价值。


 


Tangosol 使用分布式缓存


Tangosol Coherence 提供了分布式数据管理平台,它可通过将目前流行的 Java EE 容器嵌入其中来提供集群环境。 Tangosol Coherence 同样也提供了分布式缓存系统将分布在不同 JVM 实例中的 Java 对象高效地共享起来。