如果我们不遵循RESTful最佳做法会出现什么问题?

时间:2016-12-30 15:42:17

标签: rest api http caching proxy

TL; DR:向下滚动到最后一段。

在定义RESTful API时,有很多关于最佳实践的讨论:支持哪些HTTP方法,在每种情况下使用哪种HTTP方法,返回哪个HTTP状态代码,何时在查询字符串中传递参数?路径与内容体相对于标题,如何进行版本控制,结果集限制,分页等。

如果您已经决定使用最佳实践,那么有很多问题和答案可以解释做任何特定事情的最佳实践。不幸的是,对于 为什么 首先使用最佳做法似乎毫无疑问(也没有回答)。

大多数最佳实践指南都指导开发人员遵循最小意外的原则,在正常情况下,这将是遵循它们的充分理由。不幸的是,REST-over-HTTP是一个反复无常的标准,如果没有与之密切相关,最好的实践是不可能实现的,而且亲密参与的缺点是你最终会将你的应用程序紧紧地绑定到特殊的运输机制。因此,有些人(像我一样)正在争论“最少惊喜”的好处是否证明了使用REST-over-HTTP问题乱丢应用程序的缺点。

作为最佳实践的替代方法,检查了一种不同的方法,这表明我们对HTTP的参与应该限制在最低限度,以便从A点到B点获得应用程序定义的有效负载。根据这种方法,您只能在整个应用程序中使用单个REST入口点URL,您永远不会使用除HTTP POST之外的任何HTTP方法,永远不会返回除HTTP 200之外的任何HTTP状态代码,并且永远不会以特定于应用程序的方式之外的任何方式传递任何参数请求的有效负载。请求将无法传递,在这种情况下,Web服务器有责任向客户端返回“未找到HTTP 404”,或者它将成功传递,在这种情况下,请求的传递是“ HTTP 200 OK“就传输协议而言,从那一点开始可能出错的任何其他内容完全是应用程序问题,而不是传输协议的业务。显然,这种方法有点像说“让我告诉你在哪里坚持你的最佳实践”。

现在,还有其他声音说事情并不那么简单,如果你不遵循RESTful最佳实践,事情就会破裂。

故事说明,例如,在未经授权的情况下,您应该返回一个实际的“HTTP 401 Unauthorized”(而不是包含json序列化的UnauthorizedException的成功响应),因为收到401后,浏览器会提示凭证的用户。当然,这实际上并不存在任何用水,因为REST请求不是由人类用户使用的浏览器发出的。

故事的另一个更复杂的方式是,通常,客户端和服务器之间存在代理,这些代理检查HTTP请求和响应,并试图理解它们,以便以不同方式处理不同的请求。例如,他们说,在客户端和服务器之间的某处可能存在一个缓存代理,它可以将对完全相同的URL的所有请求视为相同的,因此可以缓存。因此,路径参数是区分不同资源所必需的,否则高速缓存代理可能只将请求转发一次到服务器,然后将缓存响应返回给所有客户端。此外,该高速缓存代理可能需要知道某个请求 - 响应交换导致由于诸如“权限被拒绝”的特定错误而导致的失败,以便再次不缓存响应,否则导致临时错误的请求可能永远回答缓存错误响应。

所以,我的问题是:

除了“熟悉度”和“最少惊喜”之外,还有其他很好的理由来遵循REST最佳实践吗?这些对代理的担忧是否真实?缓存代理是否真的如此愚蠢以至于缓存REST响应?是否很难将代理配置为以不那么愚蠢的方式运行?配置代理以不那么愚蠢的方式存在缺点吗?

2 个答案:

答案 0 :(得分:1)

值得考虑的是,您所建议的是HTTP API过去15年左右的设计方式。如今,API设计师倾向于摆脱这种方法。他们确实有他们的理由。

如果您想避免使用Rest over HTTP,需要考虑以下几点:

  • 通过HTTP Rest是对HTTP / S传输机制的有效使用。避免使用ReST范例会冒每个请求/响应都包含在详细信封中的风险。 SOAP就是一个例子。

  • ReST鼓励客户端和服务器解耦,方法是将应用程序语义放入标准机制 - HTTP和XML / JSON(或其他数据格式)。标准库很好地支持这些协议和标准,并且已经建立了多年的经验。当然,您可以使用200状态代码创建您自己的“未授权”响应正文,但是ReST框架只是让它变得不必要,为什么还要麻烦?

  • ReST是一种设计方法,它鼓励您的分布式系统视图,该系统侧重于数据而非功能,这已被证明是构建分布式系统的有用机制。避免ReST存在着重于类似RPC的机制的风险,这些机制本身就存在一些风险:

    • 他们可以变得非常细粒度和'健谈'
    • 这可能是网络带宽的低效使用
    • 可以通过引入请求之间的状态和时间耦合来紧密耦合客户端和服务器。
    • 并且难以水平缩放 注意:有时RPC方法实际上是分解系统的一种比面向资源的方法更好的方法,但它们往往是例外而不是规则。
  • 现有的开发人员工具可以更轻松地调试/调查ReSTful API。例如,使用浏览器轻松进行简单的GET。 Postman或RestClient等工具已经存在,可用于更复杂的ReST样式查询。在极端情况下,tcpdump非常有用,浏览器调试工具(如firebug)也是如此。如果每个API调用都具有基于HTTP构建的应用程序层语义(例如,针对特定错误情况的特殊响应类型),那么您将立即从某些工具中丢失一些值。在PostMan中构建SOAP信封是一件痛苦的事。正如阅读SOAP响应信封一样。

  • 围绕缓存的网络基础设施真的可以像你问的那样愚蠢。可以解决这个问题,但你确实需要考虑它,并且在某些不必要的情况下,它将不可避免地涉及增加的网络流量。缓存重复查询的响应是API向外扩展的一种方式,因此您可能需要自己“解决”问题(即重新发明轮子)如何缓存重复的查询。

说了这么多,如果你想研究分布式系统的纯消息传递设计而不是ReSTful设计,为什么要考虑HTTP呢?为什么不简单地使用一些面向消息的中间件(例如RabbitMQ)来构建您的应用程序,可能在某些地方为基于Internet的客户端提供某种HTTP桥接?使用HTTP作为纯传输机制,涉及简单的“消息接受/不接受”语义似乎有点过分。

答案 1 :(得分:1)

REST适用于跨多个组织的基于网络的长期应用程序。如果您不认为需要约束,则不要使用它们。 - Roy T Fielding

  

不幸的是,对于为什么首先使用最佳实践似乎毫无疑问(也没有回答)。

如有疑问,请返回来源

Fielding's dissertation在解释REST架构约束如何确保您不会破坏这些约束旨在保护的属性方面确实做得非常出色。

请记住 - 在网络(这是REST的参考应用程序)之前," web scale"不是一件事;以前没有实现过能够发现和使用数千个自定义应用程序(由Web服务器提供)的通用客户端(浏览器)的概念。

  

根据这种方法,您只在整个应用程序中使用单个REST入口点URL,从不使用除HTTP POST之外的任何HTTP方法,永远不会返回除HTTP 200之外的任何HTTP状态代码,并且永远不会传递任何参数除了请求的特定于应用程序的有效负载之外的任何方式。

是的 - 这是一件事,它被称为RPC;您正在有效地使用Web,并将其剥离到刚刚通过端口80进行隧道传输的裸邮件传输应用程序。

这样做,你已经删除了统一界面 - 你已经失去了在部署中使用商品部件的能力,因为没有人可以参与对话,除非他们对消息数据有相同的解释。

注意:这并不意味着RPC已被打破&#34 ;;架构是关于权衡。 RPC方法放弃了从REST保护的属性中获得的一些值,但这并不意味着它不会在其他地方获取值。课程的马。

  

除了"熟悉"并且"最少惊喜",还有其他很好的理由来遵循REST最佳实践吗?

读取的便宜扩展 - 随着您的产品变得越来越流行,您可以通过安装商品反向代理服务器来为更多客户端提供服务,这些代理服务器将提供可用的缓存表示,并且只有在没有可用的新表示时才将负载放在服务器上

预取 - 如果您遵守界面的安全规定,代理商(和中间人)知道他们可以自行决定下载表示,而无需担心运营商将对资金损失负责。 AKA - 您的资源可以被抓取(和缓存)

类似地,使用幂等方法(在适当的情况下)与代理(和中介)通信,重试发送未确认的消息不会造成任何伤害(例如,在网络中断的情况下)。

客户和服务器的自主创新,尤其是跨组织。马赛克是博物馆的一部分,Netscape很久以前就消失了,但网络仍然很强大。

  

当然,这并不能保留任何用水,因为人类用户使用的浏览器不会发出REST请求。

当然他们是 - 你认为你在哪里读到这个答案?

到目前为止,REST在向人工代理公开功能方面表现得非常好;也就是说服务器端在这一点上无处不在,以至于我们几乎不再考虑它了。您 - 操作人员 - 可以使用相同的应用程序来订购披萨,在您的房子上运行诊断,以及远程启动汽车这一概念与空气一样正常。

但你完全正确地取代人类似乎还有很长的路要走;有多种标准和媒体类型可用于传递数据的语义内容 - 自动化客户端可以查看标记,识别电话号码元素,并从中提供自定义的菜单选项 - 但是可以构建代理模式智能需要将提供的功能与目标保持一致,或者从错误状态中恢复,似乎还有很长的路要走。