什么是监视 REST 资源以进行更改的 RESTful 方式?

Posted

技术标签:

【中文标题】什么是监视 REST 资源以进行更改的 RESTful 方式?【英文标题】:What is a RESTful way of monitoring a REST resource for changes? 【发布时间】:2010-09-29 04:32:33 【问题描述】:

如果有一个 REST 资源我想监控来自其他客户端的更改或修改,那么最好(也是最 RESTful)的方式是什么?

我这样做的一个想法是通过提供特定资源来保持连接打开,而不是在资源不(尚)存在时立即返回。例如,给定资源:

/game/17/playerToMove

对该资源的“GET”可能会告诉我轮到我的对手移动了。与其不断轮询该资源以找出轮到我移动的时间,不如记下移动编号(例如 5)并尝试检索下一步:

/game/17/move/5

在“正常”的 REST 模型中,对此 URL 的 GET 请求似乎会返回 404(未找到)错误。但是,如果相反,服务器保持连接打开,直到我的对手下棋,即:

PUT /game/17/move/5

然后服务器可以返回我的对手放入该资源的内容。这既可以为我提供我需要的数据,也可以在不需要轮询的情况下通知我的对手何时移动。

这种方案是 RESTful 的吗?还是违反了某种 REST 原则?

【问题讨论】:

“Scrappy,rest 方法是什么?” 您可以使用长轮询,或者将 REST 与 websocket 服务结合,将事件发送到客户端。 【参考方案1】:

您提出的解决方案听起来像long polling,它可以很好地工作。

您将请求/game/17/move/5 并且服务器不会发送任何数据,直到移动 5 完成。如果连接断开,或者您遇到超时,您只需重新连接,直到获得有效响应。

这样做的好处是非常快——只要服务器有新数据,客户端就会得到它。它对断开的连接也有弹性,并且在客户端断开连接一段时间后仍然有效(您可以在移动后一小时请求 /game/17/move/5 并立即获取数据,然后转到 move/6/ 等等)

长轮询的问题是每个“轮询”都会占用一个服务器线程,这会很快破坏像 Apache 这样的服务器(因为它耗尽了工作线程,因此无法接受其他请求)。你需要一个专门的网络服务器来处理长轮询请求。Python 模块 twisted(一个“事件驱动的网络引擎”)非常适合这个,但它比常规轮询工作更多。

在回答您关于 Jetty/Tomcat 的评论时,我对 Java 没有任何经验,但似乎它们都使用与 Apache 类似的工作线程池系统,所以它会有同样的问题。我确实找到了this post,它似乎正好解决了这个问题(对于 Tomcat)

【讨论】:

我使用 Jetty 作为 Java servlet 容器。它似乎适用于“长轮询”。它是否有与 Apache 相同的问题(即,工作线程不足)? Tomcat 呢? 为避免占用线程,您可以使用 asp.net 异步 HTTP 处理程序。这会将线程返回到线程池。【参考方案2】:

我发现this article 提出了一个新的 HTTP 标头“When-Modified-After”,它本质上做了同样的事情——服务器等待并保持连接打开,直到资源被修改。

我更喜欢基于版本的方法而不是基于时间戳的方法,因为它不太容易出现竞争条件,并且可以为您提供更多关于您正在检索的内容的信息。对这种方法有什么想法吗?

【讨论】:

基于版本的方法将使用 ETag HTTP 标头。 en.wikipedia.org/wiki/HTTP_ETag【参考方案3】:

如果您的目标客户端是网络浏览器,我建议使用 404,因为保持连接打开可以主动阻止客户端中的浏览器请求到同一域。多久轮询一次取决于客户。


2021 年编辑:上面的答案是在 2009 年,以供参考。

今天,我建议使用带有推送通知的 WebSocket 接口。

或者,在上述建议中,我可能会建议将连接保持 500-1000 毫秒,并在返回 404 之前在服务器上检查两次,以减少在客户端创建多个连接的开销。

【讨论】:

这是对错误的一种误用(您如何检测到实际的 404,因为您请求 /game/x14 而不是 /game/14).. 返回 'error':'no new content' 或者问题会少一些.. 不,因为在执行第 14 步之前,资源不存在……它是正确的 404。 我建议改为响应 503,如果预期的用例是它会在未来出现。按照规范,以后不应自动重试 404。 @MikkoRantalainen 这不是 503,“服务”是网络服务器,503 通常是反向代理到其后面的资源关闭或数据库服务器关闭等的错误代码... 404 是一个不存在的资源,这就是它。如果步骤 14 从未发生,则它永远不会存在。 404 表示资源不存在,并不意味着资源永远不存在。 我同意 404 似乎更好,因为它在逻辑上是“未找到”。但是,根据 HTTP 规范,不能自动重试 404(4xx 系列有通用定义“客户端不应该在没有修改的情况下重复请求。”)。当然,如果你有自定义服务和自定义客户端,你可以随意改变规则。我想一种选择是响应 404 + Expires: <suitable time in future> 表示该资源现在不存在,但可能在到期后存在。不过,我认为对此的确切解释尚未完全定义。

以上是关于什么是监视 REST 资源以进行更改的 RESTful 方式?的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS 监视对象数组以进行数据更改

保存整个集合的最佳实践?

监视或记录目录权限更改?

如何修复 react-scripts 启动时的“错误监视文件以进行更改:ECONNRESET”错误?

如何唯一标识您的 Android 应用程序以获取 REST API

REST与RESTful学习