我已经实现了两个REST服务:Twitter和Netflix.两次,我都在努力寻找将这些服务公开为REST而不是SOAP的决策所涉及的用途和逻辑.我希望有人能够让我知道我所缺少的内容并解释为什么将REST用作这些服务的服务实现.
实现REST服务比实现SOAP服务花费的时间更长.所有现代语言/框架/平台都存在用于读取WSDL并输出代理类和客户端的工具.实现REST服务是手工完成的 - 通过阅读文档来实现这一点.此外,在实现这两个服务时,您必须"猜测"管道中将返回的内容,因为没有真正的架构或参考文档.
为什么要编写一个返回XML的REST服务呢?唯一的区别是,使用REST,您不知道每个元素/属性所代表的类型 - 您可以自己实现它,并希望有一天字符串不会出现在您认为总是为int的字段中.SOAP使用WSDL定义数据结构,因此这是一个明智的选择.
我听说过使用SOAP,你有SOAP信封的"开销".在这个时代,我们真的需要担心少数几个字节吗?
我听说过用REST可以将URL弹出到浏览器中并查看数据.当然,如果您的REST服务使用简单或无需身份验证.例如,Netflix服务使用OAuth,它要求您在提交请求之前对事物进行签名和编码.
为什么我们需要每个资源的"可读"URL?如果我们使用工具来实现服务,我们真的关心实际的URL吗?
Darrel Mille.. 193
煤矿中的金丝雀.
我一直在等待近一年这样的问题.这一天不可避免地会到来,我相信在接下来的几个月里我们会看到更多这样的问题.
警告标志
你是绝对正确的,构建RESTful客户端需要比SOAP客户端更长的时间.SOAP工具包带走了许多样板代码,并且几乎不费力地使客户端代理对象可用.使用像Visual Studio和服务器URL这样的工具,我可以在五分钟内在本地访问任意复杂度的远程对象.
返回application/xml和application/json的服务对于客户端开发人员来说非常烦人.我们该怎么处理那一团数据呢?
幸运的是,许多提供REST服务的站点还提供了许多客户端库,以便我们可以使用这些库来访问一堆强类型对象.看起来有点愚蠢.如果他们使用过SOAP,我们可以自己编写代码类代码.
SOAP开销,哈.它的延迟会导致死亡.如果人们真正关心通过线路的多余字节数,那么HTTP可能不是正确的选择.您是否看到了用户代理标头使用了多少字节?
是的,你有没有尝试过使用网络浏览器作为HTML和javascript以外的任何调试工具.相信我很糟糕.你只能使用两个动词,缓存不断阻碍,错误处理吞下了这么多信息,它一直在寻找一个该死的favicon.ico.只是拍我
可读的URL.只有名词,没有动词.是的,只要我们只进行CRUD操作并且我们只需要以一种方式访问对象的层次结构,这很容易.不幸的是,大多数应用程序需要比这更多的功能.
迫在眉睫的灾难
目前正在开发一大批开发人员,开发与REST服务集成的应用程序,这些服务正在为您提供相同的结论.它们被承诺简单,灵活,可扩展,可演化以及偶然重用的圣杯.网络本身的特点,怎么会出问题.
但是,他们发现版本控制同样是一个问题,但编译器无法帮助检测问题.随着数据结构的发展和URL的重构,手写的客户端代码很难维护.仅使用名词和四个动词设计API可能非常困难,特别是在RESTful Url狂热者告诉您何时可以使用查询字符串时.
开发人员将开始问我们为什么要浪费我们的努力来支持Json格式和Xml格式,为什么不把我们的工作集中在一个并做得好呢?
事情怎么会这么错
我会告诉你出了什么问题.我们作为开发人员让营销部门利用我们的主要弱点.我们对银弹的永恒追求使我们对REST真实存在的现实视而不见.从表面上看,REST看似简单易行.使用Urls命名您的资源并使用GET,PUT,POST和DELETE.地狱,我们开发人员已经知道如何做到这一点,我们多年来一直在处理数据库,这些数据库有表,列和具有SELECT,INSERT,UPDATE和DELETE的SQL语句.它应该是小菜一碟.
一些人讨论的还有REST的其他部分,例如自描述性和超媒体约束,但这些约束并不像资源识别和统一接口那么简单.似乎增加了复杂性,其中期望的目标是简单性.
REST的这个淡化版本在很多方面都在开发者文化中得到了验证.创建了服务器框架,鼓励资源标识和统一接口,但没有做任何事情来支持其他约束.条款开始浮出差异化的方法,(HI-REST与LO-REST,企业REST与学术REST,REST与RESTful).
有些人尖叫说如果你不应用所有约束,那就不是REST.你不会得到好处.没有一半REST.但是那些声音被标记为宗教狂热分子,他们对自己的宝贵术语被默默无闻并成为主流而感到不安.嫉妒的人试图让REST听起来比现在更困难.
REST这个词肯定已成为主流.几乎每个拥有API的主要Web属性都支持"REST".Twitter和Netflix是两个非常引人注目的.可怕的是,我只能想到一个自我描述的公共API,并且有一些真正实现超媒体约束的公共API.当然像StackOverflow和Gowalla这样的网站在他们的回复中支持链接,但是他们的链接存在巨大的漏洞.StackOverflow API没有根页面.想象一下,如果网站没有主页,网站会有多成功!
你被误导了我害怕
如果您已经做到这一点,那么您的问题的简短答案是那些API(Netflix和Twitter)不符合所有约束,因此您将无法获得REST apis应该带来的好处.
REST客户端构建的时间比SOAP客户端要长,但它们并不依赖于某个特定服务,因此您应该能够跨服务重用它们.以网络浏览器的经典例子为例.Web浏览器可以访问多少服务?Feed阅读器怎么样?现在普通的Twitter客户端可以访问多少种不同的服务?是的,只有一个.
REST客户端不应该构建为与单个服务接口,它们应该构建为处理可由任何服务提供的特定媒体类型.显而易见的问题是,如何为提供application/json或application/xml的服务构建REST客户端.嗯,你不能.那是因为这些格式对REST客户端完全没用.你自己说的,
由于没有真正的架构或参考文档,你必须对管道中的内容做出"猜测"
对于像Twitter这样的服务,你是完全正确的.但是,REST中的自描述约束表明HTTP内容类型标题应该准确描述通过线路传输的内容.提供application/json和application/xml不会告诉您有关内容的任何信息.
在考虑基于REST的系统的性能时,有必要从更大的角度来看.在将快速排序与shell排序进行比较时,谈论包络字节就像谈论循环展开一样.有些情况下SOAP可以更好地执行,并且有些情况下REST可以更好地执行.语境就是一切.
REST通过非常灵活地支持它所支持的媒体类型以及对缓存的复杂支持来获得其大部分性能优势.尽管几乎所有的约束都必须遵守,但缓存才能正常工作.
关于可读网址的最后一点是迄今为止最具讽刺意味的.如果您真的致力于超媒体约束,那么每个URL都可能是GUID,而客户端开发人员在可读性方面将失去任何东西.
在开发REST系统时,URI应该对客户端不透明这一事实是最重要的事情之一.可读URL对于服务器开发人员来说很方便,结构良好的URL使服务器框架更容易分派请求,但这些实现细节应该对使用API的开发人员没有影响.
Twitter API甚至不接近RESTful,这就是为什么你无法看到使用它而不是SOAP的任何好处.Netflix API更接近,但它使用通用媒体类型表明,如果不遵守单一约束,就会对服务带来的好处产生深远的影响.
这可能不是他们的全部错
我已经对服务提供商进行了大量的倾销,但是要花两个时间来RESTful跳舞.服务可以虔诚地遵循所有约束,并且客户仍然可以轻松地撤消所有益处.
如果客户端硬编码URL访问某些类型的资源,则阻止服务器更改这些URL.基于对服务如何构建其URL的隐式知识的任何类型的URL构造都是违规的.
假设从链接返回什么类型的表示可能会导致问题.基于HTTP头中未明确声明的知识对表示的内容进行假设肯定会产生将导致未来痛苦的耦合.
他们应该使用SOAP吗?
就个人而言,我不这么认为.REST完成权限允许分布式系统长期发展.如果您正在构建具有由不同人员开发并且需要持续多年的组件的分布式系统,那么REST是一个非常好的选择.
煤矿中的金丝雀.
我一直在等待近一年这样的问题.这一天不可避免地会到来,我相信在接下来的几个月里我们会看到更多这样的问题.
警告标志
你是绝对正确的,构建RESTful客户端需要比SOAP客户端更长的时间.SOAP工具包带走了许多样板代码,并且几乎不费力地使客户端代理对象可用.使用像Visual Studio和服务器URL这样的工具,我可以在五分钟内在本地访问任意复杂度的远程对象.
返回application/xml和application/json的服务对于客户端开发人员来说非常烦人.我们该怎么处理那一团数据呢?
幸运的是,许多提供REST服务的站点还提供了许多客户端库,以便我们可以使用这些库来访问一堆强类型对象.看起来有点愚蠢.如果他们使用过SOAP,我们可以自己编写代码类代码.
SOAP开销,哈.它的延迟会导致死亡.如果人们真正关心通过线路的多余字节数,那么HTTP可能不是正确的选择.您是否看到了用户代理标头使用了多少字节?
是的,你有没有尝试过使用网络浏览器作为HTML和javascript以外的任何调试工具.相信我很糟糕.你只能使用两个动词,缓存不断阻碍,错误处理吞下了这么多信息,它一直在寻找一个该死的favicon.ico.只是拍我
可读的URL.只有名词,没有动词.是的,只要我们只进行CRUD操作并且我们只需要以一种方式访问对象的层次结构,这很容易.不幸的是,大多数应用程序需要比这更多的功能.
迫在眉睫的灾难
目前正在开发一大批开发人员,开发与REST服务集成的应用程序,这些服务正在为您提供相同的结论.它们被承诺简单,灵活,可扩展,可演化以及偶然重用的圣杯.网络本身的特点,怎么会出问题.
但是,他们发现版本控制同样是一个问题,但编译器无法帮助检测问题.随着数据结构的发展和URL的重构,手写的客户端代码很难维护.仅使用名词和四个动词设计API可能非常困难,特别是在RESTful Url狂热者告诉您何时可以使用查询字符串时.
开发人员将开始问我们为什么要浪费我们的努力来支持Json格式和Xml格式,为什么不把我们的工作集中在一个并做得好呢?
事情怎么会这么错
我会告诉你出了什么问题.我们作为开发人员让营销部门利用我们的主要弱点.我们对银弹的永恒追求使我们对REST真实存在的现实视而不见.从表面上看,REST看似简单易行.使用Urls命名您的资源并使用GET,PUT,POST和DELETE.地狱,我们开发人员已经知道如何做到这一点,我们多年来一直在处理数据库,这些数据库有表,列和具有SELECT,INSERT,UPDATE和DELETE的SQL语句.它应该是小菜一碟.
一些人讨论的还有REST的其他部分,例如自描述性和超媒体约束,但这些约束并不像资源识别和统一接口那么简单.似乎增加了复杂性,其中期望的目标是简单性.
REST的这个淡化版本在很多方面都在开发者文化中得到了验证.创建了服务器框架,鼓励资源标识和统一接口,但没有做任何事情来支持其他约束.条款开始浮出差异化的方法,(HI-REST与LO-REST,企业REST与学术REST,REST与RESTful).
有些人尖叫说如果你不应用所有约束,那就不是REST.你不会得到好处.没有一半REST.但是那些声音被标记为宗教狂热分子,他们对自己的宝贵术语被默默无闻并成为主流而感到不安.嫉妒的人试图让REST听起来比现在更困难.
REST这个词肯定已成为主流.几乎每个拥有API的主要Web属性都支持"REST".Twitter和Netflix是两个非常引人注目的.可怕的是,我只能想到一个自我描述的公共API,并且有一些真正实现超媒体约束的公共API.当然像StackOverflow和Gowalla这样的网站在他们的回复中支持链接,但是他们的链接存在巨大的漏洞.StackOverflow API没有根页面.想象一下,如果网站没有主页,网站会有多成功!
你被误导了我害怕
如果您已经做到这一点,那么您的问题的简短答案是那些API(Netflix和Twitter)不符合所有约束,因此您将无法获得REST apis应该带来的好处.
REST客户端构建的时间比SOAP客户端要长,但它们并不依赖于某个特定服务,因此您应该能够跨服务重用它们.以网络浏览器的经典例子为例.Web浏览器可以访问多少服务?Feed阅读器怎么样?现在普通的Twitter客户端可以访问多少种不同的服务?是的,只有一个.
REST客户端不应该构建为与单个服务接口,它们应该构建为处理可由任何服务提供的特定媒体类型.显而易见的问题是,如何为提供application/json或application/xml的服务构建REST客户端.嗯,你不能.那是因为这些格式对REST客户端完全没用.你自己说的,
由于没有真正的架构或参考文档,你必须对管道中的内容做出"猜测"
对于像Twitter这样的服务,你是完全正确的.但是,REST中的自描述约束表明HTTP内容类型标题应该准确描述通过线路传输的内容.提供application/json和application/xml不会告诉您有关内容的任何信息.
在考虑基于REST的系统的性能时,有必要从更大的角度来看.在将快速排序与shell排序进行比较时,谈论包络字节就像谈论循环展开一样.有些情况下SOAP可以更好地执行,并且有些情况下REST可以更好地执行.语境就是一切.
REST通过非常灵活地支持它所支持的媒体类型以及对缓存的复杂支持来获得其大部分性能优势.尽管几乎所有的约束都必须遵守,但缓存才能正常工作.
关于可读网址的最后一点是迄今为止最具讽刺意味的.如果您真的致力于超媒体约束,那么每个URL都可能是GUID,而客户端开发人员在可读性方面将失去任何东西.
在开发REST系统时,URI应该对客户端不透明这一事实是最重要的事情之一.可读URL对于服务器开发人员来说很方便,结构良好的URL使服务器框架更容易分派请求,但这些实现细节应该对使用API的开发人员没有影响.
Twitter API甚至不接近RESTful,这就是为什么你无法看到使用它而不是SOAP的任何好处.Netflix API更接近,但它使用通用媒体类型表明,如果不遵守单一约束,就会对服务带来的好处产生深远的影响.
这可能不是他们的全部错
我已经对服务提供商进行了大量的倾销,但是要花两个时间来RESTful跳舞.服务可以虔诚地遵循所有约束,并且客户仍然可以轻松地撤消所有益处.
如果客户端硬编码URL访问某些类型的资源,则阻止服务器更改这些URL.基于对服务如何构建其URL的隐式知识的任何类型的URL构造都是违规的.
假设从链接返回什么类型的表示可能会导致问题.基于HTTP头中未明确声明的知识对表示的内容进行假设肯定会产生将导致未来痛苦的耦合.
他们应该使用SOAP吗?
就个人而言,我不这么认为.REST完成权限允许分布式系统长期发展.如果您正在构建具有由不同人员开发并且需要持续多年的组件的分布式系统,那么REST是一个非常好的选择.
SOAP是一个面向对象的,远程过程调用的技术栈.它的工作原理是在现有协议(HTTP)之上构建新的抽象.
REST是一种面向文档的方法,它只使用现有协议(HTTP)的功能."REST"只是一个流行词 - 概念是这样的:只需按照设计的方式使用网络即可!
回答编辑问题:
"实现REST服务比实现SOAP服务花费的时间更长."
嗯,不,它不能无限长.如果您要检索的内容已经是文档或文件,那么它实际上要快得多.例如,WMS的OGC规范(Web制图服务)定义了协议的SOAP和REST版本,并且有几乎没有人实现SOAP版本的原因 - 这是因为如果你想要获得一个地图,它就是更容易构建一个URL并从该URL获取图像字节比将其封装到SOAP消息中更麻烦.但是,我同意,如果Web服务的重点是在域对象模型中传输一些强类型对象,那么SOAP更适合该用途.
"为什么要写一个返回XML的REST服务?"
嗯,是的,这可能很愚蠢.但这取决于XML是什么.如果在某个地方有明确定义的架构,那么就没有歧义.例如,您可以将WSDL URL视为一种用于检索有关Web服务的信息的RESTful Web服务.在这种情况下,添加另一个SOAP请求的开销将毫无意义.
通常,当正在传输的内容可以被视为一个文件时,REST会成为一个单元.当内容需要被视为具有成员的对象时,SOAP会获胜.
"我听说过使用SOAP,你有SOAP信封的"开销".在这个时代,我们真的需要担心一些字节吗?"
是.不是在所有情况下,但有一些网站有很大的流量,它会有所作为.是否足以超过使用SOAP而不是REST 的语义差异?我对此表示怀疑.如果你正在做一个对象远程协议并且字节数有所不同,那么SOAP可能不是你的工具 - 也许你应该使用CORBA或DCOM.
"我听说过用REST可以将URL弹出到浏览器中并查看数据."
是的,如果在浏览器中查看数据是有意义的,这是支持REST的一个大论据.例如,使用图像数据,这是调试服务的简单方法 - 只需将URL粘贴到浏览器的地址栏中,然后查看图像的外观.或者,如果返回的数据是XML格式,并且您有一个引用的XML样式表,可以在浏览器中呈现为可读的HTML,那么您可以在一个包中获得语义标记和简单可视化的好处.但是你是对的,当使用更复杂的身份验证方案时,这种好处大多会消失.如果您无法将所有身份验证信息编码到每个HTTP请求中,那么我认为它根本不算作REST.
"为什么我们需要为每个资源提供"可读"的URL?如果我们使用工具来实现服务,我们真的关心实际的URL吗?"
这得看情况.为什么我们需要Web上任何资源的可读URL?你可以阅读Tim Berners-Lee的文章Cool URIs Do not Change的基本原理,但基本上,只要资源在将来仍然有用,该资源的URI应该保持不变.
显然,对于瞬态资源(如文章中的"今天的钱"链接),没有必要,因为如果相应的资源消失,引用资源的需要就会消失.但是对于更持久的资源(例如,像StackOverflow问题,或IMDB上的电影),您希望拥有一个永远有效的URL.当您设计Web服务时,您需要确定资源本身是否可以比您的服务更长,如果是这样,那么REST可能是正确的方法.
对于记录,是的,我一直在开发网页,因为NetFlix或Twitter存在之前.不,我还没有任何需要或机会将客户端实施到NetFlix或Twitter的服务.但即使他们的服务非常难以使用,这并不意味着他们在其上实现服务的技术很糟糕 - 只是这两种实现都很糟糕.
简而言之:REST和SOAP 只是工具.他们每个人都有优点和缺点.如果你拥有的唯一工具是锤子,那么每个问题看起来都像钉子一样.因此,了解这两种工具,并学习如何正确使用它们,然后为每项工作选择合适的工具.
一个诚实的问题值得一个诚实的答案.但首先,如果你不认为它本质上是修辞的话,你为什么要用这个问题的文本作为另一个问题的答案呢?
无论如何:
" 所有现代语言/框架/平台都可以使用工具来读取WSDL并输出代理类和客户端.实现REST服务是通过阅读文档手动完成的. "
就像浏览器供应商上下阅读并重新阅读HTML 4.01规范一样,尝试实现一致的浏览体验.您是否已经反思过浏览器是在网上银行和堆栈溢出之前发明的,而且,您可以使用浏览器来完成这些事情.这是可能的,因为每个人都同意使用HTML(以及CSS,JS,JPEG等相关格式)的唯一原因.
博客实际上并不是那么新,有人想出了AtomPub,它允许任何博客软件访问和更新博客中的帖子,就像任何网络浏览器都可以访问任何网页一样.这非常简洁,并且由于协议强加的RESTful限制而起作用.
但对于Twitter和Netflix,没有普遍的协议,"所有存在的微博都应该使用媒体类型应用/推文",主要是因为微博是如此新颖.也许在几年之后,一些微博服务就会采用相同的API,以便Twitter,Facebook,Identica可以互操作.他们现有的API都不在RESTful附近,无论他们声称多少,所以我不认为它会很快发生.
" 此外,在实施这两项服务时,您必须对管道中的内容做出"猜测",因为没有真正的架构或参考文档. "
你已经击中了头部.REST完全是关于分布式和超媒体的,这几乎总结了它.浏览器查看从请求中获取的内容并将其显示给用户.HTML页面通常会产生更多的GET请求,例如CSS,脚本和图像.图像通常仅呈现给屏幕,执行JavaScript等等.每次,浏览器都会执行它所做的事情,因为它在一个或
标记中找到了链接,而响应媒体类型是
image/jpeg
或text/css
.
如果Twitter制作基于超媒体的API,那么application/tweet
每次你跟踪推文的链接时,它都可能总是返回,但是客户端永远不应该假设它,并且在对其进行操作之前总是检查它得到了什么.
" 为什么要写一个返回XML的REST服务? "
这一切都归结为媒体类型.与HTML一样,如果您看到一个您不知道实际含义的元素,HTML规范会指示您忽略它们,并处理标记的"正文"(如果有).同样,atom spec指示您忽略未知元素和外部标记(来自不同的名称空间)而不处理正文(IIRC).
为通用问题域设计媒体类型(如在富文本问题域的HTML媒体类型中)非常困难.为非常狭窄的问题域制作媒体类型可能要容易得多(如推文).但设计可扩展性并指定客户端(和服务器)在看到与规范不匹配的元素或数据项时应该如何反应总是一个好主意.例如,JPEG具有特定于应用程序的记录类型(例如APP1),其用于包含各种元数据.
" 我听说过使用SOAP,你有SOAP信封的"开销".在这个时代,我们真的需要担心一些字节吗? "
不,我们没有.REST绝对不是为了提高线路效率,它实际上是在交换线路效率.REST的效率来自于所有其他约束所启用的缓存的可能性: Fielding的论文说明:然而,权衡是统一的接口降级效率,因为信息是以标准化形式传递的,而不是特定于应用程序需求的形式.REST接口旨在高效地进行大粒度超媒体数据传输,针对Web的常见情况进行优化,但会导致界面不适合其他形式的架构交互. 我不认为SOAP Envelope字节计数开销是一个有效的问题.
" 我听说过用REST可以将URL弹出到浏览器中并查看数据. "
是的,这也是一个无效的论点.它不起作用.即使它确实有效,大多数狭窄的 REST API都使用浏览器不知道的媒体类型,但它仍然无法工作.
但是,浏览器测试基于HTTP的API的可能性要大得多,例如命令行实用程序或浏览器扩展,它们允许您控制HTTP请求的几乎任何方面,检查响应标头并发现您可以关注的链接.但即便如此,这远不如生成WSDL存根和制作三行程序来调用函数那么容易.
" 为什么我们需要为每个资源提供"可读"的URL?如果我们使用工具来实现服务,我们真的关心实际的URL吗? "
如果你看看网络是如何工作的,我很确定人类总是很高兴维基百科页面的URI看起来像这样,http://en.wikipedia.org/wiki/Stack_overflow
而不是http://en.wikipedia.org/wiki/?oldid=376349090
.但它实际上对REST来说并不重要.尝试正确的重要一点是选择将相关数据放在不太可能改变的URI中.您可能认为数据库ID永远不会改变,但是当需要合并两个数据集时会发生什么?您的所有主键都会更改.页面标题(Stack_overflow)不会更改.
对于长时间的回复感到抱歉,但我相信这个问题是有效的,并且在此之前没有得到解决.我相信Darrel Miller一旦回来也会加上他的答案.
编辑:格式化
Martin Fowler 在Richardson成熟度模型上发表了一篇文章,该文章很好地解释了SOAP和REST之间的区别.