首页 > 范文大全 > 正文

REST与SOAP的冲突

开篇:润墨网以专业的文秘视角,为您筛选了一篇REST与SOAP的冲突范文,如需获取更多写作素材,在线客服老师一对一协助。欢迎您的阅读与分享!

实际上SOAP和rest所针对的领域并不完全重叠,但是如果我们把问题聚焦于web开发领域,就会发现两者的区别甚至冲突。在这个领域,它们都试图解决同样的问题:应该如何提供Web服务?

对于web服务,W3C将其定义为:“服务提供者完成一组工作,为服务使用者交付所需的最终结果。最终结果通常会使使用者的状态发生变化,但也可能使提供者的状态改变,或者双方都产生变化”,这段定义引发了第一个分歧。

服务提供者状态

这事实上是一个风格而非架构问题,REST规定服务提供者必须是无状态的,而使用者的状态应该随着“服务提供者交付的最终结果”而变化,这意味着客户端必须在请求中包含处理此请求所需的全部信息,REST认为这样可以增加服务的可见性(visibility),可靠性(reliability)以及可伸缩性(scalability)。

可见性得到增强是因为现在服务端不再需要查找请求的上下文就可以直接处理它,每个请求都是自描述的,这意味着服务端更容易理解请求。可靠性得到增强则是因为这样可以大大减少局部错误的发生几率以及从局部错误中恢复的工作量。 可伸缩性得到增强则是因为服务端现在不再需要在请求间保持状态,所有资源都可以在处理完一个请求后立即释放,因此服务端不需要维护一个跨请求的资源管理模块,这大大简化了服务端的实现。

但不利的方面是增加了网络负担(因为请求可能需要传送额外的数据),同时服务端对应用的控制也被减弱,因为现在服务端必须依赖于客户端是否正确的实现了REST的语义。

soap则没有对状态迁移作出规定,因为SOAP是个架构,而这不属于架构的范畴。

对Web的不同理解

REST认为Web本身就是一组资源的集合,因此,Web服务本质上就是对资源的访问。

而SOAP最初是作为简单对象访问协议被提出,但随后被扩展为一个通用XML消息处理框架,因此,在SOAP看来,Web服务就是一组消息的交互,而Web只是用来承载这一交换过程的一个中间载体。

根据Berners-Lee(Web的创造者之一)对Web的定义:“Web的主要目的在于提供一个信息共享空间,人和机器都可以通过它来沟通”。也就是说,Web最初是被设计为一个信息共享平台,它所要解决的主要问题是使人们可以很轻易地制作、以及阅读他人的信息,这就要求信息之间既要相互独立又必须保持某种联系,为了实现这个目标,Web最终被设计成了一个易于使用且可扩展的分布式超媒体系统(HTTP+HTML)。

作为HTTP协议的起草人之一,以及Apache Web服务器开发者,Roy Fielding(REST的提出者)对Web的理解显然要更深刻一些。Roy认为Web服务的部署必须考虑Web作为一个易于使用且可扩展的分布式超媒体系统的特点,因此REST并不是一套全新的Web服务架构,它只是为Web服务施加了一系列的约束,以增强其组件间交互的可伸缩性,接口的通用性以及组件的独立性,从而使其更好的适应目前的Web架构。

但SOAP对Web的使用却是明显违背Web设计者的这一设计初衷的,因为SOAP最初是作为一个RPC规范被提出来的,虽然现在它的含义已经发生了变化,但它的目的实际还是完成消息从一个节点到另一个节点的传递,传递的过程中可能会经过一系列的中间节点,而Web对于SOAP的意义,实际上就是一个用于消息交换的中间节点,甚至于 Web对于SOAP并不是必须的。之所以大部分的SOAP实现都选择绑定HTTP协议,只是因为HTTP提供了一个统一的穿越防火墙的解决方案,而这明显是对HTTP的误用,因为这直接导致防火墙失去了它应有的意义。

由于对Web以及Web服务的认识存在差异,这进一步造成了它们在其它方面的更多分歧。

URI的使用

前面我们已经讲过,Web是一个超媒体系统,也就是说信息之间既相互独立又彼此保持联系,而将它们联系在一起的核心就是URI,URI保证了信息的唯一性以及全局可达性。

REST认为Web就是资源的集合,Web服务就是对资源的访问,资源则是对信息的抽象,资源之间也是彼此独立但又相互联系的,每一个资源都必须有一个URI来唯一标识它。不过资源与信息的区别在于资源可以是动态的,比如“本月最受欢迎菜肴”,可能在7月份是“回锅肉”,但8月份就变成了“鱼香肉丝”,因此我们可以将资源理解为一个函数映射,在不同的时期它会映射到不同的值,甚至可以映射为一个空值,比如“2008年票房最好电影”,在2008年到来之前,这个资源映射到一个空值。不过尽管资源可以是动态的,但它在语义上却必须保持静态,比如“本月最受欢迎菜肴”绝不能够是“可乐”,因此这就要求资源URI必须能够在语义上保证资源的有效性。

同时,传统Web大多是一个个的封闭式系统,因此即使一个资源的URI失效,只要将所有对此资源的引用同时进行修改,就可以保证系统运转正常,但Web服务所面对的却是十分开放的环境,这就使得同时修改对某个资源的引用变得不可能,因此REST要求资源URI必须能在语义上对资源进行清晰的描述,并应该尽量避免改变。对于“本月最受欢迎菜肴”,它的URI就应该是:/food/popular/current而不应该是/food/popular/2007-08。

而SOAP本身并非为Web设计,它只关心消息交换,因此,URI对于SOAP的意义并不大,尽管我们可能经常会像下面这样使用SOAP:

bank = new SOAPProxy(".....")

bank.addMoneyToAccount(account 23423532, 50 dollars)

但实际上SOAP并不关心第一行的URI到底指向哪里,对它来说更重要的是账户号码和转账金额,而这些信息是与服务本身捆绑在一起的,没法通过URI来直接定位不同账户。这在某种程度上带来了一些灵活性,比如SOAP可以由多种传输协议来承载(而不止是HTTP),但是这也带来了一个问题,由于缺少对URI的支持,导致它无法利用一些需要URI支持的技术,比如XLink、XPointer等等。

接口是否应该统一

Web在设计之初一个很重要的目标就是要易于扩展且易于使用,这就要求它所提供的接口必须尽量简单同时要保持一致,因此HTTP被设计为只支持4个方法:GET、POST、PUT、DELETE。

REST认为Web服务的设计也应该遵从这一思想,因为这可以使组件间的交互统一化,增强交互的可见性。但统一接口的缺点在于有可能会降低效率,比如get_x_and_y必须被拆分为两个接口get_x与get_y,这就使得原本的一次交互变成了两次。不过这样的好处要更为明显,组件间的耦合度被减小到了最低,同时,客户端的实现也变得简单,且不需要因为接口的变动而频繁升级。

SOAP则并没有对接口进行限制,这样导致的结果就是随着功能的不断增强,API的数量也变得日益庞大,并且在SOAP中,接口是消息的一部分,这就导致它无法利用HTTP自带的方法,同时,SOAP1.1规范使用POST来发送请求,这使得它和HTTP的语义产生了冲突,虽然SOAP1.2改用了GET请求,但并没有从根本上解决问题(使用HTTP GET来调用一个delete_x的接口明显是不合适的)。

结果的表现形式

REST规定服务提供者必须根据使用者提交的资源URI返回资源的某种表示(可以是HTML,XML,JPEG或者别的随便什么东西)。

SOAP则限定结果必须包含于SOAP消息内,也就是结果只能以XML来组织,而XML并不擅长于二进制数据表示,这在一定程度上限制了SOAP对于结果的表现能力,并且SOAP1.1使用200 OK来返回错误信息,这也同HTTP的语义有冲突。

但实际上很难说这两种表现方式到底孰优孰劣,你肯定需要花上点功夫才能搞定Google Adwords的SOAP API返回的庞大数据,但是要解析Amazon的REST API的返回结果也不是那么容易,所以资源使用的难易程度更多取决于业务,而非结果的表现形式,复杂的业务必然导致复杂的表现。

以上的分歧如果我们对其进行综合分析,就会发现,实际上只有一个分歧,借用SOAP的术语,那就是:究竟哪些东西应该装在信封内,而哪些应该写在信封外面?

如果我们将Web服务看作是一封邮件的话,那么结果无疑是显而易见的,收信人以及投递方式应该写在信封上,其它东西则应该写在信封里面。这跟REST的理念是符合的,而SOAP则将同样的信息同时写在了信封和信纸上,这无疑是一种浪费。

因此,结论就是,对于Web服务来说,REST相比于SOAP的优势无疑是明显的,并且也是趋势,毕竟简单总是更受欢迎。这从目前各大网站的转变就可以看出来,目前Yahoo(包括Flickr以及del.icio.us),Bloglines,Technorati以及eBay等都已经转而采用REST来它们的API,Amazon则同时提供了REST和SOAP两种方式的API,只有Google还坚持只提供SOAP API。

尽管如此,但这并不意味着SOAP会就此消失,以上谈到的SOAP的种种缺陷归根结底还是在于SOAP在设计之初并没有考虑到与Web的融合问题,因此当我们试图将SOAP和Web捆绑在一起的时候,必然会出现种种的不良反应。

但是对于企业应用来说,基于消息的中间件仍然是必不可少的,但REST在大型应用中的表现还有待考验,而SOAP在这方面则具备许多REST所不具备的优势(比如标准化,增强的安全以及路由特性,良好的工具以及厂商支持等等)。