正确的API方法可以延长处理时间

时间:2014-03-11 10:20:02

标签: http

我正在制作一个主要由数据库提供的HTTP Web API。简化后,db包含userobjects 这些对象有last_online(当用户在线时)和last_checked(我最后一次检查了userobject )。

检查userobject 可能需要3到30秒。当last_checked时间少于10分钟时,一切都没问题; API调用返回200和userobject。

但是当数据是staler超过10分钟时,我想重新处理userobject。显然我无法让我的API返回并等待。

HTTP API的正确方法是什么(有时)需要从长时间运行的流程返回数据?

2 个答案:

答案 0 :(得分:1)

一种相当“老派”的处理方法是返回一个延续令牌 - 基本上是一个工作ID,说“定期检查;迟早会带来结果。”鉴于即使在正常的“检查”情况下,即使30秒也是相当长的时间,您可能想要回馈延续令牌。

更现代的替代方案是网络套接字或悬挂式接收......这实际上取决于客户端的用例。

答案 1 :(得分:1)

我的第一个建议是让服务器每隔X分钟更新一次用户对象作为后台进程。我没有看到任何理由将服务器数据保持在客户端的最新状态。对GET电话的回复将包含Expires标头。然后,客户端可以将响应缓存一段固定的时间,从而节省服务器命中数,直到数据刷新为止。

如果您必须让刷新由客户端驱动,那么您希望GET返回202 Accepted,这表示API正在处理但尚未完成的有效请求。从GET请求返回的实体应提供API应何时检查以获取更新数据的时间戳。数据刷新后,GET将返回包含刷新数据的200 Ok。这是我推荐的方法。

GET /userObject
<- 202 Accepted
{ "checkAt": <timestamp> }

GET /userObject
<- 200 OK
{ "userName": "Bob", ... }

您还可以考虑在回复中使用Retry-After标头,但这仅适用于503 Service Unavailable或任何不同的3xx (Redirection)响应。你绝对没有描述503,听起来重定向也不正确。

如果您确实想要转到重定向路由,则返回302 Found,在Location标头中指定临时URI,在Retry-After标头中指定延迟时间

第四种方法是使用POSTPost-Redirect-Get模式。您可以POST到您的userObject URI并让它返回带有302 Found标头的Retry-After

我真的不认为选项三或四可以为你买任何第二种选择都没有的东西,我认为这是最清楚的。三表示当您的资源不存在时,您的资源当前位于不同的位置。四从基本上将GET请求(给我用户对象)转换为POST(刷新用户对象,但仅在需要时)。

如果您决定遵循@ JonSkeet的建议,您可能需要一个单独的资源,例如/userObjects/userObjectRequests。客户始终POST/userObjectRequests。如果userObject在后端有效,那么POST会将302返回到/userObjects。如果它不有效,POST将返回具有id和估计完成时间的实体。客户可以在GET上致电/userObjectRequests/{id},他们可以获得302到userObject(如果已准备好)或200 id和新的估计完成时间。