持久的RESTful交互

时间:2020-03-06 14:35:26  来源:igfitidea点击:

目前,我们的团队正在进行讨论,我会对其他观点感兴趣。假设我们有一个RESTful Web服务,其作用是通过应用各种分析算法和服务来注释文档。基本的交互作用很明确:我们拥有一个资源,即文档集合;客户将新文档发布到集合中,获取新文档的URI,然后可以获取该文档docURI以获取该文档,或者获取{docURI} /元数据以查看常规元数据{docURI} / ne`(用于命名实体等)。问题在于某些分析可能需要很长时间才能完成。假设客户端在分析完成之前获取元数据URI,因为它希望能够在UI中显示部分或者增量结果。将来重复执行GET可能会产生更多结果。

我们讨论的解决方案包括:

  • 保持HTTP连接打开,直到完成所有分析为止(这似乎不可扩展)
  • 使用" content-length"和" accept-range"标头来获取增量内容(但我们不知道最终内容将持续多长时间)
  • 为每个资源提供一个Atom提要,以便客户端订阅更新事件,而不是简单地获取资源(如果存在许多活动文档,似乎过于复杂,可能会浪费资源)
  • 只是让GET返回当时可用的任何内容(但仍然使客户不知道我们何时最终完成)(已编辑以在注释后删除对等幂的引用)。

对于在RESTful架构中处理长期或者异步交互的替代方法有任何意见或者建议吗?

伊恩

解决方案

我将通过以下方式实现它:

1)客户端请求元数据
2)服务器返回实际数据(如果已经可用)或者NotReady标记
3)客户端询问服务器何时有可用数据(此步骤可以与之前的步骤合并)
4)服务器返回时间间隔(可能对执行的作业总数有一些启发式方法,等等)
5)客户等待指定的时间,然后转到步骤1

这样,我们可以尽快向客户端提供数据。我们可以通过调整在第4步中返回的延迟间隔来调整服务器负载

providing an Atom feed for each resource so the client subscribes to update events rather than simply GETting the resource (seems overly complicated and possibly resource hungry if there are many active documents)

我们考虑过SUP吗?

如果可以选择轮询,为什么还要烦恼feed?为什么不让客户自己轮询资源本身呢?

我们是否可以通过包括完成分析所需的估计时间来减少不必要的轮询?

使用HTTP 202接受。

另外,请查看RESTful Web服务,这是我从上面学到的。

just ignoring idempotency and having GET return whatever is available at the time (but it still leaves the problem of the client knowing when we're finally done).

随时间返回不同结果的GET真的意味着它不是幂等的吗?规格说明:

Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request

也就是说,多次调用GET可能会返回不同的结果,只要调用本身没有副作用即可。

在这种情况下,也许REST方法可以使用条件GET和缓存机制来指示何时完成:

  • 没有ETag标头。
  • 一个ETag。随后带有" ETag"的请求应返回" 304 Not Modified"。

注意,我们可能需要考虑缓存中涉及的其他响应头,而不仅仅是Expires。

这种"感觉"就像REST风格的设计,我们可以想象Web浏览器在对该资源进行连续请求时做正确的事情。

"让GET返回当时可用的任何内容"很有道理。除非他们进行轮询,否则我们不想继续返回他们已经知道的东西。每次投票,答案就会变长。

我们需要他们在GET请求中为我们提供"到目前为止我所见"。这使我们具有幂等性。如果他们要求块1,他们总是得到相同的答案。一旦他们看到了块1,就可以要求块2.

答案并没有变得更大。更多作品可用。 "集合级" GET提供响应的大小。对于每个可用的零件,我们都有"详细级别"的GET。

本质上,这是一种类似于TCP / IP确认的算法。当他们确认一块时,我们将发送下一块。如果还有下一块,否则我们将发送200份新消息以进行报告。

"客户知道我们何时最终完成的问题"是难以理解的。他们不知道,我们无法预测需要多长时间。

我们不希望他们进行"繁忙等待"-轮询以查看是否已完成-这对服务器来说是一个很大的负担。如果他们不耐烦。我们可以限制他们的请求。我们可以向他们发送"以x秒为单位进行检查",其中x会逐渐变大。

我们甚至可以使用Unix样式的调度程序算法,当他们轮询时,其得分会降低,如果在X秒内未轮询,则得分会升高。

另一种选择是某种队列,我们可以在其中将结果发布回它们。
为此,他们必须提供一个URI,我们可以发布该URI来告诉他们我们已完成操作。

或者,他们将Atom用于轻量级的轮询体系结构。尽管Atom看起来很复杂-并且仍然涉及轮询-我们还是提供了一个最小的Atom答案("尚未更改"),直到完成为止,而当我们提供​​("新结果")时,它们就可以完成真正的重量级任务。这是全有或者全无,而不是上面的增量响应技术。

我们也可以将"集合级" GET视为整个过程中的Atom状态。

一种可能不适合情况的替代解决方案是添加一个称为" AnnotationRequests"的新端点。将文档(或者指向该文档的链接)发布到AnnotationRequests端点,它应返回一个位置(例如http://example.org/AnnotationRequest/2042),该位置将允许客户端轮询流程的状态。该过程完成后," AnnotationRequest"表示形式可以包含指向完整文档的链接。

一个不错的副作用是我们可以对AnnotationRequests进行GET操作,以便查看当前正在处理的文档。由我们决定要保留AnnotationRequests多长时间。保持完整的历史记录,可能是很有价值的,这些历史记录是何时请求它们,由谁花费的时间以及花费多长时间,或者可以将它们定期丢弃。

我们可能想查看Udi Dahan的nServiceBus。