Fabric3,一款新的服务组件架构(SCA)的开源实现,最近发布了其1.5版。
该版本基于已经实现了OASIS SCA 组装规范V1.1的1.4版本之上,在此之外还提供了以下新特性:
InfoQ有幸采访了Metaform Systems的创始人暨SCA规范的功臣Jim Marino。
InfoQ:您能从解释为什么我们需要SCA开始吗?我们已经有J2EE、.NET、Web服务、REST、JMS等,为什么我们还需要另一种规范/实现呢?
JM:整体上说,SCA让分布式应用的编写更为简单,并且它让之前难以实现或不可能实现的很多能力成为现实。SCA是使能并管理分布式应用的基础。因为这种说法相当模糊,所以我将尽力通过解释SCA与你所提到的那些技术之间的关系来让这种说法具体化。
首先,SCA与Java EE的关系是多方面的。SCA与很多J2EE的API(如JPA和Servlets)配合得相当好。举例来说,我们在Fabric3中提供了实体管理注入、持久上下文管理以及基于Hibernate的透明事务管理的集成。Hibernate与JPA是Fabric3中访问关系型数据的最流行的方式。
从编程模型级别,SCA提供了与EJB以及其他编程模型等之外的又一选择。由于这些编程模型都是围绕依赖注入而设计的,所以他们没有本质的差别。但是,SCA的编程模型特别注重异步编程以及为更好地处理远程服务调用而提供的便利。而且,SCA规范小组还正要增加一项支持,也就是将发布订阅模式直接加入到该编程模型中。我认为它的加入将带来很多重要的附加能力。
SCA还带来了J2EE和其他技术不具备的关键特性——装配和策略。装配是一种通过本地或异地的服务构建应用系统的方式。这一点非常类似与Spring的应用上下文,它是一种连接应用程序不同部分的方法。然而,不同于Spring的应用上下文,装配可以是分布的,而且可用于描述跨应用的连接。装配带来另一特性是模块化。在装配中,服务可由其他服务组装而成。这使得开发者可以在低层次的模块化系统(如OSGi)之上设计模块化应用架构。
装配的确很强大,它不仅能描述单个应用的组合,还能描述企业内的一组服务,它们可以是细粒度的服务也可以是非常粗粒度的服务。我们使用Fabric3 中的该特性对装配进行分析,确定服务的中间件需求,并且动态地提供相应的运行时基础设施。它还可用于依赖分析,从而能确定哪个客户端在使用服务, 或者SLA是否满足。由于分布式系统已发展成含有数千计的服务,所以由装配提供的信息将更好地用于这些服务的管理。
SCA提供的另一关键特性是是跨应用的策略。SCA提供了定义诸如安全类型以及SLA等的策略的能力,这些策略能够跨应用系统使用。其他编程模型一般都需要开发者为每个端点配置策略,这件事可能非常复杂、容易出错而且繁重。SCA使得策略只需一次定义,却可以通过“推”或“拉”的方式得到重用。“拉”的机制可以通过在Java注解(Annotation)中引用策略别名的方式开启。“推”的机制可以理解成是一种“分布的”跨语言的AOP。通过这种机制,人们就可以定义策略和基于XPath的查询表达式,查询表达式在装配过程中被解析并决定在何处应用策略。该机制的一个例子是“为所有部署的Web服务端点开启X.509认证”
上述这些表明,SCA的确利用了很多现有技术。Web服务(或更具体点,WS-*)用于提供互操作性。这对于需要向外暴露的SCA服务而言非常重要,比如用.NET编写的客户端。JMS可用于服务间的消息传输,它对于需要可靠性的场景非常重要。Fabric3还使用JAX-RS为SCA应用提供了一个RESTFul的门面。
我把.NET放在最后说,因为它与SCA的关系是最有意思的。不同于J2EE,SCA被设计成跨语言的。Windows通讯基础(WCF)是.NET使用的基于服务的编程模型,它是由类似于SCA的需求发展而来的。换句话说,微软希望创建一个适用于创建分布式的,基于服务的应用需求的简化的编程模型。如果将WCF服务与SCA组件做个比较的话,你会发现他们非常相似。事实上,二者的大多数概念都能直接映射。
然而,.NET(更具体地说是WCF)所缺乏的是装配的对应。目前,WCF的服务视图是非常“自治的”,它们是孤立地创建,配置和部署的。SCA的装配可用于组装WCF服务。事实上,我觉得从SCA的角度,“微软比其他基于Java的(支持SCA的)提供商做得更好”的说法并不牵强。他们有CLR,它是跨语言的而JVM却不能。此外,.NET是应用开发的一款非常完整的端到端平台。如果.NET版的SCA被开发出来,它将可能成为比基于Java的平台更完整,更完善的选择。
当然,另一方面,SCA装配代表了现有.NET产品不具备的一项创新。微软对此的反应值得关注。
InfoQ:您能描述一下Fabric3中都支持哪些SCA规范呢?下一版还会有什么?
JM:当然可以。Fabric3当前支持SCA装配、策略、Java,Web服务绑定、HTTP绑定和JMS规范。
我们正在做的并将在下一个版本中发布的两个关键特性是对消息传输(发布/订阅模式)及Spring的支持。前者将使得使用SCA创建基于事件的架构成为可能, 而且将复杂的事件处理集成到应用中也会更加简便。我们在金融服务行业中的很多用户准备利用这项功能更进行市场数据分析。对Spring的支持使得SCA能够把Spring的Bean连接到远程服务。
我们还对运行时设计有很大投资,让其利用虚拟和基于云的环境所带来的优势。不同于很多“遗留”中间件提供商,我们不对现有中间件进行改造使之适应这些(遗留)环境。而是向前看,我们关注与Amazon EC2设施的集成,比如用于基于消息的服务连接的SQS以及非基于多播的集群。
InfoQ:除了SCA,Fabric3还提供了那些特性?你是如何针对这些特性作出决定的。
JM:Fabric3提供了一组通常可以在商业中间件产品找到的特性,包括:
可以说以上这些特性都是企业级软件所需的。Fabric3还提供了很多创新的特性,包括动态连接与策略。应用程序能够在不影响服务中正在发生的交互的前提下被更新或重新连接。另外,如SLA策略可以在服务部署之后被“添加”到服务之上。
Fabric3可以配置成自动根据应用程序需求提供运行时扩展。举个例子,Fabric3能够发现一些服务使用了Hibernate,并在服务部署时自动向集群节点提供 Hiberenate运行时扩展。该过程是完全动态发生的,根本不需要重新启动服务器。类似地,当一个应用被卸载时,如果其扩展在节点上不再需要时,服务器也会自动移除它。
我最喜爱的特性是运行时扩展。Fabric3是围绕模块化内核而设计的,在内核中,诸如对远程传输和事务的支持这样的能力都是以扩展的方式加入的。有趣的是这些扩展实际上并未“超出”SCA的范围。我们对运行时进行了设计使其成为一组SCA服务。Fabric3有一个很小的启动程序,它读取SCA装配图,并连接服务与创建运行时。这意味着运行时是在编写SCA“应用”并将其部署到特定的运行时域时被扩展的。正因为如此,动态更新运行时才成为可能,它基本上等同于部署一个终端用户的应用
一旦我们完成了对事件的支持(在Fabric3中源码中有一个初级的实现),我们将能够创建并利用时间流的运行时。到那时,就能实现对运行时事件执行复杂的事件操作和让Fabric3根据各种环境条件进行调节。
InfoQ:你能把Fabric3与其他流行的SCA实现做个比较吗,如Tuscany?
JM:Tuscany项目在帮助SCA的采用方面做了一项很好的工作。一个标准有用多种实现(特别是多个开源实现)是件好事,因为这为用户带来了更多选择,而且还可以通过竞争来激发创新。
即便如此,我显然认为Fabric3有很多优势。这些优势已我前面提到的企业级特性为核心,如扩展性、动态连接与方便使用等等。Tuscany由IBM领导,他们的业务模型通常是诱导客户购买基于开源软件之上的提供了企业级特性的产品。所以,他们的定位与我们不同,所以将来很可能也有不同的方向。
InfoQ:Fabric3提供了与BPEL引擎的集成吗?你认为SCA与BPEL的关系是怎样的呢?
JM:是的,我们有一个商业伙伴正在使用Fabric3作为他们的BPEL产品的SCA平台。另外还有一个Fabric3的开发者正致力于与Apache ODE的集成, 但目前还不能用,因为此项工作目前还在进行中。
至于SCA与BPEL的更为广泛的关系,前者允许服务通过使用BPEL而创建。二者之间的集成有很多值得提及的好处。从SCA的角度看,它是的开发者可以使用BPEL语言去实现面向流程的服务;从BPEL的角度,SCA提供了连接应用的一部分(这部分更适合于传统的编程语言如Java)的便利的方式。举个例子,若没有SCA,从BPEL访问Java代码必须要使用Web服务或私有的提供商机的集成机制。SCA对此做了标准化,使得访问Java时免除了负担及复杂的Web服务,并提供了将BPEL和Java组件部署在一个单元的方法……
InfoQ:Fabric3在自动部署方面有什么特别的特性。
JM:Fabric3提供了一组高级的部署特性。如我前面提到的,Fabric3可以跨多个集群向节点自动提供应用程序包,这也包括了依赖关系。此外,因为运行时是使用SCA创建的,所以还可以使用相同的机制为应用程序提供所需的运行时扩展(及其依赖)。
我们在1.5版中加入的另一有意思的特性是基于补偿的部署。如果某次部署失败,那么该节点就会回滚到其之前的状态。在J2EE中,由于部署单元几乎都是自治的,所以这并不是一个什么难解的问题。然而在SCA中,一个应用中的服务可能连接到另一个应用中的服务,维护运行时的一致性就颇具挑战了。例如, 如果一个应用部署失败,对另一应用中的服务所做的任何更改(如动态连接)都必须要取消。Fabric3使用了一种基于记忆补偿的方法来回滚更改,其结果是运行时总能处在一致的状态。
InfoQ:Fabric3的实现是如何解决负载均衡以及故障恢复的呢?
JM:Fabric3中的负载均衡是在传输层处理的。对于Web服务和POX,Fabric3依赖于HTTP的负载均衡。对于消息传输,F3依赖于消息提供者的能力, 如JMS的实现。
对与无状态服务,其故障恢复非常直接——Fabric3对服务器进行集群所以不需要做什么特别复杂的事情。我们正在做的一件事是支持集群的单例服务。我们的目标是让用户能通过注解(annotation)和定制的SCA范围来指定集群的单例服务。
会话服务显然要复杂得多。我们所使用的BPEL实现依赖于数据库来复制状态。虽然然在我们掌控之中,但我们目前还没有实现基于Java的会话服务的故障恢复能力。
InfoQ:Fabric3的实现中支持哪种版本控制?
JM:对于工件的版本控制,Fabric3依赖于SCA的输入/输出(import/export)机制,它部分建立于OSGi之上。对于Java工件,SCA支持OSGi的版本范围。对于基于XML的工件,如WSDL和XSD,SCA允许归档(被称为贡献[contribution])输入和输出名字空间(namespace)。如果一个贡献(contribution)输入了一个命名空 间,它将被匹配到输出了该命名空间的其他贡献(contribution)上。在输出贡献(contribution)中的在该名字空间下的工件会对输入贡献(contribution)可用。要为XML工件定义版本,版本必须要包含在名字空间的声明之中。所以,SCA的输入/输出(import/export)机制是OSGi输入/输出特性的子集。
对于服务的版本控制,Fabric3支持将一部服务部署到多个端点。还可以通过ESB仲裁的方式通过一个端点代理多个服务的多个版本。对于后一种方法我们做得不多,但是Fabric3的架构支持它。
InfoQ:Fabric3提供了何些工具?
JM:没有直接的工具。然而,现在Eclipse STP项目在其建模工具中支持了Fabric3扩展语法。我们还打算在策略定义的支持上紧密合作。
我还应该提到IntelliJ所具备的对于SCA XML装配的很好的重构能力,如当类或其所在包变更时,在XML中的自动进行重命名。我认为这仅仅是一种“凑合用”的特性。因为我不知道JetBrains正在做某种具体的SCA集成工作,这可能只是某个优雅且通用的IDE设计中的一个用例而已。
InfoQ:如果用户向感受一下Fabric3你有和建议。
JM:从我们的例子开始并订阅我们的用户列表。我们的目标是建立一个使用Fabric的有益且友好的氛围。
查看英文原文: Jim Marino on Fabric3 1.5 Release