REST会是前段URL未来吗?

浏览:1090 发布日期:2012/12/15 分类:业界资讯
面向 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 设计实现。虽然两种方法都有其优势,但都没有改变最难的部分——定义和企业业务模型一致的业务服务/资源。有些情况的确两种都适合,但归根到底这完全是两 种不同的风格。
评论( 相关
后面还有条评论,点击查看>>