常见的三种Web服务架构

转自http://www.cnblogs.com/bvbook/archive/2008/12/24/1360942.html

相互竞争的服务架构

The Competing Architectures

我们已经给出了“不同Web服务会有不同做法”的两个主要问题,现在要据此对不同风格的Web服务进行分类了。根据我的研究,常见的Web服务架构主要有三种:REST式架构、RPC式架构和REST-RPC混合架构。下面依次对它们进行介绍。

REST式、面向资源的架构

RESTful, Resource-Oriented Architectures

本书的主题是符合REST风格的Web服务架构——按照Roy Fielding博士论文里的评判标准,它们可以获得很高的得分。现在,虽然许多架构从技术上说是REST式的(注3),但我希望关注那些最适合Web服务的架构;所以,当我谈及REST式Web服务时,我指的是那些具备Web特征的服务——称它们为面向资源的(resource-oriented)。将在第3章通过一个真实的Web服务——Amazon S3(Simple Storage Service)来介绍面向资源的REST的基本概念,然后在第4章,向你逐个介绍REST的标志特征,并定义一种非常适合REST式Web服务的架构——面向资源的架构(Resource-Oriented Architecture)。

REST式架构意味着,方法信息(method information)都在HTTP方法(HTTP method)里;面向资源的架构(ROA)意味着,作用域信息(scoping information)都在URI里——二者结合起来是很强大的。一个面向资源的REST式Web服务,通过HTTP请求的第一行(如“GET /reports/open-bugs HTTP/1.1”)就能基本了解客户端要做什么了,HTTP请求的其余部分只是具体细节而已。实际上,很多HTTP请求只要第一行就行了。如果HTTP方法跟方法信息对不上,那么服务就算不上是REST式的;如果作用域信息不放在URI里,那么服务就不是面向资源的。虽然并非只有这两条要求,但它们是很好的经验。

l   提供Atom发布协议(http://www.ietf.org/html.char ters/atompub-charter.html)及其变型的服务,例如GData(http://code.google.com/apis/gdata/

l   Amazon S3(Simple Storage Service)(http://aws.amazon.com/s3

l   Yahoo!提供的大部分Web服务(http://developer.yahoo.com/

l   许多其他未采用SOAP的、只读的Web服务

l   静态网站

l   很多Web应用(尤其是像搜索引擎这种只读的)

每当谈到非REST式架构或非面向资源的架构时,我都是有一定目的的。这一章将在Programmable Web的背景之下,对REST式Web服务加以全面考察。在第2章会提到一些真实的Web服务,并指出:无论一个服务是否正好符合我所推荐的架构,你都可以采用同样的客户端工具访问它。在第10章,会就“应如何设计programmable web”这一久远的话题发表观点。

RPC式架构

RPC-Style Architectures

RPC式Web服务(RPC-style Web Service)通常从客户端收到一个充满数据的信封(envelope),然后发回一个同样充满数据的信封。RPC式架构意味着:方法信息和作用域信息都在信封(envelope)或报头(headers)里。具体采用哪种信封,并不影响这里的分类,不过HTTP是一种常见信封格式(毕竟,采用HTTP才称得上是Web服务)。另一种常见的信封格式是SOAP(把SOAP信封放在HTTP信封里,在HTTP上传送SOAP文档)。各个RPC式服务采用自己的词汇,就像计算机程序一样(你每次写程序,定义的函数名称都不相同)。而REST式Web服务则相反,它们共用一套标准词汇,即HTTP方法。REST式服务里的每个对象都具有统一的基本接口。

XML-RPC是最典型的RPC架构的例子。虽然目前XML-RPC主要是一种遗留协议(legacy protocol)了,但由于它相对简单,而且比较容易解释,所以我还是准备从它开始讲起。示例1-11所示的Ruby客户端用于访问一个XML-RPC服务,该服务的作用是查询具有统一产品代码(Universal Product Code)的产品。

示例1-11:一个访问XML-RPC服务的例子:根据UPC查询产品

#!/usr/bin/ruby -w

# xmlrpc-upc.rb

require 'xmlrpc/client'

def find_product(upc)

server = XMLRPC::Client.new2('http://www.upcdatabase.com/rpc')

begin

response = server.call('lookupUPC', upc)

rescue XMLRPC::FaultException => e

puts "Error: "

puts e.faultCode

puts e.faultString

end

end

puts find_product("001441000055")['description']

# "Trader Joe's Thai Rice Noodles"

XML-RPC服务就像C语言一样,你可以调用一个带参数(“001441000055”)的函数(lookupUPC),并获得返回值。方法信息(函数名)和作用域信息(参数)都放在XML文档(如示例1-12所示)里。

示例1-12:一个描述XML-RPC请求的XML文档

<?xml version="1.0" ?>

<methodCall>

<methodName>lookupUPC</methodName>

<params>

<param><value><string>001441000055</string></value></param>

</params>

</methodCall>

这个XML文档是放在信封里传给服务器的。这里的信封(envelope)就是一个HTTP请求,它由HTTP方法、URI、报头和实体主体等部分组成,其中实体主体就是上面的XML文档(如示例1-13所示)。

示例1-13:一个包含了描述XML-RPC请求的XML文档的HTTP信封

POST /rpc HTTP/1.1

Host: www.upcdatabase.com

User-Agent: XMLRPC::Client (Ruby 1.8.4)

Content-Type: text/xml; charset=utf-8

Content-Length: 158

Connection: keep-alive

<?xml version="1.0" ?>

<methodCall>

<methodName>lookupUPC</methodName>

...

</methodCall>

上述HTTP信封里的XML文档,将随你所调用方法的不同而有所变化,但HTTP信封的格式总是不变的。无论你对这个UPC查询服务提什么请求,URI总是http://www. upcdatabase.com/rpc,HTTP方法总是POST。简单地说,XML-RPC服务未采用HTTP的很多特性;它只暴露一个URI(称为“端点”),并且该URI只支持一种HTTP方法——POST方法。

REST式服务为不同的作用域信息暴露不同的URI;而RPC式服务一般为每个“文档处理器”(用于打开信封,并把信封转换为软件指令)暴露一个URI。我们做个对比,假设上述UPC查询服务被设计为一种REST式架构的话,那么其客户端代码将如示例1-14所示。

示例1-14:假想的示例代码:一个REST式UPC查询服务

require 'open-uri'

upc_data = open('http://www.upcdatabase.com/upc/00598491').read()

...

这里,方法信息包含在HTTP方法里(默认的HTTP方法是GET,它对应于示例1-13中的lookupUPC),作用域信息包含在URI里。这个假想的服务暴露的URI不只一个,每个UPC代码都有与之对应的URI。与示例1-13不同的是,这里的HTTP信封是空的——它是一个没有实体主体的HTTP GET请求。

另一个RPC式服务的例子可以参见示例1-8:Google SOAP API是一个采用SOAP作为信封格式的RPC式服务。

较多采用或只采用HTTP POST的服务,多半是RPC式服务。虽然这不是绝对的,但至少可以说明该服务没有把HTTP方法用于表达方法信息。如果一个REST式服务过多地采用HTTP POST,那么它就容易演变为REST-RPC混合架构。

下面是一些知名的RPC式Web服务的例子:

l   所有采用XML-RPC的服务

l   几乎所有的SOAP服务(这一点是有争议的,本章后面的“Programmable Web涉及的技术”一节对此进行了探讨)

l   少部分Web应用(通常是没设计好的)

REST-RPC混合架构

REST-RPC Hybrid Architectures

这一术语是我创造的,它用于形容那些介于REST式架构与纯RPC式架构之间的Web服务。这些服务通常是由那些对真实Web应用懂得比较多,但对REST理论不精的程序员们创建的。

我们再次回顾一下这个调用Flickr Web服务时使用的URI:http://www.flickr.com/services/ rest?api_key=xxx&method=flickr.photos.search&tags=penguin。尽管URI里包含“rest”字样,但它显然是一个采用HTTP信封的RPC式服务。另一方面,它的作用域信息(“具有‘penguin’标签的照片”)是放在URI里的——从这一点看,它跟REST式面向资源的服务有点相像;不过它的方法信息(“搜索照片”)也被放在URI里了,而前面说过,对于REST式服务,方法信息应该放在HTTP方法里,其余部分全部作为作用域信息。看来,这个服务只是把HTTP当作信封格式来用,然后按照自己的意愿来放置方法信息和作用域信息——这是一个RPC式服务,鉴定完毕!

不过,我们来看示例1-15。

示例1-15:一个向Flickr Web服务发HTTP请求的例子

GET services/rest?api_key=xxx&method=flickr.photos.search&tags=penguin HTTP/1.1

Host: www.flickr.com

这是当客户端调用Flickr Web服务时发出的HTTP请求。这里看上去,貌似方法信息是在HTTP方法里的。 这个请求的意图是获取(GET)数据。 获取什么数据呢?一个搜索“具有‘penguin’标签的照片”的结果列表。原先貌似方法信息的数据(“搜索照片”),现在看上去像是作用域信息(“photos/tag/penguin”)了。刚才那个被鉴定为RPC式的服务,现在呈现出REST风格了。

这是一个错觉。一个RPC式服务采用普通老式HTTP(Plain Old HTTP)作为信封格式,且方法信息和作用域信息刚好都在HTTP请求的URI路径里的话,就会产生这种错觉。假如HTTP方法是GET,并且请求服务的意图也是“获取(GET)”信息的话,就会很难分辨方法信息是在HTTP方法里,还是在URI里了。所以你会把一个RPC式服务的HTTP请求看成是REST式Web服务的HTTP请求。这个HTTP请求里可能含有“method=flickr. photos.search”这样的信息,但这个信息会被误认为是作用域信息(就像“photos/”和“search/”是作用域信息一样)。这些RPC式服务,不经意间或多或少地带着点REST式Web服务的特征。它们只是把HTTP作为一种信封格式来用,不过它们使用HTTP信封的方式可能刚好跟REST式服务的做法雷同。

许多只读的Web服务,尽管它们起初也许是按RPC风格设计的,但都可称得上是完全REST式和面向资源的!但是,如果该服务允许客户端修改数据的话,就会出现客户端所使用的HTTP方法与真正的方法信息不一致的情况——这样它就不具备REST式服务的特征了。像这样的服务,我称之为REST-RPC混合服务。

举个例子。即使客户端的意图是修改数据,Flickr Web API仍旧让客户端使用HTTP GET。如果要删除一个照片,你需要向一个包含“method=flickr.photos.delete”的URI发出GET请求,尽管你的这个请求的意图并不是获取(GET)数据,如我在第5章所讲。Flickr Web API是一种REST-RPC混合架构:当客户端通过GET方法获取数据时,它是REST式的;当客户端通过GET方法修改数据时,它是RPC式的。

一些知名的REST-RPC混合Web服务包括:

l   del.icio.us API

l   Flickr Web API

l   许多被说成是REST式架构的Web服务

l   大部分Web应用

从设计的角度来看,我认为不会有人特意把服务设计为REST-RPC混合架构。由于HTTP工作方式的原因,任何采用普通HTTP并暴露多个URI的RPC式服务,往往最终成为REST式架构或混合架构。许多程序员按他们设计Web应用的方式来设计Web服务,并最终形成混合架构的服务。

混合架构的存在已经造成了不少混乱。从事Web应用设计的人容易设计出REST-RPC混合架构,而且他们常常声称这种混合架构是REST式架构——他们仍在以设计human web的方式来设计Web服务。已经有不少功夫花费在分辨REST式架构与其他架构上了。我把“其他架构”称为REST-RPC混合架构,这是众多新词中的一个,我认为这个新词是看待这些常见而令人困惑的服务最准确有效的方式。假如你知道它们的其他称呼(在写本书的时候,“HTTP+POX”是最流行的),不妨继续往下读,后面我会用我自己的语言来解释这些其他术语。

常见的三种Web服务架构的更多相关文章

  1. MySQL - 常见的三种数据库存储引擎

    原文:MySQL - 常见的三种数据库存储引擎 数据库存储引擎:是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建.查询.更新和删除数据.不同的存储引擎提供不同的存储机制.索引技巧. ...

  2. Web服务架构风格之REST

    REST(Representational State Transfer)是一种Web服务的架构,其目的是创建具有良好扩展性的分布式系统.它的约束包含: 使用C/S模型.client和server之间 ...

  3. Web服务架构

    # Web服务架构 ### Web服务模型-- 服务提供者.服务请求者.服务注册中心,服务注册中心是一个可选的角色. 现在的Web服务不仅限于WSDL,还有RESTful. - 服务提供者.即Web服 ...

  4. Java中常见的5种WEB服务器介绍

    这篇文章主要介绍了Java中常见的5种WEB服务器介绍,它们分别是Tomcat.Resin.JBoss.WebSphere.WebLogic,需要的朋友可以参考下 Web服务器是运行及发布Web应用的 ...

  5. Java进阶(三十一) Web服务调用

    Java进阶(三十一) Web服务调用 前言 有朋友问了一个问题:如何调用已知的音乐服务接口,服务文档如下: https://www.evernote.com/shard/s744/sh/c37cd5 ...

  6. 缓慢变化维 (Slowly Changing Dimension) 常见的三种类型及原型设计(转)

    开篇介绍 在从 OLTP 业务数据库向 DW 数据仓库抽取数据的过程中,特别是第一次导入之后的每一次增量抽取往往会遇到这样的问题:业务数据库中的一些数据发生了更改,到底要不要将这些变化也反映到数据仓库 ...

  7. 三种web性能压力测试工具

    三种web性能压力测试工具http_load webbench ab小结 题记:压力和性能测试工具很多,下文讨论的是我觉得比较容易上手,用的比较多的三种 http_load 下载地址:http://w ...

  8. Iass、Pass、SasS三种云服务区别?

    Iass.Pass.SasS三种云服务区别 我们可以把云计算理解成一栋大楼,而这栋楼又可以分为顶楼.中间.低层三大块.那么我们就可以把Iass(基础设施).Pass(平台).Sass(软件)理解成这栋 ...

  9. 中小型研发团队架构实践三:微服务架构(MSA)

    一.MSA 简介 1.1.MSA 是什么 微服务架构 MSA 是 Microservice Architect 的简称,它是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相通讯.互相 ...

随机推荐

  1. win7重装系统时,使用PE工具箱进入系统看到的“C盘变成0.2G,D盘变成48G左右”这是什么回事?

    引入: 今天帮同学重装系统,重装系统使用的方法是利用PE工具箱制作出启动U盘,进行重装系统. 我的步骤是 第一步:开机按F2挂载U盘优先启动,于是开机时就进入PE微系统 第二步: 用分区工具(Disk ...

  2. C# WinForm 判断窗体控件是否修改过

    本文转载:http://www.cnblogs.com/LinFx/archive/2011/12/23/2299895.html 1.自定义控件, 和接口 ) return IsModify(con ...

  3. cocos2d-x 3.0 final 中文显示

    cocos2d-x 3.0的中文显示非常easy,首先,你须要一个xml文件保存中文,还须要一个能显示中文的TTF文件 <?xml version="1.0" encodin ...

  4. 覆盖equals的时候总要覆盖hashCode

    import java.util.HashMap; public class Student { private String name ; private String id; public Stu ...

  5. 从高德 SDK 学习 Android 动态加载资源

    前不久跑去折腾高德 SDK 中的 HUD 功能,相信用过该功能的用户都知道 HUD 界面上的导航转向图标是动态变化的.从高德官方导航 API 文档中 AMapNaviGuide 类的描述可知,导航转向 ...

  6. RHEL7安装配置TigerVNC

    TigerVNC使用非加密的链接,默认会被firewalld blocked 掉,想要 vnc正常工作就需要让firewalld开放相应的端口才行. vnc默认的端口号为5900,而每个vnc win ...

  7. C++ hello world

    日文版本的vs 2008 , 在 < 新建 里面先创建一个项目 然后点击项目去创建一个C++的主启动文件 选择创建的文件类型 然后在文件里面写入代码 #include<iostream&g ...

  8. Java-Android 之输入提示框

    Android的文本提示框有两种方式: main.xml文件 <?xml version="1.0" encoding="utf-8"?> < ...

  9. mysql - 编码

    show variables like 'character%'; 通过以上命令可以查询编码情况, 不过,在安装的时候,建议选择‘gbk’这类中文编码, 如果选择的是utf8,则在处理的过程中需要进行 ...

  10. 利用抽象、多态实现无反射的绿色环保ORM框架

    最近一直在忙新公司的基础库建设,对系统架构.开发框架及快速开发平台的设计实施都积累了一定的实践经验. 一般的中小型的软件开发公司,如果按照技术储备来衡量软件项目的技术含量的评定依据是可行的.但如果光是 ...