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

我已经实现了两个REST服务:Twitter和Netflix。 这两次,我努力寻找决定将这些服务公开为REST而不是SOAP的决定所涉及的用途和逻辑。 我希望有人能够告诉我我缺less的东西,并解释为什么REST被用作这些服务的服务实现。

1)实现REST服务比实现SOAP服务花费的时间要长得多。 所有现代语言/框架/平台的工具都可以在WSDL中读取并输出代理类和客户端。 实现一个REST服务是通过手工完成的,通过阅读文档来获得这个服务。 此外,在实施这两项服务的同时,您还必须“猜测”什么会回来,因为没有真正的模式或参考文件。

2)为什么编写一个返回XML的REST服务呢? 唯一的区别是,使用REST你不知道每个元素/属性代表的types – 你自己来实现它,并希望有一天一个string不会出现在你认为总是一个整数的字段中。 SOAP使用WSDL定义了数据结构,所以这是一个简单的事情。

3)我听说过使用SOAP的投诉,您有SOAP Envelope的“开销”。 在这个时代,我们真的需要担心less数几个字节吗?

4)我听说过REST,你可以将URLpopup到浏览器中查看数据。 当然,如果你的REST服务使用简单的或者没有authentication。 例如,Netflix服务使用OAuth,在您提交请求之前,您需要对事物进行签名和编码。

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

煤矿里的金丝雀。

我现在一直在等待这样的问题近一年。 这一天不可避免,我相信在接下来的几个月里,我们将会看到更多类似的问题。

警告标志

您绝对正确,构buildRESTful客户端比SOAP客户端需要更长的时间。 SOAP工具包带走了大量的样板代码,几乎毫不费力就可以使客户端代理对象可用。 使用像Visual Studio和服务器URL这样的工具,我可以在五分钟内在本地访问任意复杂的远程对象。

返回application / xml和application / json的服务对于客户端开发者来说是非常烦人的。 我们应该怎样处理这些数据呢?

幸运的是,许多提供REST服务的站点还提供了一堆客户端库,以便我们可以使用这些库来访问大量强types对象。 似乎有点愚蠢。 如果他们使用SOAP,我们可以自己编写代理类。

SOAP开销,哈。 这是杀死的延迟。 如果人们真的担心通过networking的超出字节数,那么HTTP可能不是正确的select。 你见过用户代理头有多less字节?

是啊,你有没有试过使用networking浏览器作为除HTML和JavaScript以外的其他任何debugging工具。 相信我这很糟糕。 你只能使用其中的两个动词,caching是不断的阻碍,error handling吞下了这么多的信息,它不断地寻找一个该死的favicon.ico。 只要开枪

可读的URL。 只有名词,没有动词。 是的,只要我们只做CRUD操作就可以了,我们只需要以一种方式访问​​对象的层次结构。 不幸的是,大多数应用程序需要比这更多的function。

即将发生的灾难

目前正在开发一系列开发应用程序的开发人员,这些应用程序与REST服务集成在一起,这些服务正在与您得到相同的结论集。 他们承诺简单,灵活,可伸缩性,可演化性和偶然重用的圣杯。 networking本身的特点,怎么会出事呢。

但是,他们发现版本控制同样是个问题,但是编译器不能帮助检测问题。 随着数据结构的演变和URL的重构,手写客户端代码是一个难题。 围绕名词和四个动词deviseAPI可能非常困难,尤其是在REST风格的Url狂热者可以告诉你什么时候可以使用查询string的时候。

开发人员会开始问我们为什么要浪费我们的努力来支持JSON格式和Xml格式,为什么不把我们的努力集中在一个,做得好呢?

事情怎么搞错了

我会告诉你哪里出了问题。 我们作为开发商让市场部门利用我们的主要弱点。 我们对银弹的永恒追求使我们忽视了REST真正的现实。 在表面REST看起来很容易和简单。 使用Urls命名您的资源,并使用GET,PUT,POST和DELETE。 地狱,我们开发人员已经知道如何做到这一点,我们一直在处理数据库多年的表和列和SQL语句有SELECT,INSERT,UPDATE和DELETE。 应该是一块蛋糕。

还有一些人讨论过REST的其他部分,比如自描述性和超媒体约束,但这些约束并不像资源标识和统一接口那么简单。 在希望的目标是简单的情况下,似乎增加了复杂性。

这种淡化REST版本在许多方面在开发者文化中得到了validation。 服务器框架的创build鼓励了资源标识和统一接口,但没有做任何事情来支持其他约束。 术语开始围绕着差异化的方法(HI-REST与LO-REST,企业REST与学术REST,REST与RESTful)有所不同。

有些人尖叫,如果你不应用所有的约束不是REST。 你不会得到好处。 没有一半REST。 但是这些声音被贴上了宗教狂热分子的标签,他们为自己的宝贵名词被从朦胧中偷走而成为主stream而感到不安。 嫉妒的人试图使REST听起来更难。

REST这个词已经成为主stream。 几乎每个拥有API的主要networking媒体资源都支持“REST”。 Twitter和Netflix是两个非常高调的。 可怕的是,我只能想到一个自描述的公共API,有一些真正实现超媒体约束。 确保一些像StackOverflow和Gowalla这样的站点在响应中支持链接,但是链接中有巨大的漏洞。 StackOverflow API没有根页面。 想象一下,如果网站没有主页,那么网站会是多么的成功!

你害怕我被误导了

如果你已经做到了这一点,那么你的问题的简短答案是这些API(Netflix和Twitter)不符合所有的约束,因此你不会得到REST apis应该带来的好处。

与SOAP客户端相比,REST客户端的构build需要花费更长的时间,但是他们并没有绑定到一个特定的服务,所以您应该能够跨服务重用它们。 以Web浏览器的经典示例为例。 网页浏览器可以访问多less项服务? 怎么样饲料读者? 现在,平均Twitter客户端可以访问多less个不同的服务? 是的,只有一个。

REST客户端不应该被构build为与单个服务接口,它们应该被构build来处理可以由任何服务服务的特定媒体types。 显而易见的问题是,如何为一个提供application / json或application / xml的服务构build一个REST客户端。 那么你不能。 这是因为这些格式对于REST客户端完全没有用处。 你自己说,

因为没有真正的模式或参考文件,所以你必须“猜测”什么会回来

你对Twitter这样的服务绝对正确。 但是,REST中的自描述性约束表明,HTTP内容types头应该精确描述通过线路传输的内容。 交付应用程序/ JSON和应用程序/ XML告诉你什么关于内容。

当考虑基于REST的系统的性能时,有必要查看更大的图片。 谈论信封字节就像谈到快速sorting和shellsorting时的循环展开一样。 有些情况下SOAP可以更好地执行,并且有些情况下REST可以更好地执行。 上下文就是一切。

REST通过对其支持的媒体types以及对高速caching的复杂支持非常灵活,从而获得了很多性能优势。 尽pipe几乎所有的约束条件都必须遵守,caching才能正常工作。

关于可读URL的最后一点是最具讽刺意味的。 如果您确实承诺超媒体约束,那么每个URL都可以是一个GUID,客户端开发人员在可读性方面不会丢失任何内容。

对于客户端而言,URI对于不透明的事实是开发REST系统时最关键的事情之一。 对于服务器开发人员来说,可读URL是很方便的,结构良好的URL使得服务器框架能够更容易地分派请求,但这些实现细节应该对使用API​​的开发人员没有影响。

Twitter API甚至没有接近RESTful,这就是为什么你无法看到使用SOAP的好处。 Netflix API距离更近,但通用媒体types的使用表明,即使不能遵守单一的约束条件,也会对服务带来的好处产生深远的影响。

这可能不是他们的错

我在服务提供商方面做了很多倾销,但是需要两个人来进行REST风格的跳舞。 服务可以在宗教上遵循所有的约束条件,并且客户仍然可以容易地取消所有的好处。

如果客户端硬编码访问某些types的资源,那么它会阻止服务器更改这些URL。 基于对服务如何构build其url的隐式知识的任何types的URL构build都是违规的。

假设从链接返回什么types的表示会导致问题。 根据HTTP头文件中没有明确规定的知识对表示内容做出假设,肯定会造成耦合,将来会引起痛苦。

他们是否应该使用SOAP?

我个人并不这么认为。 REST做得正确,可以使分布式系统长期发展。 如果你正在构build分布式系统,这些系统的组件由不同的人开发,需要持续很多年,那么REST是一个不错的select。

SOAP是一个面向对象的 远程过程调用技术栈。 它通过在现有协议(HTTP)之上构build新的抽象来工作。

REST是一种面向文档的方法,它简单地使用现有协议(HTTP)的function。 “REST”只是一个stream行词 – 概念是这样的:只要按照它devise的方式使用networking!

回应编辑质疑:

  1. “实现REST服务比实现SOAP服务花费的时间要长得多。”

    嗯,不,它不能无限延长。 而在你想要检索的东西已经是文件或文件的情况下 ,实际上要快得多 。 例如,WMS(Web Mapping Service)的OGC规范定义了协议的SOAP和REST版本,几乎没有人实现SOAP版本是有原因的 – 这是因为如果你想获得地图,只需构build一个URL并从该URL获取图像字节比将其封装到SOAP消息中更容易。 但是,我同意,如果Web服务的重点是在域对象模型中传递一些强types的对象,则SOAP更适合这种用途。

  2. “为什么编写一个返回XML的REST服务呢?”

    那么,是的,这可能是愚蠢的。 但这取决于XML是什么。 如果在某个地方有明确定义的模式,那就没有歧义。 例如,您可以将WSDL URL视为一种REST风格的Web服务,用于检索有关Web服务的信息。 在这种情况下,增加另一个SOAP请求的开销将是毫无意义的。

    一般来说,当正在传输的内容可​​以被认为是一个单独文件时,REST获胜。 当内容需要被视为成员对象时,SOAP获胜。

  3. “我听说过这样的抱怨:在SOAP中,SOAP Envelope具有”开销“,在这个时代,我们真的需要担心几个字节吗?

    是。 不是在任何情况下,但是有很多stream量的网站在其中有所作为。 它是否足以胜过使用SOAP而不是REST的语义差异 ? 我对此表示怀疑。 如果你正在做一个对象远程协议和字节数有所作为,SOAP可能不是你的工具 – 也许你应该使用CORBA或DCOM。

  4. “我听说过这样的观点:使用REST,您可以将URLpopup到浏览器中查看数据。”

    是的, 如果在浏览器中查看数据是有意义的 ,这是支持REST的一个大的论据。 例如,对于图像数据,这是一个debugging服务的简单方法 – 只需将url粘贴到浏览器的地址栏中即可看到图像的外观。 或者,如果返回的数据是XML格式的,而且您有一个引用的XML样式表在浏览器中呈现为可读的HTML,那么您可以在一个包中获得语义标记和简单可视化的好处。 但是你是正确的,这个好处大部分是在更复杂的authenticationscheme下消失的。 如果你不能把所有的authentication信息都编码到每一个HTTP请求中 ,那么我会认为它根本不算作REST。

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

    这得看情况。 为什么我们需要可读的URL在networking上的任何资源? 你可以阅读蒂姆·伯纳斯·李(Tim Berners-Lee)的文章Cool URIs不要改变原理,但基本上,只要资源在将来仍然有用,那么资源的URI就应该保持不变。

    很明显,对于短暂的资源(如文章中的“今天的钱”链接),不需要它,因为如果相应的资源消失,引用资源的需求就会消失。 但是对于更永久的资源(例如StackOverflow问题,或IMDB上的电影),您希望拥有一个永久有效的URL。 在deviseWeb服务时,您需要确定资源本身是否可以超越您的服务,如果是这样,那么REST可能是正确的select。

为了logging,是的,自从NetFlix或Twitter存在之前,我一直在开发网页。 不,我还没有任何需要或有机会实施NetFlix或Twitter的服务的客户。 但是,即使他们的服务非常难以使用,这并不意味着他们在其上实施服务的技术是不好的 – 只是这两种实现是不好的。

长话短说:REST和SOAP 只是工具 。 他们各有优点和缺点。 如果你唯一的工具是锤子,那么每一个问题看起来像一个钉子。 因此,了解这两种工具,并学习如何正确使用它们,然后为每项工作select合适的工具。

一个诚实的问题值得诚实的回答。 但是,首先,如果你不认为这是一个修辞的话,你为什么用这个问题的文本作为另一个问题的答案呢?

无论如何:

  1. 所有现代语言/框架/平台的工具都可以在WSDL中读取并输出代理类和客户端。实现REST服务是通过阅读文档手动完成的。

    就像浏览器供应商已经阅读并重新阅读HTML 4.01规范来尝试实现一致的浏览体验。 你有没有反映浏览器是早在互联网银行和计算器之前发明的事实,然而,你可以使用浏览器来做这些事情。 这是因为每个人都同意使用HTML(以及CSS,JS,JPEG等相关格式)的唯一原因。

    博客实际上并不是什么新鲜事,有人提出了AtomPub,它允许任何博客软件访问和更新博客中的post,就像任何网页浏览器可以访问任何网页一样。 这是相当整洁,因为协议施加的RESTful约束,工程。

    但对Twitter和Netflix而言,目前还没有普遍认同的“所有微博都会使用媒体types的应用/推特”,这主要是因为微博如此新颖。 也许在几年的时间里,一些微博服务落户于相同的API,以便Twitter,Facebook,Identica和互操作。 他们现有的API都不在RESTful附近,不pipe他们声称多less,所以我不认为它会很快发生。

    而且,在实施这两项服务的同时,你还必须”猜测“pipe道中会发生什么,因为没有真正的模式或参考文件。

    你已经击中了头部。 REST全部是关于分布式和超媒体的,几乎可以总结出来。 浏览器查看从请求获得的内容并将其显示给用户。 一个HTML页面通常会产生更多的GET请求,例如CSS,脚本和图像。 一个图像通常只被渲染到屏幕上,JavaScript被执行,等等。 浏览器每次都会执行它的function,因为它find了<img><style>标记中的链接,并且响应媒体types为image/jpegtext/css

    如果Twitter制作了一个基于超媒体的API,那么每当你关注推特的链接时,它可能总会返回一个application/tweet文,但是客户端永远不应该假设它,并且总是在进行操作之前检查它是什么。

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

    这一切都归结为媒体types。 像HTML一样,如果你看到一个你不知道实际意义的元素,那么HTML规范指示你忽略它们,并且处理标签的“主体”(如果有的话)。 同样,primefaces规范指示您忽略未知元素和外部标记(来自不同的名称空间), 而不处理正文(IIRC)。

    为通用问题域devise媒体types(如富文本问题域的HTML媒体types)非常困难。 为非常狭窄的问题域制作媒体types可能更容易(比如推特)。 但是,devise可扩展性并指定客户端(和服务器)在看到不符合规范的元素或数据项时应如何反应总是一个好主意。 例如,JPEG具有用于包含各种元数据的特定于应用程序的loggingtypes(例如APP1)。

  3. 我听说过这样的抱怨:在SOAP中,SOAP Envelope具有”开销“,在这个时代,我们真的需要担心几个字节吗?

    不,我们不。 REST绝对不是关于在线路上的有效性,而是实际上是在交换线路效率。REST的效率来自所有其他约束所实现的caching的可能性: Fielding的论文指出: 但是,权衡是统一的接口退化效率,因为信息是以标准化的forms传输的,而不是专门针对应用程序需求的信息。 REST接口被devise为对于大规模超媒体数据传输是高效的,针对Web的常见情况进行优化,但是导致其他forms的架构交互不是最佳的接口。 我不认为SOAP Envelope字节数开销是一个有效的问题。

  4. 我听说过这样的观点:使用REST,您可以将URLpopup到浏览器中查看数据。

    是的,这也是一个无效的论点。 这种方式不行。 即使这样做确实有效,但是大多数REST API都使用了浏览器不知道的媒体types,但仍然无法正常工作。

    但是,比浏览器testing基于HTTP的API更多的可能性,比如命令行工具或浏览器扩展,它们允许您控制HTTP请求的几乎任何方面,检查响应头并发现要遵循的链接。 但是,即使如此,这也远不如生成WSDL存​​根并使三行程序调用该函数那么简单。

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

    如果你看看networking是如何工作的,我敢肯定人们总是很高兴维基百科页面的URI看起来像这样, http://en.wikipedia.org/wiki/?oldid=376349090 http://en.wikipedia.org/wiki/Stack_overflow而不是http://en.wikipedia.org/wiki/?oldid=376349090 。 但是对于REST其实并不重要。 尝试正确的重要事情是select将相关数据放在不太可能改变的URI中。 你可能会认为数据库ID永远不会改变,但当两个数据集需要合并时会发生什么? 所有的主键都会改变。 页面标题(Stack_overflow)不会改变。

对不起,长时间的回应,但我相信这个问题是有效的,并没有在此之前解决这个SO。 我相信Darrel Miller也会在他回来的​​时候加上他的答案。

编辑:格式

Martin Fowler 在Richardson成熟度模型上发表了一篇文章,对解释SOAP和REST之间的区别做了很好的工作。

WSDL和其他文档级别的协议是多余的。 除了提供文档和提交表单之外,HTTP协议还支持更丰富的操作。

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