dzwcom 2014-05-17
RESTfulWebservice和SOAPWebserivce对比及区别
接口抽象
RESTfulWeb服务使用标准的HTTP方法(GET/PUT/POST/DELETE)来抽象所有Web系统的服务能力,而不同的是,SOAP应用都通过定义自己个性化的接口方法来抽象Web服务,这更像我们经常谈到的RPC。例如本例中的getUserList与getUserByName方法。
RESTfulWeb服务使用标准的HTTP方法优势,从大的方面来讲:标准化的HTTP操作方法,结合其他的标准化技术,如URI,HTML,XML等,将会极大提高系统与系统之间整合的互操作能力。尤其在Web应用领域,RESTfulWeb服务所表达的这种抽象能力更加贴近Web本身的工作方式,也更加自然。
同时,使用标准HTTP方法实现的RRESTfulWeb服务也带来了HTTP方法本身的一些优势:
无状态性(Stateless)
HTTP协议从本质上说是一种无状态的协议,客户端发出的HTTP请求之间可以相互隔离,不存在相互的状态依赖。基于HTTP的ROA,以非常自然的方式来实现无状态服务请求处理逻辑。对于分布式的应用而言,任意给定的两个服务请求Request1与Request2,由于它们之间并没有相互之间的状态依赖,就不需要对它们进行相互协作处理,其结果是:Request1与Request2可以在任何的服务器上执行,这样的应用很容易在服务器端支持负载平衡(load-balance)。
安全操作与幂指相等特性(Safety/Idempotence)
HTTP的GET、HEAD请求本质上应该是安全的调用,即:GET、HEAD调用不会有任何的副作用,不会造成服务器端状态的改变。对于服务器来说,客户端对某一URI做n次的GET、HAED调用,其状态与没有做调用是一样的,不会发生任何的改变。
HTTP的PUT、DELTE调用,具有幂指相等特性,即:客户端对某一URI做n次的PUT、DELTE调用,其效果与做一次的调用是一样的。HTTP的GET、HEAD方法也具有幂指相等特性。
HTTP这些标准方法在原则上保证你的分布式系统具有这些特性,以帮助构建更加健壮的分布式系统。
安全控制
为了说明问题,基于上面的在线用户管理系统,我们给定以下场景:
参考一开始我们给出的用例图,对于客户端Client2,我们只希望它能以只读的方式访问User和UserList资源,而Client1具有访问所有资源的所有权限。
如何做这样的安全控制?
通行的做法是:所有从客户端Client2发出的HTTP请求都经过代理服务器(ProxyServer)。代理服务器制定安全策略:所有经过该代理的访问User和UserList资源的请求只具有读取权限,即:允许GET/HEAD操作,而像具有写权限的PUT/DELTE是不被允许的。
如果对于REST,我们看看这样的安全策略是如何部署的。如下图所示:
图4.REST与代理服务器(ProxyServers)
一般代理服务器的实现根据(URI,HTTPMethod)两元组来决定HTTP请求的安全合法性。
当发现类似于(http://localhost:8182/v1/users/{username},DELETE)这样的请求时,予以拒绝。
对于SOAP,如果我们想借助于既有的代理服务器进行安全控制,会比较尴尬,如下图:
图5.SOAP与代理服务器(ProxyServers)
所有的SOAP消息经过代理服务器,只能看到(http://localhost:8182/v1/soap/servlet/messagerouter,HTTPPOST)这样的信息,如果代理服务器想知道当前的HTTP请求具体做的是什么,必须对SOAP的消息体解码,这样的话,意味着要求第三方的代理服务器需要理解当前的SOAP消息语义,而这种SOAP应用与代理服务器之间的紧耦合关系是不合理的。
关于缓存
众所周知,对于基于网络的分布式应用,网络传输是一个影响应用性能的重要因素。如何使用缓存来节省网络传输带来的开销,这是每一个构建分布式网络应用的开发人员必须考虑的问题。
HTTP协议带条件的HTTPGET请求(ConditionalGET)被设计用来节省客户端与服务器之间网络传输带来的开销,这也给客户端实现Cache机制(包括在客户端与服务器之间的任何代理)提供了可能。HTTP协议通过HTTPHEADER域:If-Modified-Since/Last-Modified,If-None-Match/ETag实现带条件的GET请求。
REST的应用可以充分地挖掘HTTP协议对缓存支持的能力。当客户端第一次发送HTTPGET请求给服务器获得内容后,该内容可能被缓存服务器(CacheServer)缓存。当下一次客户端请求同样的资源时,缓存可以直接给出响应,而不需要请求远程的服务器获得。而这一切对客户端来说都是透明的。
图6.REST与缓存服务器(CacheServer)
而对于SOAP,情况又是怎样的呢?
使用HTTP协议的SOAP,由于其设计原则上并不像REST那样强调与Web的工作方式相一致,所以,基于SOAP应用很难充分发挥HTTP本身的缓存能力。
图7.SOAP与缓存服务器(CacheServer)
两个因素决定了基于SOAP应用的缓存机制要远比REST复杂:
其一、所有经过缓存服务器的SOAP消息总是HTTPPOST,缓存服务器如果不解码SOAP消息体,没法知道该HTTP请求是否是想从服务器获得数据。
其二、SOAP消息所使用的URI总是指向SOAP的服务器,如本文例子中的http://localhost:8182/v1/soap/servlet/messagerouter,这并没有表达真实的资源URI,其结果是缓存服务器根本不知道那个资源正在被请求,更不用谈进行缓存处理。
关于连接性
在一个纯的SOAP应用中,URI本质上除了用来指示SOAP服务器外,本身没有任何意义。与REST的不同的是,无法通过URI驱动SOAP方法调用。例如在我们的例子中,当我们通过
getUserListSOAP消息获得所有的用户列表后,仍然无法通过既有的信息得到某个具体的用户信息。唯一的方法只有通过WSDL的指示,通过调用getUserByName获得,getUserList与getUserByName是彼此孤立的。
而对于REST,情况是完全不同的:通过http://localhost:8182/v1/usersURI获得用户列表,然后再通过用户列表中所提供的LINK属性,例如<link>http://localhost:8182/v1/users/tester</link>获得tester用户的用户信息。这样的工作方式,非常类似于你在浏览器的某个页面上点击某个hyperlink,浏览器帮你自动定向到你想访问的页面,并不依赖任何第三方的信息。
总结
典型的基于SOAP的Web服务以操作为中心,每个操作接受XML文档作为输入,提供XML文档作为输出。在本质上讲,它们是RPC风格的。而在遵循REST原则的ROA应用中,服务是以资源为中心的,对每个资源的操作都是标准化的HTTP方法。
本文主要集中在以上的几个方面,对SOAP与REST进行了对比,可以看到,基于REST构建的系统其系统的扩展能力要强于SOAP,这可以体现在它的统一接口抽象、代理服务器支持、缓存服务器支持等诸多方面。并且,伴随着WebSiteasWebServices演进的趋势,基于REST设计和实现的简单性和强扩展性,有理由相信,REST将会成为Web服务的一个重要架构实践领域。