由SOAP说开去 - - 谈谈WebServices、RMI、RPC、SOA、REST、XML、JSON
引子:
关于SOAP其实我一直模模糊糊不太理解,这种模模糊糊的感觉表述起来是这样:
- 在使用web服务时(功能接口),本来我就可以通过安卓中固有的http类(使用http协议),来发送http请求,并且解析返回的数据(一般是xml或者json),得到我要的结果
- 为什么还非得多此一举使用soap呢,而且soap自己的介绍也说,它其实没有发明技术,它其实就是http+xml
- 在安卓中使用soap的方法是:(下载第三方类库),装配一个soap请求体,使用soap包装过的http类,通过http把请求体发送出去,然后解析返回的soap数据,取出里边的xml数据,得到我要的结果
- 所以说人家好好的http,你平白无故在头尾包装一个soap(有点像加一个没有作用的信封,因为HTTP本来就自带信封),这不就是没事收保护费吗,不嫌烦么。(但其实我分析到这发现只是收了一个保护费,我表示还算可以接受吧,毕竟大家都交了)
于是我详细查阅了网上的资料,结合自己的理解,归纳整理如下,引用部分过于零散,就未标示,还请谅解
要好好谈SOAP,就必须从其源头开始,它的源头就是WebServices(Web服务)
1.Web服务
最早的软件都是本地软件,只运行在本地电脑上,直到网络技术诞生它也只是利用网络传送资料,这之后网络技术独自发展网页WEB自己发展了好多年,直到大家发现网络技术不只是用来看看网页,还可以把网络技术更深地应用进本地软件中,深入地跟本地软件的功能结合,拓展本地软件的功能,Web服务的概念就是在这种环境下兴起的。
Web服务 简单地说,,就是服务器如何向客户端提供服务,现有的实现方式可以分为三类:
- SOA 面向服务的架构【面向消息】
- RPC 远程过程调用的架构(remote procedure call)【面向方法】
- REST 表征状态转移的架构(Representational state transfer)【面向资源】
1.1.其他相关概念
RMI
- 使用java的程序员,对于RMI(RemoteMethod Invoke,远程方法调用)一定不陌生,在java中,为了在分布式应用开发时,能够方便调用远程对象,java提供了RMI的API。在 RMI 中,远程对象按照好象它是本地行事,客户机应用程序会直接调用远程对象存根上的方法,因此,调用起来就如本地对象一样方便。RMI中封装了对象和请求的网 络传送,使得异地的对象服务直接可用。
- 但RMI的使用必须是在能够识别java代码的环境下使用,即必须有JVM的支持。因此,他只适合在java程序间的对象通信。如果不在 Java 环境下工作,或者需要与非 Java 环境通信,那么SOAP、RPC、CORAR等都是可以的。.
- RPC(Remote Method Invocation,远端过程调用) 与RMI的区别很明显,相比于RMI直接获取远端方法的签名,进行调用的方式,RPC使用的是C/S方式,发送请求到服务器,等待服务器返回结果。
- 通信方式:远程对象按照好象它是本地行事.客户机应用程序直接调用远 程对象存根上的方法
- 优点:远程对象按照好象它是本地行事,编译期可以检查错误
- 缺点:只能基于java语言。异常信息容易丢失。客户机与服务器紧耦合。
2.SOA
SOA 是前几年炒的很火的一个词, 不亚于当前的 Cloud Computing , 如果说 RPC 是基于方法调用(method),那么 SOA 则是基于 消息, 基于方法调用通常会与特定的程序语言 耦合起来,而后者则与具体的实现语言无关, 所以在一定程度上得到大公司的支持
3.RPC
3.1总览:
- RPC 即远程过程调用, 很简单的概念:像调用本地服务(方法)一样调用服务器的服务(方法).
- 一般的过程是:向服务器发送一个过程调用的方法及其参数,得到服务器返回的方法执行的结果
- 通信方式:一般直接用底层的TCP,这样更加快速,这是相比REST只能用HTTP的优势,但它也可用HTTP
3.2.实现方式:
- XML-RPC
- XML-RPC是一个用XML消息执行RPC的简单协议,服务请求使用XML来编码,并通过HTTP POST发送,XML响应被嵌入HTTP响应主体。
- 在 Web服务发展的初期,XML格式化消息的第一个主要用途是,应用于XML-RPC协议。XML- RPC中,客户端发送一条特定消息,该消息中必须包括名称、运行服务的程序以及输入参数。(相反, REST风格的请求却不关心正在运行的程序是什么,它仅仅请求命名资源)
- JSON-RPC
- JSON-RPC是基于JSON格式的消息交换,JSON比XML更加轻巧,并且非常容易在页面JS中使用,其他特点与XML-RPC类似
- XML-RPC , JSON-RPC的通信方式相同, 所不同的只是传输数据的格式,JSON格式更加易用
- SOAP协议
- XML- RPC只能使用有限的数据类型种类和一些简单的数据结构。人们认为这个协议还不够强大,于是就在使用HTTP的XML-RPC的基础上发展出了更加强大的 SOAP协议,虽然其最初的定义是简单对象访问协议。之后,大家逐渐意识到SOAP其实并不简单,而且也不需要必须使用面向对象语言,所以,现在人们只是沿用SOAP这个名称而已,它经常被用于一些比较复杂的系统之上
- SOAP是在计算机之间交换信息的基于XML的协议,主要侧重于通过HTTP传输RPC。它利用了XML的命名空间和XML模式(XML Schema),比XML-RPC更具适用性,能够支持更多的类型及数据结构。
- 简单的说,SOAP定义了如何将一个对象编码成一种格式并通过一种协议传送到另一个地方并还原的规范。
- 当然很多东西都是现成的,对象编码后的格式是XML,传输的应用层协议是HTTP。 HTTP也并没有定义如何在网络上进行通信,其所使用的是TCP协议,TCP也没有定义在路由之间如何传输包,那是IP协议。
- 但SOAP也不是什么新东西都没有,譬如对象如何序列化成为XML格式,远程过程调用(RPC)如何实现等,都是SOAP协议的一部分。
- XML- RPC只有简单的数据类型集,取而代之,SOAP是通过利用XML Schema的不断发展来定义数据类型的。同时,SOAP也能够利用XML 命名空间,这是XML-RPC所不需要的。如此一来,SOAP消息的开头部分就可以是任何类型的XML命名空间声明,其代价是在系统之间增加了更多的复杂 性和不兼容性。
- 最 初,SOAP是作为XML-RPC的扩展而发展起来的,它主要强调的是,通过从WSDL文件中所获得的方法和变量名来进行远程过程调用。现在,通过不断 进步,人们发现了更多的使用SOAP的方式,而不仅仅是采用“文件”方式(只是使用一个SOAP信封来传送XML格式化文件)。无论如何,要掌握 SOAP,了解WSDL所扮演的角色是最根本的,看后边的WSDL
- SOAP与XML-RPC对比
- XML-RPC是启动Web服务最容易的方法,在很多方面比SOAP更简单易用,但不同于SOAP的是,XML-RPC没有相应的服务描述语法,这妨碍了XML-RPC服务的自动调用
- SOAP 有明显的优越性:它非常适合异步通信和针对松耦合的客户机和服务器。但这种好处会招致一些不利结果。必须做大量的运行时检查,而且开发人员丧失了许多可以确保方法和参数是正确的编译时便利。
- 可以认为SOAP是XML-RPC的高级版本,二者基于相同的原理:利用HTTP + XML封装进行RPC调用
- 安全与SOAP
- 如果企业使用SOAP来传送有价值的信息的话,那么,安全就是最重要的问题。由OASIS组织发起,计算机行业的领导者们已经联合开发了一套标准,称为WS-Security。这个标准对基本的SOAP通信做出了改善,以便能够处理以下几个问题:
- 消息机密性——由于拦截HTTP消息的方式非常多,因此,在请求和响应过程中,必须能够对所有重要信息加密。很幸运,现在的加密技术非常先进,我们能够对消息内容进行加密,以保证消息不被修改。
- 客户和服务身份——必须能够核实SOAP请求来源的身份。
- 如果企业使用SOAP来传送有价值的信息的话,那么,安全就是最重要的问题。由OASIS组织发起,计算机行业的领导者们已经联合开发了一套标准,称为WS-Security。这个标准对基本的SOAP通信做出了改善,以便能够处理以下几个问题:
3.3.其他相关概念
yar
yar是PRC的一个框架,类似webservice的,可以远程调用方法,返回的数据不单单是字符串,可以是数组等类型。
比方说,当你的项目非常庞大的时候,有些公用的模块就需要对外提供接口。
1、可以用curl方式调用,接口返回xml格式、或者json格式的字符串,调用方自己去解析。
2、可以用使用yar写的方法,直接返回结果,就跟调用代码本身的方法一样,可以返回字符串、数组等格式。
Web服务描述语言-WSDL
WSDL(Web Services Description Language)是描述web服务的,是描述怎样访问web服务的。WSDL是用来描述SOAP的,换句话说,WSDL 文件告诉你调用 SOAP 所需要知道的一切。WSDL也是一段xml。现在各个语言对wsdl的支持都很成熟,可以根据同一份wsdl文件生成自己语言的客户端。
为了创建一个用于描述Web服务的XML格式化文件,Web服务描述语言(WSDL)标准提供了足够多的细节,以便能够构建出客户端代码,从而访问服务或者服务器端代码以提供服务。一个服务的WSDL文件将会为你提供以下几个方面的内容:
- 用于访问服务的地址信息
- 用于传送信息的传输协议(例如,通道数)
- 用于所有可使用功能的名称和接口使用方法
- 在所有的请求和响应中所使用的数据类型
2001 年3月,W3C推出了WSDL 1.1版本用于讨论,这并不是最终确定的规范。W3C Web服务描述工作组目前正在开发该规范的2.0版本,基本上已经到了尾声。虽然,WSDL通常是用于特定的SOAP服务,但是,从理论说,它是完全可以 用于特定的REST风格的GET或者POST操作的。
能够根据服务的WSDL描述来自动创建客户端和服务器端代码,支持这一功能的开发环境目前使用得很广泛,以便能够适用于Web服务器和Web服务客户端的 不同程序设计语言。如果你使用Google搜索“SOAP IDE”的话,大概会出现上百万条相关信息。也有这样的工具,根据Java或C#对象来生成相应的WSDL和代码。自动生成代码也许能够使你的开发效率更 高,但是离优化却是越来越远。
SOAP数据包结构解析
SOAP的消息被称为一个SOAP Envelope,包括SOAP Header和SOAP Body。其中,SOAP Header可以方便的插入各种其它消息来扩充Web Service的功能,比如Security(采用证书访问Web Service),SOAP Body则是具体的消息正文,也就是Marshall后的信息。
SOAP调用的时候,也就是向一个URL(比如 http://api.google.com/search/beta2 )发送HTTP Post报文(根据SOAP规范,HTTP Get报文也可被支持),调用方法的名字在HTTP Request Header SOAP-Action中给出,接下来就是SOAP Envelope了。服务端接到请求,执行计算,将返回结果Marshall成XML,用HTTP返回给客户端。
4.REST
4.1.概念:
- REST并不是一种新兴的技术语言,也不是什么新的技术框架,非协议也非规范 。准确来说说REST只是一种概念、风格或者约束,是一种针对网络应用的开发方式, 是回归HTTP本身的建议,可以降低开发的复杂性,提高系统的可伸缩性。
- REST是由Roy Thomas Fieding在他的博士论文《架构风格与基于网络的软件架构设计》中提出的一种架构思想。Roy Fielding是Apache基金会的合作创作者,同时也是HTTP、URI等Web基础协议的主要设计者。从Roy Fielding的背景,我想大家就应该能了解到REST与Web之间的关系了吧。的确,在REST中我们关注技术实际上也只是URI、HTTP、Hypertext(超文本)而已。
- REST是中文翻译为表征状态转移(英文:Representational State Transfer)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。从字面意思来说,“表述”是很难理解是什么东西的?从论文上我们可以看到表述,一般指HTML文档(包括json,xml等),jpeg等图片资源。
- REST 采用Web 服务使用标准的 HTTP 方法 (GET/PUT/POST/DELETE) 将所有 Web 系统的服务抽象为资源,REST从资源的角度来观察整个网络,分布在各处的资源由URI确定,而客户端的应用通过URI来获取资源的表征。Http协议所抽象的get,post,put,delete就好比数据库中最基本的增删改查,而互联网上的各种资源就好比数据库中的记录(可能这么比喻不是很好),对于各种资源的操作最后总是能抽象成为这四种基本操作,在定义了定位资源的规则以后,对于资源的操作通过标准的Http协议就可以实现,开发者也会受益于这种轻量级的协议。
- 谈到REST大家的第一印象就是通过http协议的GET,POST,DELETE,PUT方法实现对url资源的CRUD(创建、读取、更新和删除)操作。这种形式的REST只是CRUD(增删改查),从这个层面上,好像REST只是和RPC一个层面的东西,没有什么了不起,其实这些都是对REST误读。也误导大家实现REST时,特种注重GET,POST,PUT,DELETE方法的处理,包括一些所谓的REST框架,比如JBoss RESTEasy,Restlet Tomcat。究其原因是, REST提供了一组架构约束,当作为一个整体来应用时,强调组件交互的可伸缩性、接口的通用性、组件的独立部署、以及用来减少交互延迟、增强安全性、封装遗留系统的中间组件。其实从整个REST推导过程中可以了解到,REST没有提及HTTP协议的任何方法,只是后期大家从REST的统一接口中扩展出这些操作概念。
4.1.推导REST
先从理论层次上我们看一下REST是怎么推导来的(参考论文第五章)
Web架构背后的设计基本原理,能够被描述为由一组应用于架构中元素之上的约束组成的架构风格。当将每个约束添加到进化中的风格时,会产生一些影响。通过检查这些影响,我们就能够识别出Web的约束所导致的属性。然后就能够应用额外的约束来形成一种新的架构风格,这种风格能够更好地反映出现代Web架构所期待的属性。通过简述REST作为架构风格的推导过程,后面各节将会详细描述组成REST风格的各种特定约束
0. 从“空”风格开始。从架构的观点来看,空风格描述了一个组件之间没有明显边界的系统,这就是我们描述REST的起点。
- 客户-服务器。客户-服务器约束背后的原则是分离关注点。通过分离用户接口和数据存储这两个关注点,我们改善了用户接口跨多个平台的可移植性;同时通过简化服务器组件,改善了系统的可伸缩性。
- 无状态。这个约束导致了可见性、可靠性和可伸缩性三个架构属性,但是无状态并不是没有缺点的,无状态增加了在一系列请求中发送的重复数据(每次交互的开销),可能会降低网络性,正因为这个缺点,所以在REST风格中增加了缓存的考虑。
- 缓存,添加缓存约束的好处在于,它们有可能部分或全部消除一些交互,从而通过减少一系列交互的平均延迟时间,来提高效率、可伸缩性和用户可觉察的性能。但是缓存还是有缺点的,如果缓存中陈旧的数据与将请求直接发送到服务器得到的数据差别很大,那么缓存会降低可靠性。注意这里的缓存并不是指MC,redis之类的缓存,而是在网络代理中,比如proxy服务器上的缓存机制。
- 统一接口。使REST架构风格区别于其他基于网络的架构风格的核心特征是,它强调组件之间要有一个统一的接口,为了获得统一的接口,需要有多个架构约束来指导组件的行为。REST由四个接口约束来定义:资源的识别(identification ofresources)、通过表述对资源执行的操作、自描述的消息(self-descriptive messages)、以及作为应用状态引擎的超媒体相关因素REST和其他概念关系。统一接口的虽然晦涩,但是它是REST风格核心特征,也是前面我们讨论通过CURD方式操作资源的一种表现,也是我们最容易接触感受到的一层,后面淘宝,微博,微信开放平台的开放接口,其实就是我们接触这个平台的统一接口,评价一个开发平台是否REST的标准,也在于这个平台的设计者对统一接口的理解。
- 分层系统,分成系统风格通过限制组件的行为(即,每个组件只能“看到”与其交互的紧邻层),将架构分解为若干等级的层。通过将组件对系统的知识限制在单一层内,为整个系统的复杂性设置了边界,并且提高了底层独立性。分层系统增加了数据处理的开销和延迟,因此降低了用户可觉察的性能对于一个支持缓存约束的基于网络的系统来说,可以通过在中间层使用共享缓存所获得的好处来弥补这一缺点。正因为REST风格有这样的缺点,才会特意强调缓存的作用。
- 按需代码,通过下载并执行applet形式或脚本形式的代码,REST允许对客户端的功能进行扩展,看似简单的一种风格设计,其实对B/S贡献最大的就是这个特性,现在ajax的底层其实就是按需代码机制。
4.2.REST风格/约束:
Fielding 在他的论文中提出了一个RESTful应用应该具备的几点约束。
- 每个资源都应该有一个唯一的标识
- 使用标准的方法来更改资源的状态
- Request和Response的自描述
- 资源多重表述
- 无状态的服务
Fielding 认为,只有具备了上面的约束的应用才能算是REST应用,其实现在许多所谓的REST应用或服务,其实并不能算是真正的REST应用,目前很多所谓的REST应用,其实只是RPC而已。出现这样的情况很正常,因为RPC更符合一般程序员的思维。
之后这几个约束被表述为:
- Client–server C/S结构 (这是Internet服务的一个基本特征)
- 无状态性
- 能够利用Cache机制增进性能 (想起了浏览器?)
- 分层系统 (想起了无数的架构?)
- 统一的接口规范分层交互
- 随需代码 - Javascript (可选,其实是一种扩展性的要求)
看了这几个特征后,你想起了什么? 你可能会破口而出:HTTP
HTTP是WWW的最核心的协议, 它将简单的分布于世界各个角落的资源都统一起来, 统一的地址, 简单的方法, 和一定数量的表达方式.(你可能对这三点描述很模糊,请go ahead).
REST 的三个要素就是是 唯一的资源标识, 简单的方法 (此处的方法是个抽象的概念), 一定的表达方式.
REST 是以 资源 为中心, 名词即资源的地址, 动词即施加于名词上的一些有限操作, 表达是对各种资源形态的抽象.
以HTTP为例,名词即为URI(统一资源标识), 动词包括POST, GET, PUT, DELETE等(还有其它不常用的2个,所以 整个动词集合是有限的), 资源的形态(如text, html, image, pdf等)
根据以上的描述,我们其实发现HTTP是一种典型的REST风格,这也难怪,在1994年提出REST风格时,REST被称作“HTTP对象模型”,但是那个名称常常引起误解,使人们误以为它是一个HTTP服务器的实现模型。这个名称“表述性状态转移”是有意唤起人们对于一个良好设计的Web应用如何运转的印象。反过来看HTTP就是REST的具体实现。在一个REST风格中,我们能够感受到的就是统一接口的数据,这些数据包括所以,当我们开发一个web服务时,比如一个网站,由于使用了HTTP(HTTPS)协议,其实就是一种REST风格,但是在这个REST风格中我们着重处理的是两点
1:URI,即所谓的资源,网站的uri设计
2:统一接口,即所谓的PUT,GET,POST,DELETE方法
虽然我们的网站是REST的风格的,但是由于统一接口设计的不好,导致我们网站在访问请求时,效率低下,以及可扩展性差。在深入浅出REST中,作者总结了五条关键原
1:为所有“事物”定义ID
2:将所有事物链接在一起
3:使用标准方法
4:资源多重表述
5:无状态通信
其中前四条就是对统一接口中的数据元素,第一二条讲的就是uri,第三四条讲的是控制数据。第五条无状态通信,这个需要特别说明下,无状态通信是指服务器和客户端通信是无状态的,假如我们的系统中使用Session保存客户端状态,这种情况就是非无状态通信,是一种unREST的方式。但是应用本身是有状态的,比如用户登录前后,就是应用状态的变化。
4.3.REST与WEB
Fielding指出,使用且符合代表性状态传输(REST)设计约束的 Web 上部署的组件,可以充分利用 Web 的有用特性,万维网(World Wide Web)才能够达到最佳的工作效果。可以这样理解REST——当一个浏览器得到并且显示构成HTML页面的各个元素时,它正在获取资源的当前状态的表现形式。在Fielding的博士论文中,他列举了REST风格的设计约束,并且解释了为什么这些约束能够充分利用Web 的有用特性,使其达到最佳状态,以及这些约束的关键所在。同时,在论文中,他也包含了一些关于REST和某些目前的Web风格之间 “不符合”的讨论,以及这些Web风格是如何导致设计无法利用Web特性的。
Fielding认为,对于使用HTTP承载应用程序协议穿越防火墙,XML-RPC 和SOAP所采用的方式是“从根本上被误导的概念。”它们所采用的方式违背了设立防火墙的概念,结果是,防火墙厂商为了保护系统需要侦察出所承载的协议。由于大多数SOAP应用程序使用HTTP都是为了穿越防火墙,因此,你可以发现REST与SOAP之间的冲突是从哪里开始的。Fielding认为,如果你打算使用HTTP的话,就应该与充分利用HTTP本身的含义。
REST风格强调,通过有限的操作或者是“动词”以及一个组件之间的标准接口,也就是HTTP协议提供的借口,来提升客户与服务之间的交互。通过为每一个资源分配其自己的URL,来实现灵活性,REST可以调用包含上百个URI的资源类型的客户,其中的关键是REST能够给你无限多的“名词”。REST使用HTTP的动词——简单的良定义操作集:POST, GET, PUT,DELETE进行请求和响应,从而避免了歧义。举个例子,GET只能够简单地返回资源的表现形式,而不能够创建任何其他的内容。
在Web发展的初期,由于人们都在试验通过收集各种不同来源的元素,从而把Web应用程序融合在一起,有大量这种Web服务的不成熟探索的例子——从HTTP页面中解析信息,用于页面创建者没有计划到的用途。这种“屏幕抓取”的Web类比表明,REST风格的方法是先于那些更加复杂的Web服务而出现的。
4.4.规划REST服务
在InfoQ上有一篇很好的文章来介绍如何规划REST服务《如何获取(GET)一杯咖啡——星巴克REST案例分析》,估计大家看完这篇文章,应该对如何规划REST服务会有更深的认识。
当我们要规划REST服务的时候,其中最关键的概念是“资源”。
资源是什么呢?广义上讲,任何事物只要有用,它就是资源。狭义的讲(在Web环境中),它是一个可以存放、连接在计算机上,可以通过比特流进行操控的实体。一个实体若要成为资源,它必须有一个URI。在这里URI包含了两重含义:1)它是该资源的名称 2)它是该资源的地址。
在规划URI的时候,有几点希望大家能够注意一下:
- 一个URI标识一个资源,但是一个资源可以被多个URI标识。
- 资源也是有层次的,这个层次应该在URI上充分的体现出来。
- 在规划URI的时候,需要定义一些团队内部确认的关键字或符号,这些关键字或符号是有特殊意义的,不能随便使用。
- 需要有一个URI定义的文档,以备以后的查询和维护。
- 可以使用URI Template来描述URI的定义。如何使用URI Template请看看这篇文章。
当我们定义好资源之后,接下来要做的事情就是定义操作资源的方法以及资源的表述格式了。
使用HTTP提供的基本方法来对资源进行操作,一般的操作定义如下:POST(创建资源)、GET(获取资源)、PUT(修改资源)、DELETE(删除)。它们正好对应了CRUD。
对资源的表述,一般的选择会是XML,但是我更加推荐使用JSON来表述资源。在网络中的传输量小,而且也便于JavaScript解析,同时使用其他语言解析也是非常方便的事情。不过,最关键的还是占用更少的资源,让同样的资源能够服务于更多的人。
4.5.一个简单的REST举例
假设我们希望一个Web服务暴露一部分目录,从这个目录中,用户将能够得到一些描述、图片、安装指令等等。为了得到数字“n1996-01”的描述,用户需要格式化一个GET请求,类似于下面的这个URL: http://company.com/catalog/description/n1996-01
在处理这个请求时,“/catalog”将映射到一个服务中,之后,通过该服务对“description/n1996-01”进行解释,从而 定位资源。在创建响应时,服务需要使用内容类型(Content-Type)的头文件来指定返回格式。在这种情况下,假定返回格式是HTML或者XML, 客户端能够使用它来控制页面的布局。如果要得到图片,那么这个请求将对“/catalog/picture/n1996-01”进行寻址,返回的响应将是 图片内容类型(Content-Type)。
4.6.REST的应用场景:
其实,我们经常容易犯的一个错误是:当我们了解了一个新的技术,就会用这个技术来解决所有的问题。有一句谚语是这么来说的:“在锤子的眼里,所有的东西都是钉子”,其实REST也只是我们工具箱里面的其中的一个工具而已,希望不要把它当做我们唯一的工具。下面,我们就来聊聊适合使用REST的应用场景和不适合使用REST的应用场景。
在我看来,REST最适合的应用场景是需要对外暴露服务的情况。此时,我们可以充分利用REST的自描述、无状态、唯一标识等特性来提供清晰、友好的API;此外,目前Jesery、RESTEasy等JAX-RS框架也提供了OAuth的支持,基本上能够保证服务安全。
最不适合的应用场景是对性能要求高的系统内部的服务调用,在这种情况下使用REST的话,那么REST所有的特性都会变成拖累。这个时候,还是需要选择更底层的通信协议和方式会更好一些,比如ICE。这样的错误,我曾经犯过,后来通过很长时间的努力才慢慢的将这个错误改过来。
4.7.RPC与REST的比较
- RPC是以动词为中心的,REST是以名词为中心的,此处的动词指的是一些方法,名词是指资源。REST强调资源(名词)有统一的接口以此来对它们寻址,而RPC强调过程(动词)有统一的接口来激发它们
- 你会发现,以动词为中心,意味着,当你要需要加入新功能时,你必须要添加更多的动词, 这时候服务器端需要实现 相应的动词(方法), 客户端需要知道这个新的动词并进行调用.
- 而以名词为中心, 假使我请求的是 hostname/friends/, 无论这个URI对应的服务怎么变化,客户端是无需 关注和更新的,而这种变化对客户端也是透明的.
- 一个基于RPC的架构,动词数量是 没有限制的。REST说,我们使用四个动词——非常熟悉,HTTP标准的GET、POST、PUT以及DELETE——来进行请求和响应,REST使用资 源寻址来处理其可变性
- 至于其它的区别,如对实现语言的依赖, 耦合性等,这些都是上面提到的这个根本区别所衍生的
- REST回归HTTP最初的设计;RPC仅仅只是把HTTP作为传输协议来使用。
- REST是由超文本驱动的;RPC是由方法驱动的。
- REST强调HTTP通信的语义可见性,通过消息头和标准的HTTP方法来体现;RPC把语义封装在HTTP消息体中。
如何选择?
根据笔者自己的经验和心得, 建议 能够使用REST就尽量使用REST, 主要基于下面几个考虑:
- 扩展性
- 松耦合(意味着,不用强制要求客户端去更新相应的代码)
- 客户端实现语言无关
- 性能
- 安全性(例如HTTPS)
当然上述的几点也并非 RPC 都不满足,不过相对而言, REST 更加清晰和简洁, 再辅以 JSON 相应的服务会在性能和稳定性(简单通常意味着robust)方面有很大的提高.
总体上,因为REST模式的Web服务与复杂的SOAP和XML-RPC对比来讲明显的更加简洁,越来越多的web服务开始采用REST风格设计和实现。例如,Amazon.com提供接近REST风格的Web服务进行图书查找;雅虎提供的Web服务也是REST风格的。REST对于资源型服务接口来说很合适,同时特别适合对于效率要求很高,但是对于安全要求不高的场景。而SOAP的成熟性可以给需要提供给多开发语言的,对于安全性要求较高的接口设计带来便利。所以我觉得纯粹说什么设计模式将会占据主导地位没有什么意义,关键还是看应用场景,正是那句老话:适合的才是最好的
同时很重要一点就是不要扭曲了REST现在很多网站都跟风去开发REST风格的接口,其实都是在学其形,不知其心,最后弄得不伦不类,性能上不去,安全又保证不了,徒有一个看似象摸象样的皮囊。
4.8.soap与REST比较:
- REST依赖一套简单的“动词”,把所有的复杂性都转移到了指定资源的“名词”中。与此不同,SOAP却有一套相当复杂的XML格式化命令和数据传输选项。
- 非常重要一点是,REST是需要请求HTTP的,与其相比,SOAP更具优势,SOAP消息可以由所有能够处理Unicode文本的传输方式来传 送,很可惜,这一点通常不被人们所认可。事实是,由于HTTP穿透防火墙的便捷性,以及开发商们对Web非常熟悉,因此,人们还在继续强调着HTTP传 输。
- 在 开发人员的意识里,对于Web服务的开发而言,REST和SOAP风格各有千秋。SOAP拥有更为详尽的标准化成果和开源工具。除此之外,现在,有许多 集成开发环境能够在现有代码的基础上,依据接口方法自动生成SOAP。如果你需要使用WSDL来发布你的服务,或者你需要一些安全功能如消息签名和加密, 那么,SOAP能够确保消息的安全性。另一方面,如果你希望使用简单接口来公布一些信息,而不需要繁琐的处理过程,那么,REST也许是最佳选择。
- 众多从事Web服务的软件设计师们认为SOAP过度复杂,于是,类似eBay和Google的服务都采用了REST风格的约束来暴露其大量数据。
- 甚至可以有RESTful SOAP。尽管还网上没人提到RESTful SOAP,但我觉得这在理论上是没问题的
造成SOAP和REST放在一起讨论是因为,网络上很多工程师把REST风格和REST的实现混淆了。REST的概念比较宽泛,本身如果符合1)Client–server, 2)Stateless, 3)Cacheable, 4)Layered system, 和5)Uniform interface这几个主要的限制,就是RESTful的设计。同时呢,由于HTTP是一个很容易满足stateless, cacheable,uniform interface的protocol,所以实际上REST被默认就是用HTTP来实现,很多人耳熟能详HTTP的verb如何对应到resource的CRUD,仿佛也成了REST风格本身的死规定。我认为其实不然,以HTTP中的PUT为例,如果用PUT来实现resource的update,那么就必须要保证idempotent,每次传给server的信息,必须是resource的全部信息,不能作partial update。不难发现,用PUT来实现update,其实是在REST的constraint上又加上了HTTP的一些限制。如果我们放弃PUT的constraint,采用POST来实现update,则partial update是可以的。紧接着就由一个问题,既然PUT被POST替代,那么我们是否可以用POST来代替GET和DELETE呢?笔者认为应该没问题,一个很现实的例子,如果browser不支持DELETE,用POST来work around是很常见的。
okay, 再来看看SOAP,很多在HTTP上实现的SOAP协议就是用POST来实现的 (wikipedia里SOAP的一个sample http://en.wikipedia.org/wiki/SOAP#Example_message)
因此,当我们使用HTTP POST来实现REST,再加上XML的数据传输格式,其实我们就是在SOAP上面实现了RESTFul的"风格"(尽管还网上没人提到RESTful SOAP,但我觉得这在理论上是没问题的)。
与RESTful SOAP相对的一个例子,很多基于Rails的website(并非说Rails不好,Rails大行其道使得REST风行,故举例)URL风格是/callSomeMethodWithArgumentA, /callSomeMethodWithArgumentB,非常长,不uniform,不满足REST的限制,这些route都是不RESTFul的,我们可以称之为non-RESTful HTTP
长话短说,本人认为SOAP协议和REST架构风格是兼容的。虽然,约定俗成,REST的具体实现一般采用HTTP,且充分利用HTTP verb的不同特性,从而形成了一些约定俗称的范式,但这种实现本身不是REST"风格"的核心。
目前,大部分Web开发者似乎都了解REST——一种采用标准URI进行调用的方案。REST很容易理解,而且只要是支持HTTP/HTTPS的客户端/服务器就支持它。你可以用HTTP GET方法来执行命令。所以,开发者们感受到的REST的优势是:开发简单、只需依托现有Web基础设施、以及学习成本低。
然而,SOAP作为一种古老的Web服务技术,短期内还不会退出历史舞台。而且,随着SOAP 1.2的出现,SOAP印象中的一些缺点已得到改进,采纳率和易用程度也都得到提高。另需注意的是,从W3C SOAP 1.2版开始,SOAP这一缩写不再代表Simple Object Access Protocol(简单对象访问协议),而是仅仅作为协议名称而已。
相对REST而言,SOAP 1.2多出一些开销,不过这些开销也带来了一些好处。首先,SOAP在三个方面离不开XML(Extensible Markup Language,可扩展标记语言):SOAP信封(envelope)是基于XML的,它定义了消息里有什么以及如何处理它;一套用于数据类型的编码规则;过程调用和响应的规划。SOAP信封由传输协议(HTTP/HTTPS)发出,RPC(Remote Procedure Call,远程过程调用)得到执行,然后一个XML文档随SOAP信封返回。
需要注意的是,基于“通用”传输协议是SOAP的一个优点。REST目前基于HTTP/HTTPS;而SOAP可支持任何传输协议,从HTTP/HTTPS到SMTP(Simple Mail Transfer Protocol,简单邮件传送协议),甚至JMS(Java Messaging Service,Java消息传递服务)。不过,由于XML较为冗长且解析费时,因此采用XML也成为一个弊端。
不过,对Web开发者来说的好消息是,目前上述两种方案都是行之有效的方案。REST和SOAP都能解决许多Web方面的问题与挑战,而且在许多情况下,它们各自都能满足开发者的要求,也就是说可互换使用。
但很多人不知道,这两种技术可以混合搭配使用。REST很好理解,且极易上手;不过由于它缺乏标准,因此只被看作是一种架构方法。与之相比,SOAP是一个工业标准,它具备良好定义的协议,以及一套良好确立的规则,在大型和小型系统中均有采用。
因此,REST的适用场合包括:
有限的带宽和资源 别忘了返回的结构可以采用(由开发者定义的)任何格式。另外,由于REST采用标准的GET、PUT、POST和DELETE动词,因此可被任何浏览器所支持。除此以外,REST还可以使用为目前大多数浏览器支持的XMLHttpRequest对象,这为AJAX增色不少。
完全无状态的操作 对于那些需多步执行的操作,REST并非最佳选择,采用SOAP更合适。但是,如果你需要无状态的CRUD(Create/Read/Update/Delete,创建/读取/更新/删除)操作,那么应采用REST。
缓存考虑 若要利用无状态操作的特性,使得信息可被缓存,那么REST是很好的选择。
以上已经覆盖很多方案了,那么,为什么还要考虑SOAP呢?正如前述,SOAP比较成熟而且是经过良好定义的,具有完整的规范。而REST只不过是一种方法,对开发未作任何规约;因此,假如你遇到以下场合,那么SOAP是最佳选择:
异步处理与调用 如果你的应用需要确保可靠性与安全性,那么请采用SOAP。SOAP 1.2为确保这种操作补充定义了WSRM(WS-Reliable Messaging)等标准。
形式化契约 若提供者/消费者双方必须就交换格式取得一致,那么采用SOAP更合适。SOAP 1.2为这种交互提供了严格的规范。
有状态的操作 如果应用需要上下文信息与对话状态管理,那么应采用SOAP。SOAP 1.2为此补充定义了WS-Security、WS-Transactions和WS-Coordination等标准。相比之下,REST方法要求开发者自己来实现这些框架性工作。
正如你所看到的,REST和SOAP各自有其用武之地。它们在安全性和传输层等方面有着自己的潜在问题,不过它们都能完成任务,而且在许多情况下,它们都丰富了Web的技术手段。因此,就这一论题,其实最好的原则就是灵活性原则;因为至少在现今的Web开发中,无论面对何种问题,Web开发者们总有办法运用好这两种技术中的一种。