码迷,mamicode.com
首页 > 其他好文 > 详细

REST会是SOA的未来吗?

时间:2015-11-01 00:31:10      阅读:266      评论:0      收藏:0      [点我收藏+]

标签:

好像无论我们到哪儿都能听到这样的说法:REST将会是SOA的未来。很多刊物也将REST和SOAP与WS*[1]标准进行比较,但这些比较看起来都太过简单了。近来出现了两种较为主流的方法——本真REST(true REST)以及将REST作为面向服务的技术方法(又称REST Web服务[2])。本文讨论的重点为:是否其中一种方法能够改进SOA实现。

面向SOA的本真REST

本真REST当然是对面向资源架构的一种实现,而并非一种纯粹的技术决策。所以当讨论本真REST时,真正应该讨论的问题是:其基础支撑——面向资源的架构(ROA)——是否真的适合作为你的SOA实现。

为正确评估该问题,让我们首先回想一下SOA的架构风格,它是基于企业业务架构的功能性分解,并且引入了两个高层次的抽象:企业业务服务和业务流程。企业业务服务代表的是现有IT能力(和企业的业务功能相一致)。业务流程编排业务服务,并定义业务的整体功能。

而REST是一组被称之为面向资源架构(ROA)的架构准则。ROA构建在资源这一概念之上;每个资源都是一个能够直接访问的分布式组件,可通过一个标准的、通用的接口来处理。所以,面向资源的架构(ROA)其最根本的还是一种基于资源的分解[3]

为了评估本真REST是否适用于面向SOA的实现,我们真正需要回答的问题是,“服务和资源之间到底是什么关系?”

服务 vs. 资源

何为服务?

在最简单的情况下,服务可以被定义为一个自包含、独立开发、可部署、可管理和可维护的软件实现,它从整体上为企业提供特定的与业务相关的功能,并且在设计上是“可集成的”。“服务”可以通过动词(verb)来定义(例如,“验证客户信用积分”,这描述了服务实现的业务功能)。

服务并不是某个编程结构或一组APIs,而是一个用于实现企业解决方案的架构(设计单元、实现以及维护)和部署构件。服务接口(尤其对某个给定的服务而言)定义服务功能,并且可由多种方式实现。存在两种基本的定义服务接口的方法——RPC风格和消息(messaging)风格,RPC风格实现使用服务调用语义并且通过服务接口中的一组参数来定义。而消息风格的服务接口被有效地固定(本质上只需要进行“执行”操作)使用XML文档作为输入和输出(这和GoF设计模式非常相似)。在这种情况下,服务语义是由输入和输出消息的语义来确定[4]

过去,服务通常被定义为一组方法的集合,但正如参考文献[2]中解释的那样,这些方法彼此相互独立[5],但作为整体它们共享同一个命名空间,这样简化了对服务的管理。

何为资源?

在最简单的情况下,资源可以被定义为一个可直接访问的、独立开发的、可部署的、可管理的和可维护的软件构件,它支持特定的数据。资源可以通过名词(noun)来定义,比如“医生的预约”就描述了资源提供的数据。某一资源也可以和其他资源相关联并为它们提供引用(链接)。实际上,一个资源就类似于一个对象[6],不过它是带有预定义(CRUD)接口语义的对象。

REST中的语义基于HTTP操作集,如下所示[5]

  • createResource——创建一个新的资源(以及相应的唯一标示)– PUT
  • getResourceRepresentation——获取资源信息– GET
  • deleteResource ——删除资源(可选地包括相关联的资源)– DELETE(只是引用的资源),POST(当需要删除相关联的资源时使用)
  • modifyResource——更改资源— POST
  • getMetaInforatmion——取得资源元数据信息—HEAD

资源通过两部分定义:资源URL和资源所提供的所有操作上定义的输入/输出参数[7]。这和服务不同,服务的方法之间是完全独立,并且能够以独立端点(endpoints)的方式部署,而资源上的方法遵循OO语义,这意味着所有的方法(除createResource以外)都必须依附于底层的某个资源(同一个URL)。

资源和服务之间的根本差异

基于上述对资源和服务的定义,凭直觉它们显然是不同的。我们先继续深究这些差别,然后再讨论它们是如何对最终架构产生影响的。

正如文献[6]中描述的:

REST不仅不是面向服务的,相反,面向服务和REST风马牛不相及

文献[7]中进一步阐明了二者之间的区别:

如果把WS-*比作是互联网世界的RPC,那么REST就是互联网世界的数据库管理系统(DBMS)……传统的基于SOA的集成表现了不同软件构件之间通过各种过程或方法进行交互。REST有效地将每个软件构件看作一组数据库表,而这些构件之间使用SELECT, INSERT, UPDATE和DELETE来通信。(或如你所想的使用GET, PUT, POST, DELETE)。那业务逻辑放在哪里呢?在存储过程中?不太对,其实在触发器中。

这里我们用J2EE打个稍微不太恰当的比方。我们把服务想象成无状态会话bean,而资源想象成实体bean。

服务(或会话beans)作为控制器控制执行所需的操作,不管底层是哪个资源。打个比方,某个支出账户服务可能会用到账户ID、支出金额和支出所需账户。这样的服务可以支出任何现有账户。

资源(或实体bean)充当数据访问机制,其面对给定数据类型的某一实例。比如,为了从某一账户支出,需要先找到这一账户相关的信息,然后才能更新它,从而向所需账户进行支出。另外提醒一下,与能实现任意所需的方法的实体bean不同的是,一个REST资源只有一个更改资源的方法。这意味着真实的业务操作——支出——只能编码成消息请求的一部分。

区别引出的结论

综上所述,不可能使用本真REST来构建SOA系统。构建系统可以,但一定不是SOA。两者都可以从与业务一致的分解入手,但是由于各自使用截然不同的分解方法,它们最终得到的也是基于不同组件和连接器的完全不同的架构风格[8]

仅仅因为它们都试图解决同一个问题——业务与IT对齐,并且都基于业务驱动的分解,并不能表明最终的架构风格也是一样的。

另一个问题在于能否可能使用本真REST来构建一个完整的系统。鉴于上述理由,这个问题等价于能否可能只使用数据库或实体bean来构建一个完整的系统。当然你可以了,但是需要以存储过程(重写方法的本意)的方式增加处理代码,或者触发器(完成基于数据变化的后置处理)。这同样适用于本真REST实现—你只有通过改变modifyResource方法的本意(通常使用命令行模式)来实现不止数据更新这个方法。

因此,某个基于REST的实现和本真REST是大相径庭的;一般来说其包含了至少一些REST Web服务的元素。那么REST Web服务是什么呢?

REST Web服务

REST Web服务方法是指单纯使用REST技术作为通信手段来构建SOA的一种方法。在这种情况下,服务由SOA风格的分解来定义,而基于REST的Web服务[9]作为通信。

虽然一般也被称为REST,这种方法其实和本真REST没有一点关系,倒是和POX(plain old XML over HTTP)很类似,不过与POX不同的是,它不仅支持XML,还支持其他数据类型,比如JSON(JavaScript Object Notation)、ATOM、二进制数据块。而且,它不像POX那样通常只基于GET和PUT,它基于更多的HTTP方法。

归功于Web的优势和Ajax技术的遍地开花,使用JSON逐渐变成主流的方法;大部分流行的浏览器都内置对JSON支持。由于在JavaScript中处理XML(尤其是带有很多命名空间)并不是一件容易的事,所以,Web实现使用基于JSON的REST Web服务要容易的多。面向Web交互的REST Web服务的扩增导致了这些技术的日益流行和广泛传播。

真正的差异是什么?

描述SOAP和REST区别的出版刊物通常会指出如下REST Web服务的优点,比如[11]

  • 轻量级——无需太多额外的XML标记
  • 人工可读的结果集
  • 易于构建——无需工具支持

虽然这些区别很重要(我随后会再详细讨论),但是SOAP和REST最主要的区别在于REST是直接实现于HTTP协议之上,而SOAP引人了一个抽象层(SOAP消息传递),这可以在任何传输协议之上实现。标准化SOAP绑定目前存在于HTTP、SMTP和JMS之上,而非标准化绑定已经在其他一些协议解决方案实现了。这层额外的抽象层(提供协议和基于SOAP实现之间的解耦)是造成SOAP和REST Web服务区别的根源。

对于这一抽象层的看法很大程度上取决于不同的人。REST阵营认为它是过度设计的产物,并声称没有提供任何实际价值。他们声称HTTP已经提供了服务交互实现必需的所有特点。而SOAP阵营,从另一方面,争辩道HTTP并不是服务交互(尤其在企业内部)通常所需的唯一协议,而设计一个方便的、可扩展[10]的抽象层对构建健壮的、功能丰富的服务交互是很有必要的。

虽然两种观点都有其可取之处,但我认为把SOA实现限制到单一协议,即HTTP,实际操作起来不太可行。诚然,HTTP是无处不在,并且其使用方法一般也无需投资额外的基础设施,但是HTTP是不可靠的(HTTP-R没有广泛被采用)、同步的(产生了瞬时的耦合)[11]、而且也没有事务语义等等。

再者,就算认为HTTP是在实现中使用的唯一协议,也可以非常方便的利用SOAP信封把业务信息(SOAP 消息体)和基础设施信息或附加信息(SOAP 消息头)从SOAP消息中隔离。总的来说,如果你本来的实现并不需要任何基础设施或附加数据,整个SOAP信封的开销是很少的——只需两个标签,而且对必要时添加数据提供了明确定义的方法。

所以,从各个方面来看,以数据信封的方式将业务信息和基础设施关注分离是很强大的模式,甚至REST Web服务实现也常常使用这种方法。至于是否使用标准的SOAP还是定制化信封[12]模式要根据具体实现而定。

其他关键不同点

我们花点时间来讨论一下其他一些常常被发表刊物引用的关于SOAP和REST Web服务的不同点。

简单化

一个普遍的观点是REST要比SOAP简单得多。照这个观点,REST简单的根源基于一个事实:REST不需要WSDL或任何接口定义。至少可以认为这种论调有点天真。无论哪种用于服务消费者和提供者之间通信的技术,都必须在语法和其消息交互(接口)[13]的语义上达成一致。这意味着就REST而言,下面两个方法有一个是可能的:

  • 以文本方式定义一个接口,并基于接口文档描述中的通用接口定义来“手工地”编写数据的编码/解码。虽然这种方法常被REST拥趸所推崇,其接口包含的元素很少超过10到15个,但这不是典型的粗粒度REST服务。而且,这种方法很容易出错,所以,大部分可行的REST框架都遗弃该方法而使用下面的方法。
  • 在XSD的层次定义接口,基于流行框架(比如,面向XML的JAXB或Castor,面向JSON负载的Jackson)产生数据的编码/解码。这种方法效果上就是WSDL的简约版,并且需要的工作量和基于SOAP实现差不多一样。事实上,完全相同的方法经常被用于基于SOAP的实现,设计一个单独接口和服务执行的命令模式。WSDL2.0 和/或 WADL for REST就是对该方法的扩展。

另一个SOAP常常被抱怨的就是复杂的WS*标准集。虽然不存在一个单独的规范来罗列这些关键的WS*标准集以及其彼此的关系,但对大部分服务交互用例还是存在一个标准的。就算如此,选择一个适当的WS*标准和其用法可能也需要一些额外理解和实现时间,但是:

在REST和SOA之战中争论简单化还是标准化是荒唐的,因为没有标准支持的简单只能有害于成本和应用的可管理性。

所以,除了那些简单到极点的例子之外,如“温度转换器”,REST并不比SOAP简单多少。

轻量级

另一个众多REST拥趸宣扬REST是SOAP的一种取代的原因是,实际上的REST请求和响应消息都较短。这主要基于两个原因:

  • SOAP需要一层XML包装器来包装所有的请求和响应消息,这会增加消息的大小。这话没错,但重点不是包装器增加了多少字节,而是它创建在整个负载中的比例。因为包装器的大小是固定的,其所占比例随着消息的不断变大而变小,最终可以忽略不计。考虑到一般服务都是相当粗粒度的,请求和回复消息的大小也是相当大的,所以SOAP信封的负载不太会成为大问题。
  • SOAP是基于XML的消息传输,而XML使用冗余的编码。REST,在这方面,提供了更轻量级的消息传输替代方案——JSON[14]。这话也对,但利用消息传输优化机制(MTOM),大部分SOAP框架都支持,可以把消息拆分成多个小的基于XML的SOAP信封/头/体部分,而附加的包含消息内容的部分可以编码为任何MIME类型,包括JSON和二进制流等。

虽然理论上讲,REST要比SOAP轻量级,但实际上,利用一些高级SOAP设计技术,真正使用中的SOAP和REST消息大小的差别是很小的。

易于构建 – 无需工具支持

因为REST基于HTTP,其拥趸认为,我们可以使用熟稔的技术,比如Java servlet API和Java HTTP支持来编写REST服务的实现端和客户端,而无需任何特定工具的帮助。这可以说是对的,但前提是你想要“手工”实现构建输入/输出消息和数据编组。SOAP Web服务也可以实现同样的工作。然而,大家很少希望编写这种样例代码,结果还是会使用工具,SOAP和REST都是。

结论

REST既适用于使用ROA(本真REST方法)的系统设计,也适用于使用REST技术(REST Web服务)的SOA设计实现。虽然两种方法都有其优势,但都没有改变最难的部分——定义和企业业务模型一致的业务服务/资源。有些情况的确两种都适合,但归根到底这完全是两种不同的风格。


[1]看这里,文中有个很好的比喻。

[2]这里我使用的这个词语,从技术上其毫无意义,也不是指REST,但在业界被广泛使用,而有很多人也认为它就是REST。

[3]按照定义,资源可以是任何应该被直接呈现和访问的组件。

[4]这类服务常用的一种实现是基于“命令模式”。一个输入文档定义命令本身和用于执行命令的数据。

[5]方法独立源自于这样一个事实:不同的方法可以执行同一数据——这里指的是无论是否被服务暴露都存在的企业数据,而不是在OO中的针对特定数据的某对象实例。

[6]例如,在文献[4]中对OO和REST做了直接类比。

[7]许多REST倡导者声称后者是没有必要的。我们在文章后面会再回到这个问题上。

[8]架构风格就像面向于不同软件系统之间结构和连接的“设计模式”。文献[10]提供了关于架构风格的一个比较完整的定义,“架构风格是指一组有相同原则和属性的架构”

[9]另一个在业界被普遍乱用的名称——根据定义,Web服务就是SOAP消息。

[10]所有的WS*实现都重度依赖SOAP,尤其是SOAP头。

[11]你总是可以在HTTP上实现异步消息机制,但是需要额外的抽象层,比如SOAP就在其上使用了WS-Addressing。

[12]许多REST倡导者认为HTTP已经有了一组标准的消息头,因此SOAP消息头完全没有必要。这里的问题在于一组预定义好的HTTP头固然有其良好定义的语义,但任何应用特定数据必需一个自定义HTTP消息头,这和自定义SOAP消息头的复杂度相同。

[13]一个有趣例子是,在很多JAX-RS实现中客户端API,其接口往往是一个java接口——许多对多语言的支持。

[14]简单通常意味着高价——所以,要试图通过无需手动编码对象类型而用JSON消息实现多态

REST会是SOA的未来吗?

标签:

原文地址:http://my.oschina.net/JasonZhang/blog/524454

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!