如何在REST中处理异步操作

时间:2013-04-25 12:04:51

标签: java http rest asynchronous

我需要了解在REST中处理异步操作的方法以及它们的优点和缺点。我发现了一些方法:

  1. 基于资源:将操作状态建模为状态。用户进行异步REST调用(PUT,POST等)获取AcceptedIn-Progress响应(202)。此外,通过GET重复轮询状态URI,以检查来自操作执行的状态/进度/消息。

    问题:此资源在服务器上应该有多长时间处于活动状态?如果客户端在操作完成之间的大间隔轮询中,我们如何返回状态?似乎坚持执行状态会起作用。但是,存档/删除的时间有多长,这种标准方法是什么?

  2. 基于回调:需要异步请求才能拥有回调URI。异步处理请求,完成后调用带有操作状态/结果的回调URI。

    问题:这似乎更优雅,服务器端的开销更少。但是如何处理回调服务器间歇性关闭,没有响应等情况?实现回调URI提供重试配置的典型重试?这种方法还有其他缺点吗?

  3. Servlet 3.0异步支持: HTTP客户端与Java Servlet建立连接的位置,该Java Servlet在显式关闭之前保持打开状态,直到关闭的客户端和服务器可以通过它进行异步通信。

    问题:自从它的Servlet 3.0规范以来,我认为Jersey,即Spring REST实现,目前尚未采用这种方法。是否有任何特定的REST实现,它使用类似的方法或指针来实现这一点?

  4. 任何其他方法,也许是商业方法?

4 个答案:

答案 0 :(得分:6)

Spring 3.2+支持Servlet 3.0的异步功能。来自Spring Blog

  

您可以通过将任何现有控制器方法更改为返回Callable来使其异步。例如,返回视图名称的控制器方法可以返回Callable。返回名为Person的对象的@ResponseBody可以返回Callable。对于任何其他控制器返回值类型也是如此。

Jersey 2+还支持异步服务器。请参阅参考文档中的Asynchronous Services and Clients章节。

答案 1 :(得分:3)

我认为,这种方法取决于初始请求和操作结束之间的时间差。

  • 对于短时间操作(< 10s),我会保持请求打开并在操作完成时返回响应;
  • 对于长时间操作(< 30m),我会使用servlet 3.0或Comet模型;
  • 对于极长的操作(小时,天)来说,对我来说,只是基于客户的轮询或具有大量超时的Comet。

答案 2 :(得分:0)

我正在处理相同的情况,并找到了使用Location标头响应来提供可监控的资源以检查状态(通过轮询当然)的常用方法。这似乎是最好的,但在我的情况下,我没有创建资源,所以我没有位置来检查状态(我的异步过程只是构建一个缓存页面)。

您始终可以使用自己的标题来估算完成操作的时间。无论如何,我正在考虑使用Retry-After标题来估计时间。你们觉得怎么样?

答案 3 :(得分:0)

我知道这已经过时了,但我想我会在这里说,如果你想要的是可以在无状态环境中扩展的东西,那么你应该选择第一个选项。您可以在任何地方执行基础操作,如果您将结果放在像redis这样的内容中,则客户端进行后续轮询请求的Web服务器无关紧要。我通常会将轮询间隔放在我发送给客户端的响应中。当结果准备就绪时,我将向客户端返回一个SEE OTHER,其中包含URI中结果的id。