煤矿中的金丝雀
我等了近一年时间才等到这样的问题。这一天注定会到来,我相信在未来几个月里我们将看到更多类似的问题。
预警信号
你说得对,构建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是一个不错的选择。