Netflix或Twitter风格的Web服务应该使用REST还是SOAP?

146
我实现了两个 REST 服务:Twitter 和 Netflix。但我很难理解出决定将这些服务暴露成 REST 而不是 SOAP 的用途和逻辑。希望有人能告诉我具体原因,为什么像这样的服务会选择使用 REST 来进行服务实现。
1. 实现 REST 服务比实现 SOAP 服务需要更长的时间。现代语言/框架/平台都有工具可以读取 WSDL 并输出代理类和客户端。而实现 REST 服务需要手动完成,并且需要阅读文档。此外,在实现这两个服务时,你必须猜测数据管道中的实际数据,因为没有真正的模式或参考文档。
2. 为什么要编写返回 XML 的 REST 服务?唯一的区别在于 REST 中你不知道每个元素/属性表示的类型 - 你必须自行实现并"希望"有一天不会出现将一个字符串传递到你认为应该是整数类型的字段中。SOAP 使用 WSDL 定义数据结构,所以这是轻而易举的事情。
3. 我听说使用 SOAP 会存在 "额外负担",即 SOAP 信封。在当今时代,我们是否真的需要担心一些字节的开销?
4. 我听说使用 REST 可以直接在浏览器中使用 URL 查看数据。当然,如果你的 REST 服务使用简单或无身份验证,那么没问题。例如 Netflix 服务使用 OAuth,这要求你在提交请求之前对其进行签名和编码。
5. 为什么我们需要为每个资源创建可读的 URL?如果我们使用工具来实现服务,我们是否真的关心实际的 URL?

7
你应该注意到REST并非“发明”而是自HTTP诞生以来就存在。 - Dirk Vollmar
6
与Roy Fielding的交谈会非常有趣。 :) - Gert Grenander
1
首先,"仇恨"是一个强烈的词语。其次,我们的行业有很多种做事的方式。因此,我不想对 REST 的"存在"进行哲学上的争论。作为一名优秀的开发者,您应该愿意使用最适合解决问题的技术。对于一些 Web 服务来说,REST 可能是最佳选择。我写了更多,但这被关闭了;) - Jason McCreary
1
@Joe:收到。但 REST 的讽刺之一是它并不是一种“新”的技术,只是一个自从 90 年代初就一直存在的新流行词。而 @jsm11482:这也正是为什么这个问题被关闭为“主观和争议性”的原因——因为它会引起争论! - Daniel Pryden
2
我的回答在这里 http://bit.ly/cAdYAr - Darrel Miller
显示剩余9条评论
5个回答

193

煤矿中的金丝雀

我等了近一年时间才等到这样的问题。这一天注定会到来,我相信在未来几个月里我们将看到更多类似的问题。

预警信号

你说得对,构建RESTful客户端确实比构建SOAP客户端需要更长的时间。SOAP工具包会帮我们处理大量样板代码,只需稍微努力即可获取代理对象。使用Visual Studio和服务器URL,我可以在不到5分钟的时间内访问任意复杂度的远程对象,就像是本地操作。

返回application/xml和application/json的服务对客户端开发人员而言非常麻烦。我们应该怎么处理那些数据块呢?

幸运的是,很多提供REST服务的网站也会提供一堆客户端库,这样我们就可以使用这些库来访问一系列强类型对象。但这看起来有点蠢。如果他们使用SOAP,我们可以自己生成代理类。

SOAP的开销,哈哈。延迟才是致命因素。如果人们真的关心网络传输时冗余字节的数量,那么也许HTTP不是正确的选择。你见过用户代理标头使用了多少字节吗?

对啊,你试过用Web浏览器作为除HTML和JavaScript以外的任何调试工具吗?相信我,那太糟糕了。你只能使用其中两个动词,缓存不停地干扰你,错误处理会吞没大量信息,它一直在寻找该死的favicon.ico。请射了我吧。

易读的URL。仅限名词,没有动词。是的,只要我们只需要进行增删改查操作,且只需以一个方向访问对象层次结构,就很容易实现。但很多应用程序需要比这更多的功能。

即将到来的灾难

当前有大批开发人员正在开发集成REST服务的应用程序,并正在得出与你相同的结论。他们被承诺了简单、灵活、可扩展、可演进和强大的重用性。这些都是Web本身的特点,怎么可能出错呢。

但是,他们发现版本控制同样是个问题,而编译器无法帮助检测问题。手写的客户端代码随着数据结构的演变和URL的重构变得难以维护。围绕名词和四种动词设计API可能会非常困难,特别是当RESTful Url狂热者告诉你什么时候可以使用查询字符串、什么时候不能。

开发人员将开始询问为什么我们要浪费精力支持Json格式和Xml格式,为什么不专注于其中一种并做好它?

事情怎么会变得如此糟糕

我告诉你出了什么问题。我们作为开发人员让营销部门利用了我们主要的弱点。我们对银弹的永恒追求使我们对REST的真实面貌失去了认知。在表面上,REST似乎很容易和简单。使用URL命名资源,并使用GET、PUT、POST和DELETE。该死,我们开发人员已经知道如何做了,我们处理具有表和列以及SELECT、INSERT、UPDATE和DELETE SQL语句的数据库多年了。它应该是小菜一碟。
REST 的其他部分也被某些人讨论,例如自描述性和超媒体约束,但这些约束并不像资源标识和统一接口那样简单。它们似乎增加了复杂性,而预期目标却是简单性。
这种浓缩版的 REST 在开发者文化中得到了验证。创建了服务器框架,鼓励资源标识和统一接口,但没有支持其他约束。术语开始流传,区分不同的方法(HI-REST vs LO-REST,Corporate REST vs Academic REST,REST vs RESTful)。
一些人大喊,如果你不应用所有约束,它就不是 REST。您将无法获得好处。没有半个 REST。但是,这些声音被贴上了宗教狂热者的标签,他们感到不安,因为他们珍贵的术语已被从深处夺走并变得流行起来。嫉妒的人试图让 REST 听起来比它更困难。
REST 这个术语肯定变得越来越流行了。几乎每个具有 API 的主要 Web 属性都支持“REST”。Twitter 和 Netflix 是两个非常高调的例子。令人恐惧的是,我只能想到一个自描述的公共 API,还有一些真正实现超媒体约束的 API。当然,像 StackOverflow 和 Gowalla 这样的网站支持响应中的链接,但是在它们的链接中存在巨大的漏洞。StackOverflow API 没有根页面。如果没有网站首页,这个网站会有多成功!
很抱歉,你被误导了。
如果您已经阅读到这里,对于您的问题的简短答案是,这些 API(Netflix 和 Twitter)不符合所有约束,因此您将无法获得 REST API 应该带来的好处。
REST 客户端的构建时间比 SOAP 客户端长,但它们不限于一个特定的服务,因此您应该能够在不同服务之间重复使用它们。以经典示例为例,Web 浏览器能够访问多少服务?Feed 阅读器呢?现在,普通的 Twitter 客户端可以访问多少不同的服务?是的,只有一个。
REST 客户端不应该仅构建用于与单个服务交互,而应该构建用于处理任何服务提供的特定媒体类型。对此的显然问题是,如何为提供 application/json 或 application/xml 的服务构建 REST 客户端?好吧,你不能。那是因为这些格式对于 REST 客户端是完全无用的。你自己说的。在管道传输过程中,你必须“猜测”将会返回什么内容,因为没有真正的模式或参考文档。
对于像Twitter这样的服务,您是完全正确的。但是,REST中的自描述约束规定HTTP内容类型标头应该准确描述正在通过管道传输的内容。传递application/json和application/xml并不能告诉您有关内容的任何信息。
在考虑基于REST的系统性能时,有必要看到更大的图片。谈论信封字节就像比较快速排序和希尔排序时谈论循环展开一样。 SOAP可以表现得更好,也有REST可以表现得更好的情况。上下文就是一切。
REST获得了很大的性能优势,因为它对支持的媒体类型非常灵活,并且具有复杂的缓存支持。但是,为了使缓存有效工作,必须遵守几乎所有的约束。
关于可读的URL,您最后的观点是非常讽刺的。如果您真正致力于超媒体约束,那么每个URL都可以是GUID,客户端开发人员不会因可读性而失去任何内容。
URI对客户端应该是不透明的,这是开发REST系统时最关键的事情之一。可读的URL对于服务器开发人员很方便,并且结构良好的URL使服务器框架更容易调度请求,但这些是不应影响使用API的开发人员的实现细节。
Twitter API甚至不接近RESTful,这就是为什么您无法看到使用它而不是SOAP的任何好处的原因。 Netflix API更接近,但其使用通用媒体类型表明,未遵守单个约束即可对服务产生深远影响。
可能并非完全是他们的错
我已经在服务提供者身上倾泻了很多东西,但是REST需要两个人来一起进行。服务可能会虔诚地遵循所有约束,而客户端仍然可以轻松地取消所有收益。
如果客户端硬编码URL以访问某些资源类型,则会阻止服务器更改这些URL。基于隐含知识如何构造URL的任何类型的URL构建都是违反规则的。
根据未在HTTP标头中明确说明的知识做出有关链接将返回哪种表述形式的假设可能会导致问题。根据这样的知识内容做出有关表述形式的假设,肯定会创建耦合,从而在未来引起痛苦。
他们是否应该使用SOAP?
个人认为不应该。正确执行REST允许分布式系统在长期内发展。如果您正在构建由不同人开发并需要持续多年的组件的分布式系统,则REST是一个不错的选择。

4
这可能并非全部属实。亚马逊为其Web服务提供了SOAP和REST接口,其中85%的使用是通过REST接口进行的。尽管所有企业都在炒作SOAP堆栈,但这是相当令人信服的证据,表明开发人员喜欢更简单的REST方法。来源:http://www.oreillynet.com/pub/wlg/3005 - Suraj Chandran
3
不,那只是有力的证据表明Web开发人员喜欢他们认为更简单的东西,并不意味着它在任何长期或性能导向的方面实际上都更优越。事实上,需要的是特定工作的正确工具,而不是“我知道这个工具,所以所有工作都必须符合它”的想法。 - Kevin Williams

61
SOAP是一种面向对象的远程过程调用技术栈。它通过在现有协议(HTTP)之上构建新的抽象来工作。
REST是一种面向文档的方法,只是利用现有协议(HTTP)的特性。"REST"只是一个流行语--这个概念就是:只需按照设计的方式使用Web!
  1. "实现REST服务比实现SOAP服务花费的时间无限长。"

    不,它不能是无限长的。如果你要检索的内容已经是文档或文件,那么实际上REST会更快。例如,OGC规范的WMS(Web Mapping Service)定义了协议的SOAP和REST版本,几乎没有人实现SOAP版本的原因是,如果您想获取地图,只需构建一个URL并从该URL获取图像字节比封装到SOAP消息中容易得多。但是,如果Web服务的目的是传输某个强类型对象在域对象模型中,那么SOAP更适合。

  2. "为什么编写返回XML的REST服务呢?"

    好吧,这可能有点傻。但这取决于XML的内容。如果有一个明确定义的架构,则没有歧义。例如,您可以将WSDL URL视为一种RESTful Web服务,用于检索有关Web服务的信息。在这种情况下,添加另一个SOAP请求的开销是没有意义的。

    总的来说,当要传输的内容可以被视为单个单元的文件时,REST胜出。当内容需要被视为具有成员的对象时,SOAP胜出。

  3. "我听说过使用SOAP时存在SOAP信封的“开销”投诉。在今天,我们真的需要担心少量字节吗?"

    是的。并非在每种情况下都是如此,但是有许多流量很大的站点存在差异。这是否足够大的差异以超过使用SOAP而不是REST的语义差异?我怀疑。如果您正在进行对象远程协议,并且字节数量很重要,则SOAP可能根本不适合您 - 也许您应该使用CORBA或DCOM。

  4. "我听说REST可以将URL直接放入浏览器中查看数据的论点。"

    是的,如果在浏览器中查看数据是有意义的话,这是支持REST的一个重要论点。例如,对于图像数据,这是一种轻松的调试服务的方法 - 只需将URL粘贴到浏览器的地址栏中,然后查看图像的外观即可。或者,如果返回的数据是XML格式,并且您有引用的XML样式表,可以在浏览器中呈现为可读HTML,则可以获得语义标记和易于可视化的好处。但是,当使用更复杂的身份验证方案时,这种好处基本上会消失。如果无法将所有身份验证信息编码到每个HTTP请求中,则我认为根本不算REST。

  5. "为什么我们需要每个资源的“可读”URL?如果我们使用工具实现服务,我们是否真的关心实际的URL?"

    好吧,这取决于情况。为什么我们需要Web上任何资源的可读URL?您可以阅读Tim Berners-Lee的文章Cool URIs Don't Change以了解原理,但基本上只要该资源在未来仍可能有用,那么该资源的URI应保持不变。

    显然,对于短暂的资源(例如文章中的“今天的货币”链接),没有必要,因为如果相应的资源消失,则引用该资源的需求也会消失。但是对于更永久的资源(例如StackOverflow问题或IMDB上的电影),您

    就记录而言,是的,早在NetFlix或Twitter存在之前,我就一直在开发网页。但是,我还没有任何需要或机会去实现客户端到NetFlix或Twitter服务的需求。但是,即使他们的服务难以使用,也并不意味着他们所实现的技术是不好的——只是这两个实现方式不好。

    长话短说:REST和SOAP只是工具。它们各有优点和缺点。如果你手头唯一的工具是锤子,那么每个问题都看起来像钉子。所以要了解这两种工具,并学习如何正确使用它们,然后为每个任务选择合适的工具。


11
请记住,SOAP并不仅限于HTTP,因此需要额外的抽象。SOAP风格的消息传递可以在许多协议上使用,因此比REST具有更广泛的覆盖范围。我认为这是一个简单的事实,许多狂热的REST支持者有时会忽视。REST有其存在的意义,但SOAP也同样重要。 - jrista
4
@jrista: 很有道理。SOAP并没有错,就像锤子一样,并没有任何问题,只要你的问题确实是钉子。相比之下,这个问题似乎在说:“我讨厌螺丝刀!为什么锤子不能对每个人都好?说服我螺丝刀应该存在!” ——当放在这个语境中时,它所揭示出来的荒谬性就显露无疑了。 - Daniel Pryden
2
REST是一种体系结构风格。如果你真的想要,可以使用SOAP实现RESTful服务。 我认为REST社区对于SOAP在HTTP方面的主要批评是,SOAP认为HTTP是一个传输协议,而它实际上是一个传输协议。 - Bruno
@Daniel:我完全同意上面的问题……这个问题很糟糕,而且非常主观和争议,绝对不能更荒谬了。 :P 不过,关于SOAP,我想要做一个区分……我认为它比“锤子”更适合被称为“瑞士军刀”。 ;P - jrista
3
@Daniel 哎呀!我并没有想冒犯任何人。我认为REST不是这些服务和类似服务的正确方法,这是一个诚实的询问。请不要一开始就否定我的问题。我认为这里的“争论”没关系,因为事实上,我正在提出一个观点。我只是想要一个反驳。对我来说,说REST“使用了网页设计的方式”听起来像“在我们还没有Twitter和Facebook之前……”您没有提供任何解释REST为何适用于这些类型的服务的信息。可以详细说明一下吗? - Josh M.
显示剩余3条评论

17

一个诚实的问题应该得到一个诚实的回答。但首先,如果你不认为这个问题是修辞性的,为什么要把这个问题的文本作为另一个问题的答案呢?

无论如何:

  1. "现代语言/框架/平台都有工具来读取WSDL并输出代理类和客户端。手动实现REST服务需要通过阅读文档完成。"

    就像浏览器供应商已经反复阅读HTML 4.01规范一样,试图实现一致的浏览体验。你是否思考过,浏览器早在Internet银行和StackOverflow之前就已经发明了,但是你仍然可以使用浏览器来做这些事情。这是因为每个人都同意使用HTML(以及相关格式,如CSS、JS、JPEG等)的唯一原因。

    博客其实并不是那么新鲜,有人想出了AtomPub,它允许任何博客软件访问和更新博客中的帖子,就像任何网页浏览器可以访问任何网页一样。这很棒,因为它符合RESTful协议所施加的限制。

    但对于Twitter和Netflix,没有普遍的协议规定“所有微博都必须使用应用程序/推文媒体类型”,主要是因为微博很新。也许几年后,一些微博服务会就相同的API达成共识,这样Twitter、Facebook、Identica等就可以互操作了。然而,它们现有的任何API都远远不符合RESTful,无论它们声称什么,所以我对它很快会发生的事情并不抱有期望。

    "此外,在实现这两个服务时,您必须猜测将通过管道返回什么内容,因为没有真正的模式或参考文件。"

    你说得很对。REST架构风格主要关注分布式和超媒体,这基本上就是它的全部了。浏览器会查看请求返回的内容并将其显示给用户。一个HTML页面通常会产生更多的GET请求,例如CSS、脚本和图片。图片通常只呈现到屏幕上,JavaScript被执行等等。每次,浏览器做它该做的事情,因为在<img><style>标签中发现了链接,并且响应的媒体类型是image/jpegtext/css

    如果Twitter创建一个基于超媒体的API,每当你跟随一个指向推文的链接时,它可能总是返回一个application/tweet,但客户端不应该假定它,总是在处理之前检查返回的内容。

  2. "为什么要编写返回XML的REST服务呢?"

    这一切都归结于媒体类型。就像HTML一样,如果你看到一个元素,你不知道它实际上代表什么,HTML规范告诉你忽略它们,并处理它是否有一个"body"。同样,Atom规范告诉你忽略未知元素和外部标记(来自不同的命名空间),并且处理正文(IIRC)。

    为通用问题域(如丰富文本问题域的HTML媒体类型)设计媒体类型非常困难。为非常狭窄的问题域制作媒体类型可能要容易得多(比如一条推文)。但最好考虑可扩展性并指定客户端(和服务器)在看到不符合规范的元素或数据项时应该如何反应。例如,JPEG有一个特定于应用程序的记录类型(例如APP1),用于包含各种元数据。

  3. "我听到过这样的抱怨,使用SOAP会有SOAP信封的“开销”。在当今这个时代,我们真的需要担心几个字节吗?"

    不需要。REST绝对不是为了在通讯中更高效,实际上是以牺牲通讯效率来换取其他限制所提供的缓存机制的优势: Fielding的论文指出:牺牲的是效率,因为信息是以标准化的形式传输的,而不是特定于应用程序需求的形式。REST接口被设计为适合大粒度超媒体数据传输的,优化了Web的常见情况,但导致接口不适用于其他形式的架构交互。 我认为SOAP信封字节数的开销不是一个有效的问题。

  4. "我听说使用REST,你只需将URL复制到浏览器中即可查看数据。"

    是的,那也是一个无效的论点。它不是那么简单。即使它能工作,大多数出现的狭窄的REST API使用浏览器不知道的媒体类型仍然无法访问。

    但是,除了浏览器之外,还有很多测试HTTP API的可能性,例如命令行实用程序或浏览器扩展程序,使您可以控制几乎所有HTTP请求的方面,检查响应头并为您发现要跟随的链接。但即便如此,这也远不及生成WSDL存根并编写三行程序来调用该函数容易。

  5. "为什么我们需要为每个资源使用“可读”URL?如果我们使用工具来实现服务,我们真的关心实际的URL吗?"

    如果你看一下网页是如何工作的,我相信人们大多都很高兴维基百科页面的URI看起来像这样:http://en.wikipedia.org/wiki/Stack_overflow而不是像这样:http://en.wikipedia.org/wiki/?oldid=376349090。但这实际上对于REST并不重要。重要的是尽量选择将相关数据放在URI中,而这些数据不太可能改变。您可能认为数据库ID永远不会改变,但是当需要合并两个数据集时会发生什么?所有的主键都会改变,而页面标题(Stack_overflow)则不会改变。

  6. 抱歉回复太长了,但我认为这是一个有效的问题,在这里还没有得到解决。我相信Darrel Miller回来后也会添加他的答案。

    编辑:格式化


7

这篇文章很好地解释了ReST;但SOAP只被简要提及了一次。两者之间没有进行比较。 - jaco0646

3

WSDL和其他文档级协议是多余的。HTTP协议支持比仅提供文档和提交表单更丰富的操作。

REST的支持者对此冗余感到不舒服。


这并没有告诉我为什么我应该在这些类型的服务中使用REST。对我来说,它只是不太“合适”。说“HTTP协议支持除了提供文档和提交表单之外的更丰富的操作”并不意味着我们应该实际使用它们,如果存在更好的解决方案! - Josh M.
我所暗示的是REST本身非常精简。它在协议(HTTP)层工作。 - BC.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接