Shoal 是一个基于 java 的动态集群框架,为构建容错、可靠和可用的 Java EE 应用服务器提供了基础架构支持。它还可以插入到需要集群和分布式系统支持的任何 java 应用中。Shoal 是 GlassFish (v2 及后续版本)和 JonAS 应用服务器的集群引擎。
Shoal 框架提供了客户端 APIs 以发出如运行时集群成员的增加或减少这样的事件。一个成员可以以核心成员(其失败会被通知给集群中所有其他的成员)或旁观者成员(其失败不会被通知给集群中其他成员,但它会收到其他核心成员的所有通知)的方式加入到组中。Shoal 的核心服务是组管理服务(Group Management Service——GMS),它给客户端(JVMs)提供了一个组消息句柄,使其可以向组或集群中特定的成员发送消息。Shoal 还提供了其他一些非常棒的特性,例如面向恢复的信号及支持,自动恢复成员选择( Shoal 自动委托恢复初始化)和失败保护操作。
java.net 网站上最近有一篇文章讨论了Shoal 框架的架构以及如何将它集成到java 应用中。InfoQ 与Shoal 框架的合作者Shreedhar Ganapathy 和Mohamed Abdelaziz 讨论了该产品当前的特性以及未来的发展路线图。InfoQ 问到Shoal 与其他的开源JVM 集群框架像 Terracotta 相比如何。他们说 Terracotta 采取了非基于 API 的字节码增强方式,这对于数据复制难题给出了非常好的解决方案。Shoal 的集群方式来自于一个容错的基础架构。它提供了一个组事件通知模型使得消费应用程序(consuming applications)可以解决分布式系统领域中的很多难题包括数据复制。他们解释了其开发团队如何使用 Shoal 来解决 GlassFish 服务器的特定集群需求。
以我们为例,GlassFish 需要能满足若干个 GF 组件的集群解决方案,例如 IIOP 负载平衡,Session 复制模块,事务服务模块等等。在 IIOP 负载平衡的情况下,需求如下:当一个失败产生时,orb 应该让其远程客户端对集群中的其他成员也产生失败的结果。连接到特定实例的 orb 的远程客户端会通过 Shoal 的事件通知机制得到动态的集群变化信息以及 IIOP 端点地址。
在事务服务模块的情况下,需求如下:根据一个失败成员的事务日志,从一个远程集群成员中执行自动的事务恢复操作以使得在失败时刻未完成的事务得以完成。为了支持上述特性,我们提供了一个恢复服务器选择通知 (recovery server selection notification)以及失败防护支持。
对于 Shoal 中的“组通信(Group Communication)”模块与其他的组通信框架如 JGroups 相比的问题,他们回答如下:
组通信服务提供者提供了一套 API,对各种组通信提供者实现提供了支持。默认情况下 Shoal 使用 JXTA 框架。如果遵循服务提供者 API,我们可以换成其他的实现,因此可以采用 JGroups、基于 Appia 或者基于 JINI 的组通信提供者。 JXTA 不需要指定单独的 TCP 和 UDP 传输就可以进行通信,并且它还不限于 IP(支持 RF,BT 等)。当在集群中的进行广播时,JXTA 可以动态决定向集群成员发送消息的最佳方式,这是通过 IP 广播和虚拟广播来实现的。
Shoal 中基于 JXTA 的提供者利用了 JXTA 所提供的同层寻址的位置透明性,这是因为组成员是由其名字来标识的,该名字被散列后映射为一个 128 位的标识符。该标识符被链接到网络上,向成员显示所有物理和虚拟地址,这样就可以支持容错性、灵活性和非 ip 传输。这简化了集群内的连通,我们可以通过组或者实例名来定位集群、套接字和消息通道。此外,名称模式被扩展到通信通道,这样就可以虚拟化实例(例如,可以对一个具体的应用服务使用名称而不是端口号)之间的寻址。JXTA 上的 TCP 传输通信完全是基于 NIO 的,因而能够提供可伸缩的消息处理和吞吐量。JXTA 还支持认证和授权,提供了端到端的安全性。两位作者还对 JGroups 框架中可靠的广播特性进行了评论:
JGroups 是一个著名的组通信提供者。我们喜欢 JGroups 的众多原因之一是它提供了一个非常好的可靠的广播栈。然而当前的 JXTA 提供者尚未提供可靠的广播,我们正在评估开源的实现机制以提供高效和轻量级的可靠广播。JGroups 中其他的不同点包括 RPCDispatcher ,这对于在 UDP 上模拟受阻塞的消息是非常有用的。
InfoQ 问到了“虚拟广播通道(virtual multicast channels)”以及在一个典型的 JEE 集群应用中它们是如何工作的。
虚拟广播通道是一种抽象,对跨越正常广播边界的通信提供了支持。典型地,当用户需要跨越几个子网的集群或者是广播被禁用时,他必须请求网络管理员允许在指定 sockets 上的指定路由器上进行广播通信。JXTA 的虚拟广播支持组之间的无缝通信而不必改变网络或者应用。用户仅仅需要指定一些成员作为冗余的路由主机,他们可以作为软件路由器将信息路由到其他组成员。它的工作方式非常类似于 IGMP ,仅仅需要将一个虚拟广播组加入到指定的路由节点中,接下来就可以利用这些路由节点来传播集群中的消息——这是模仿了交换机的工作方式。此外在可能的情况下可以采用 IP 广播。考虑下面的情况:你只在一个子网中进行广播,这时将一个或者几个组成员配置为路由主机使得子网外的成员可以通过 TCP 进行组通信,而子网内的成员仍旧使用广播方式通信。这对地理上分布的集群的基于 WAN 的部署提供了基础(下个版本将提供对基于 WAN 的部署包括跨防火墙的支持)。
关于集群应用中 session 的复制问题,InfoQ 问到是否可以使用 Shoal API 来对 web 应用,集群 EJB 和 JMS 组件中的 HTTP session 进行复制。他们说:
GlassFish 应用服务器中的 EJB 容器、事务服务、定时服务、Orb、Session 复制模块以及其他组件都使用了 Shoal 来与集群中的成员进行交互。用户可以将 Shoal 用于集群几乎任何产品:JMS(MQ clusters)、数据库(指 Postgres 或者 MySQL 集群),甚至进行 CVS 和 Subversion 的集群。
Shoal 框架还有一个叫做分布式状态缓存(Distributed State Cache,DSC)的共享分布式存储特性,它可以用来在内存中对应用的状态进行分布式缓存。GMS 为轻量级复制缓存提供了一个默认实现。Sreedhar 将 DSC 与其他的 java 对象缓存框架如 JBossCache 、 OSCache 和 EHCache 进行了对比.
Shoal 中的分布式状态缓存是一个接口,针对该接口可以有多种实现。默认实现是一个简单的共享缓存,可以处理轻量级消息传递如配置数据、组状态机等等。它不适合进行高吞吐量的缓存,也不支持基于 LRU(Latest Recently Used)的缓存校验与分布式的锁语义。
最近在设计和实现可伸缩应用架构时,网格和云计算得到了越来越多的重视。InfoQ 问到在网格计算架构中 Shoal 框架扮演了什么样的角色。他们解释了为何 Shoal 很适合构建这样的解决方案:
Shoal 提出了一个组长(组长依赖于其下的组通信提供者)的概念。在失败时(这同样依赖于组通信服务提供者)组长有相应的继任者。系统通过实例名称映射来动态和独立地推选出组长和继任者,这会降低网络传输并加快系统的构成,此外还能减轻网络分区症状(split brain syndrome)。一旦这两个基本需求得到了满足,我们会很清楚地看到组长是称职的计算网格的任务管理者。加上 JXTA 对于虚拟广播和跨子网的支持,我们可以扩展集中资源孤岛的概念,它可以执行任务并向主线组长报告结果。服务位置透明性也对资源的移动提供了支持,这意味着网格可以基于可用性扩展或收缩,必要时还可以移动。想想几个 Blackbox 项目数据中心托管在一个网格的情况。 Shoal 的另一个使用地方是作为一个计算网格应用的底层引擎。 FishFarm 项目当前正使用 Shoal 做这个事情。
最后根据新版本以及即将增加的一些特性,InfoQ 问到了 Shoal 项目未来发展的路线图,他们回答如下:
当前我们正从事于 Sailfin 的电信应用服务器项目的支持工作,这包括了一个负载均衡组件。我们未来的计划是提供一个基于分布式缓存的数据网格解决方案。
利用 GMS 服务,Shoal 可用于动态服务器供应,因此可以根据负载情况在失败时采取适当的动作以提供更多的资源。Shoal 是双重许可的:基于 CDDL1.0 和 GPL v2 协议(除了类路径)。
查看英文原文: Java Clustering Framework Shoal Provides Fault Tolerance and Distributed State Cache
译者简介:张龙,同济大学软件工程硕士,现就职于理光软件研究所。主要从事文档工作流和办公自动化解决方案的研发工作。热衷于 Java 轻量级框架的研究,对敏捷方法很感兴趣。曾有若干年的 J2EE 培训讲师经历。参与 InfoQ 中文站内容建设,请邮件至 china-editorial[at]infoq.com 。
评论