长期的RESTful交互

时间:2008-09-23 10:01:47

标签: design-patterns architecture rest

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

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

  • 保持HTTP连接打开 直到所有分析完成(哪个 似乎没有可扩展性)
  • 使用 {docURI}/necontent-length 标题来获取增量内容(但是 我们事先不知道多久 最终内容将是)
  • 提供 每个资源的Atom提要 客户订阅更新 事件而不仅仅是GETting 资源(似乎过度 如果有很多有效的文件,那就很复杂,可能还有资源。)
  • 刚刚获得GET回归 什么是当时可用的(但它仍然 留下了客户的问题 知道什么时候我们最终完成了) [编辑以删除评论后的幂等性参考]

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

伊恩

7 个答案:

答案 0 :(得分:3)

我会用以下方式实现它:

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

这样您就可以尽快向客户提供数据。您可以通过调整在步骤4)返回的延迟间隔来调整服务器负载

答案 1 :(得分:3)

  

为每个资源提供一个Atom提要,以便客户端订阅更新事件而不是简单地获取资源(如果有许多活动文档,似乎过于复杂并且可能资源很耗尽)

您考虑过SUP吗?

如果轮询是一种选择,为什么还要费心?为什么不让客户端轮询资源本身?

你能否通过计算完成分析的预计时间来减少不必要的民意调查?

答案 2 :(得分:2)

使用HTTP 202 Accepted

另外,请查看RESTful Web Services - 这是我了解上述内容的地方。

答案 3 :(得分:2)

  
      
  • 只是忽略幂等性并让GET返回当时可用的东西(但它仍然留下了客户知道我们什么时候最终完成的问题)。
  •   

随着时间的推移,返回不同结果的GET是否真的意味着它不是幂等的? The spec说:

  

方法也可以具有“幂等性”的特性(除了错误或期满问题之外)N的副作用> 0个相同的请求与单个请求相同

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

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

  • 在进行分析时,GET {docURI}/metadata响应可能会:
    • 将来Expires标头设置为几秒钟。
    • 没有ETag标题。
  • 完成分析后,该资源的响应包括:
    • 没有Expires标题。
    • ETag。使用ETag的后续请求应返回304 Not Modified

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

这种“感觉”就像一个RESTful设计 - 你可以想象一个网页浏览器做正确的事情,因为它连续请求这个资源。

答案 4 :(得分:1)

“只是让GET返回当时可用的任何东西”,这很有意义。除了在他们进行投票时,你不想继续他们已经知道的东西。每次轮询时答案都会变长。

你需要他们在GET请求中为你提供他们“迄今为止所看到的”。这为您提供了幂等性。如果他们要求大块1,他们总能得到相同的答案。一旦他们看到大块1,他们就可以要求大块2。

答案并没有变得更大。更多件可用。 “集合级”GET提供响应的大小。您可以获得每件可用的“详细级别”GET。

基本上,这是一种类似于TCP / IP确认的算法。当他们说一件时,你发送下一件。如果有下一篇文章,否则你发送一个200-nothing new报告。

客户知道我们何时终于完成的问题是无法估量的。他们无法知道,你无法预测需要多长时间。

你不希望他们“忙着等待” - 轮询看你是否已经完成 - 这对你的服务器来说是一个相当大的负担。如果他们不耐烦。你可以限制他们的请求。您可以向他们发送“在x秒内检查”,其中x逐渐变大。

你甚至可以使用Unix风格的调度算法,当他们轮询时他们的分数下降,如果他们不轮询X秒,他们的分数就会下降。

替代方案是某种队列,您可以将结果发回给他们。 要做到这一点,他们必须提供一个你可以POST的URI告诉他们你已经完成了。

或者,他们使用Atom来实现轻量级轮询架构。虽然Atom看起来很复杂 - 它仍然涉及轮询 - 你提供了一个最小的Atom答案(“还没有改变”)直到你完成,当你提供(“新结果”)所以他们可以做真实重量级得到。这是全有或全无的,而不是上面的增量响应技术。

您也可以将“集合级别”GET视为整个流程的Atom状态。

答案 5 :(得分:1)

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

这样做的一个不错的副作用是您可以对AnnotationRequests执行GET,因此请查看当前正在处理的文档。由您决定要保留AnnotationRequests的时间。保留完整的历史记录可能是有价值的,这些历史记录了它们被请求的时间,每个人服用的时间和持续时间,或者可以定期将它们丢弃。

答案 6 :(得分:1)

您可以查看Udi Dahan's nServiceBus