Distributed Systems笔记-Web Service Design Patterns

CMU 95702 Distributed Systems 笔记。简单介绍 XML-RPC、SOAP、REST 三种 web 服务实现方案以及 RPC、Message、Resource 三种 patterns。

Web 服务实现方案

主流的 Web 服务实现方案有以下三种,因为 XML-RPC 逐渐被 SOAP 取代,所以也可以说,主流的 Web 服务实现方案只有 REST 和 SOAP 两种。

  • REST:表征状态转移(Representational State Transfer
  • SOAP:简单对象访问协议(Simple Object Access Protocol)
  • XML-RPC:远程过程调用(Remote procedure call,RPC)

XML-RPC

XML-RPC 是一个远程过程调用(remote procedure call,RPC)的分布式计算协议,通过XML将调用函数封装,并使用 HTTP 协议作为传送机制。后来在新的功能不断被引入下,这个标准慢慢演变成为今日的 SOAP 协定。XML-RPC 协定是已登记的专利项目。XML-RPC 透过向装置了这个协定的服务器发出HTTP请求。发出请求的用户端一般都是需要向远端系统要求呼叫的软件。

eg. Long-lived image
如果需要经常把大的图片传到前端,那么可以把图片的 cache-control 设置的大一些,如 30 天,如果需要更新图片,那么上传一张新的图片到新的 URI,然后再改变 HTML,指向新的 URI。

HTML

 
       
1
 
       

Server

 
       
1
2
3
4
5
 
       
HTTP/1.1 200 Ok
Date: Thu, 15 Aug 2008 23:26:31 GMT
Server: Apache
Content-Length: 50753
Cache-Control: max-age=259200

HTML

 
       
1
 
       

SOAP

SOAP(Simple Object Access Protocol) 是一套完整的实现 Web 服务的解决方案。

SOAP 方式的 Web 服务中的 Web 服务描述语言(WSDL)和简单对象访问协议(SOAP)一起构成了 SOAP 方式下的 Web 服务的结构单元。客户端通过 WSDL 可以了解 Web 服务公开了那些可以被执行的方法以及 Web 服务可以发送或接收的消息格式(解决了公布访问资源方法的问题)。客户端按照 SOAP 将调用位于远程系统上的服务所需信息序列化为消息(解决了如何调用远程方法的问题)。注意 WSDL 描述的服务以及SOAP消息都是符合统一标准的,都是机器可读的.

WSDL 基于 XML 格式,用来描述 Web 服务。WSDL 文档可以看成是客户端和服务器之间的一个协约。使用 WSDL 工具,你可以自动处理这个过程,几乎不用手工编写代码就能够让应用程序整合新的服务。因此 WSDL 是 Web 服务体系结构的基础,因为它提供了一个通用语言,用来描述服务和整合这些服务的平台。

SOAP 本身提供了与 Web 服务交换信息的方法。SOAP 是序列化调用位于远程系统上的服务所需信息的标准方法,这些信息可以使用一种远程系统能够读懂的格式通过网络发送到远程系统,而不必关心远程系统运行于何种平台或者使用何种语言编写。SOAP 以 XML 格式提供了一个简单、轻量的用于在分散或分布环境中交换结构化和类型信息的机制。实际上它通过提供一个有标准组件的包模型和在模块中编码数据的机制,定义了一个简单的表示应用程序语义的机制。

用一个简单的例子来说明 SOAP 使用过程,一个 SOAP 消息可以发送到一个具有 Web Service 功能的 Web 站点,例如,一个含有房价信息的数据库,消息的参数中标明这是一个查询消息,此站点将返回一个 XML 格式的信息,其中包含了查询结果(价格,位置,特点,或者其他信息)。由于数据是用一种标准化的可分析的结构来传递的,所以可以直接被第三方站点所利用。

REST

表征状态转移(Representional State Transfer),是 Roy Fielding( HTTP规范的主要编写者之一)博士在2000年他的博士论文中提出来的一种软件架构风格。它并不是一个标准,而是通过表征(Representional)来描述传输状态的一种原则。其宗旨是从资源的角度来观察整个网络,分布在各处的资源由URI确定,而客户端的应用通过 URI 来获取资源的表征。获得这些表征致使这些应用程序转变了其状态。随着不断获取资源的表征,客户端应用不断地在转变着其状态。

REST 中没有用于描述资源(服务)列表,资源元数据的类似于WSDL的东西。所以我们需要其他策略去代替 WSDL 实现“公布访问资源方法的问题”。

由于没有类似于 SOAP 的权威性协议作为规范,因此各个网站的REST实现都自有一套,也正是因为这种各自实现的情况,在性能和可用性上会大大高于 SOAP 发布的 web service,但细节方面有太多没有约束的地方,其统一通用方面远远不及 SOAP。

举个例子:假设A组织,B组织都实现了Restful API来通过工号查询人员信息,因为没有统一的规范。

A的API 可能是这样:

 
       
1
 
       
http://A/api/person/001

B的API 可能是这样:

 
       
1
 
       
http://A/api/person/id=001

第三方客户端在实现远程调用的时候就必须考虑这些API的差异,分别查看A,B的API文档。

如果有个权威性协议作为规范做指导,规定这个API应该实现成下面这样,那么第三方客户端也只需按照这个标准去调用远程API,而不用查看A,B的API文档:

 
       
1
 
       
http://A/api/person/{001}

而 OData 就是这样的一个设计和使用 Restful API 的权威性协议. OData 定义了一些标准规则(像一个接口定义一堆方法一样),实现 Restful API 时候,必须实现这些标准规则(就像实现一个接口必须实现其所有方法一样)。第三方就可以根据 Odata 协议定义的规则去访问 Restful API。

特性

Resources

  • URI
    REST 的一个重要原则是 Addressability,每一个资源都有一个 URI。格式为 scheme://host:port/path?queryString#fragment。scheme 可以是 http、ftp、https 等。
  • Uniform Interface
    methods,用 http 的若干方法来操作资源。
    representation,提供了多种 formats 来表述网页,如 xml, json 等。http 用 content-type header 来定义格式。

Protocol

  • client-server
    客户和服务器之间通过一个统一的接口来互相通讯。
  • stateless
    每一个 request 都是独立的,每次发送请求时客户端都需要提供足够的信息,服务端并不会保存有关客户的任何状态。
  • cacheable
    REST 的系统能恰当对请求进行缓存,尽量减少服务器和客户端之间的信息传输来提高性能
  • layered(intermediaries)
    客户端并不会固定和一个服务器打交道

HTTP method 的补充:

  • GET - safe, idempotent, cacheable
  • PUT - idempotent
  • DELETE - idempotent
  • HEAD - safe, idempotent
  • POST

cacheable:response 可以被缓存
idempotent:该操作可以被执行多次
safe:该操作并没有副作用(不会影响别的操作)

HATEOAS

REST 另一个主要内容是 HATEOAS。HATEOS 用中文解释就是 超文本作为状态转移的引擎,这是一个 late binding 的例子。用户在浏览器输入 URL 向该资源发起一个 HTTP GET 请求,服务器会返回 response,在这个 response 中包含了下一步你该去哪里的信息,你可以在这个 response 中找到对其它资源的引用:链接、图片、脚本等。也就是说,一个典型的REST服务不需要额外的文档标示通过哪些URL访问特定类型的资源,而是通过服务端返回的响应来标示到底能在该资源上执行什么样的操作。一个REST服务的客户端也不需要知道任何有关哪里有什么样的资源这种信息。

举例来说,一个客户端可能会接收一个我们上面所描述的用于报表服务的主RESTful服务的引用:

http://company1.com/report/

如果是通过浏览器发出的请求,可能会返回一个包含如下引用的HTML文档:

http://company1.com/report/sales

用户可以点击进入并找到可浏览的年份列表。要说明的是浏览器对于URL的结构并没有特别的认知,但它知道如何分析结果并以用户可以浏览的结果返回内容。

对于其它的MIME类型道理也是一样,比如以XML的格式请求2009年的季度报表:

http://company1.com/reports/sales/2009/qtr

可能得到:

 
       
1
2
3
4
5
6
 
       
2009 Quarterly Reports

可以将 URL 想成是贯穿信息空间的向量。每一个层次都进一步的将你指向最终的资源。不同的路径可能产生同样的结果。客户端需要知道如何分析这些结果,但通过对响应给出可识别的类型,我们可以触发合适的分析器。这一结构可通过爬虫降序的从引用来抓取,或者以某种接口展现给用户浏览。一个 RESTful 接口成为了客户端通过基于已知来请求信息的方式。它们以一个已知或者已发现的点作为开始,就像你浏览web一样来浏览信息。

这就是 HATEOS 所指代的。应用的状态在超文本响应中被转移和发现。就像浏览器需要知道HTML、图片、声音文件等等一样,一个RESTful客户端也需要知道如何分析解析资源引用的结果。然而,整个过程是简单、受约束、可伸缩并且灵活的——这正是我们所期望的网络软件系统的属性。

许多人搭建的”RESTful”系统都要求客户端事先知道URL的每一层次的意义。如果服务端将信息重组了,这些系统的客户端就会崩溃。真正体现了HATEOS的客户端与它们所通讯的服务器之间才更加能做到松耦合。

更多见面向资源的架构:REST的另一面

Linked Services Pattern

是 HATEOAS 的核心。只发布一部分 root web services 的地址,在每个 response 中返回相关服务的地址,让客户端通过这种 response 来发现之后的 URI。

Only publish the addresses of a few root web services. Include the addresses of related services in each response. Let clients parse responses to discover subsequent service URIs.

Network performance

客户端 -> 服务端。

client - proxy - gateways - origin server

REST 的优势。

  • Efficiency
    缓存可以提高效率,并不需要到达 gateways 和 origin server;data control 意味着我们可以压缩数据来提高效率。
  • Scalability
    缓存:理由同上。
    无状态:如果服务器记录用户相关的状态,那么集群扩展时用户相关的状态就要及时地在集群中的各个服务器之间同步,对用户状态的同步将会是一个非常棘手的问题,当一个用户的相关状态在一个服务器上发生了更改,那么在什么时候,什么情况下对这些状态进行同步?如果该状态同步是同步进行的,那么同时刷新多个服务器上的用户状态将导致对用户请求的处理变得异常缓慢。如果该同步是异步的,那么用户在发送下一个请求时,其它服务器将可能由于用户状态不同步的原因无法正确地处理用户的请求。除此之外,如果集群进行了不停机的横向扩展,那么用户状态的同步需要如何完成?
    不同的 gateways,增加 intermediaries 非常方便。
  • User Perceived Performance
    通过 reduce media types,缓存等方式实现。
  • simplicity/evolvability/extensibility/customizability/configuration/reusability/visibility/portability/reliability

三种方案简单比较

XML-RPC已慢慢的被SOAP所取代,现在很少采用了,但它还是有版权的。

  • 成熟度上:SOAP在成熟度上优于REST
  • 效率和易用性上:REST更胜一筹
  • 安全性上:SOAP安全性高于REST,因为 REST 更关注的是效率和性能问题

总体上,因为 REST 模式的 Web 服务与复杂的 SOAP 和 XML-RPC 对比来讲明显的更加简洁,越来越多的 web 服务开始采用 REST 风格设计和实现。例如,Amazon.com 提供接近 REST 风格的 Web 服务进行图书查找;雅虎提供的 Web 服务也是REST风格的。REST 对于资源型服务接口来说很合适,同时特别适合对于效率要求很高,但是对于安全要求不高的场景。而 SOAP 的成熟性可以给需要提供给多开发语言的,对于安全性要求较高的接口设计带来便利。所以我觉得纯粹说什么设计模式将会占据主导地位没有什么意义,关键还是看应用场景,正是那句老话:适合的才是最好的

同时很重要一点就是不要扭曲了REST现在很多网站都跟风去开发 REST 风格的接口,其实都是在学其形,不知其心,最后弄得不伦不类,性能上不去,安全又保证不了,徒有一个看似象摸象样的皮囊。

三种主流的Web服务实现方案(REST+SOAP+XML-RPC)简述及比较

API styles

RPC

RPC 是指远程过程调用,也就是说两台服务器A、B,一个应用部署在A服务器上,想要调用 B 服务器上应用提供的函数/方法,需要通过网络来表达调用的语义和传达调用的数据。

这时候的 message 包括 procedure name 和 parameter list,service descriptor 通常是 WSDL 和 XSDL 或者 non-XML approach(JSON-RPC),作用是生成一个在 client 上的 service connector(proxy)。

Framework: SOAP, JAX-WS(java), WCF(Microsoft)

RPC 模型是 tightly copuled system,如果 parameter list 改变了,那么 client 将会 break。如果 descriptor 改变了,那么必须重新生成 connector 来连接 client。

request/response 是 RPC 的默认模式,request/acknowlege 会 less coupled(seperation of concerns),request 可以在队列中等待,之后再进行处理,这样可以提高 scalability。如果 client 不想再等待的时候 block,那么可以用 asynchronous response handler。

Why

通过 http 调用别的机器上的进程/方法
为什么 RPC 呢?就是无法在一个进程内,甚至一个计算机内通过本地调用的方式完成的需求,比如不同的系统间的通讯,甚至不同的组织间的通讯。由于计算能力需要横向扩展,需要在多台机器组成的集群上部署应用.

RPC 的协议有很多,比如最早的 CORBA,Java RMI,Web Service的 RPC 风格,Hessian,Thrift,甚至 Rest API。

通信细节

  1. 服务消费方(client)调用以本地调用方式调用服务;
  2. client stub 接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;
  3. server stub 收到消息后进行解码;
  4. server stub 根据解码结果调用本地的服务;
  5. 本地服务执行并将结果返回给 server stub;
  6. server stub 将返回结果打包成消息并发送至消费方;
  7. client stub 接收到消息,并进行解码;
  8. 服务消费方得到最终结果。

RPC的目标就是要2~8这些步骤都封装起来,让用户对这些细节透明。

Message

通过 http 给别的机器发送 command 命令、通知、其它信息,不用和别的进程 direct coupling,也不用知道别的机器的方法的签名。message 只包含一个参数。

这时候的 message 不包括 procedure name 和 parameter list,service descriptor 通常是 WSDL 和 XSDL,作用是生成一个 service connector(proxy),service 的主要任务是分发,要求 service 更加的聪明,能够评估消息内容并决定去执行哪个进程调用哪个方法。

response 包括了相关 service 的地址(url)。
Framework: SOAP, WS-Policy, WS-Security

默认是 request/acknowledge 模式而不是 request/response。
追加一条新的 message type 很简单。

Resource

操作另一台机器上的数据,不用和别的进程 direct coupling,最小化 the need for domain specific api’s。
消息内容是一个 http 方法,一个 uri,一个 media type。

Resource API 可能是 Restful 的。
request/acknowledge 或者 request/response。
会产生 Security risk 因为 uri is hackable

总结

如果要建一个分布式系统,high performance(speed) 是最主要的要求,那么以下选项选哪个?

  • REST sytle web service
  • JAVA RMI
  • SOAP based web service
  • Javascript using JSON
  • Plain old XML(POX) over HTTP

选 JAVA RMI,因为 java RMI 把 message 都编码成 binary 的形式,减少了在各终端的 conversion time。

Postel’s Law

最后加一条 Postel’s Law。简单来说就是 对自己严格,对他人宽容。“发送时保守”是告诫 web 开发人员的,HTML代码应该写的尽可能符合标准,能够方便别人(浏览器)去解析。“接收时开放”主要是说对一个不遵循固定标准(如不遵循HTML标准)的网页,或者说网站中出现的一个或多个错误,浏览器仍能够尽可能的解析并呈现。另外,浏览器必须向后兼容也是“接收时开放”的一个典型例子,不能因为大家都用 HTML5 编写网站浏览器就不再支持之前的 HTML 版本。

参考链接:
你应该知道的RPC原理
REST简介
WebService的两种方式SOAP和REST比较 (转)
三种主流的Web服务实现方案(REST+SOAP+XML-RPC)简述及比较

原文地址:http://www.shuang0420.com/2016/11/02/Web-Service-Design-Patterns/

你可能感兴趣的:(Distributed,System)