【问题标题】:Approach for REST request with long execution time?执行时间长的 REST 请求的方法?
【发布时间】:2010-12-10 06:04:43
【问题描述】:

我们正在构建一个大约需要 5 分钟才能执行的 REST 服务。内部应用程序每天只会调用几次。使用需要 5 分钟才能完成的 REST(即:HTTP)请求是否存在问题?

我们需要担心超时吗?我们是否应该在服务器上的单独线程中启动请求并让客户端轮询状态?

【问题讨论】:

    标签: web-services rest asynchronous


    【解决方案1】:

    这是一种方法。

    创建一个新的请求来执行 ProcessXYZ

    POST /ProcessXYZRequests
    
    201-Created
    Location: /ProcessXYZRequest/987
    

    如果要查看请求的当前状态:

    GET /ProcessXYZRequest/987
    
    <ProcessXYZRequest Id="987">
      <Status>In progress</Status>
      <Cancel method="DELETE" href="/ProcessXYZRequest/987"/>
    </ProcessXYZRequest>
    

    请求完成后,您会看到类似

    GET /ProcessXYZRequest/987
    
    <ProcessXYZRequest>
      <Status>Completed</Status>
      <Results href="/ProcessXYZRequest/Results"/>
    </ProcessXYZRequest>
    

    使用这种方法,您可以轻松想象以下请求会给出什么

    GET  /ProcessXYZRequests/Pending
    GET  /ProcessXYZRequests/Completed
    GET  /ProcessXYZRequests/Failed
    GET  /ProcessXYZRequests/Today
    

    【讨论】:

      【解决方案2】:

      假设您可以使用您选择的任何框架配置 HTTP 超时,那么您可以通过 GET 请求并挂起 5 分钟。

      但是,通过 POST 启动执行,获取收据(数字/ID 等),然后在 5 分钟后使用 GET 执行 GET 可能会更灵活(并且可能重试,因为您的过程不会花费每次正好 5 分钟)。如果请求仍在进行中,则返回适当的 HTTP 错误代码(可能是 404,但是对于不存在收据的 GET,您会返回什么?),或者返回结果(如果有)。

      【讨论】:

      • 这不是有状态的(在服务器上),有状态的行为不符合 REST 理想吗?
      • @Merlyn Morgan-Graham:“反对 REST 理想”的不是状态性,而是隐藏状态。由于状态可作为给定 URL 的资源使用,这很好。
      【解决方案3】:

      正如 Brian Agnew 指出的那样,如果可以控制超时设置,5 分钟是完全可以管理的,如果有点浪费资源的话。否则,必须至少提出两个请求:第一个请求让结果生成过程滚动,第二个请求(以及第三个、第四个,etc.,如果结果的编译时间比预期的要长)轮询结果。

      Brian Agnew 和 Darrel Miller 都为两 (+) 步方法提出了类似的方法:向工厂端点发布请求,在服务器上启动作业,然后从返回的结果端点获取结果。

      虽然上面是一个非常常见的解决方案,并且确实遵守 REST 约束的文字,但它闻起来很像 RPC。也就是说,它不是说“为我提供此资源的表示”,而是说“运行此作业”(RPC),然后“为我提供该资源的表示”。运行作业的结果资源”(REST)。 编辑:我在这里说得很松散。需要明确的是,这些都没有明确违反 REST 约束,但它确实非常类似于将非 RESTful 方法披在 REST 的外衣上,失去了它的好处(例如 缓存,幂等性)在进程中。

      因此,我宁愿建议当客户端第一次尝试获取资源时,服务器应该以 202“已接受”(http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.3)响应,也许在响应实体中的某处使用“5 分钟后再试” .此后,客户端可以轮询同一端点以获取结果(如果可用)(否则返回另一个 202,稍后再试)。

      这种方法的一些额外好处是不会不必要地创建一次性资源(例如作业),不需要查询两个单独的端点(工厂和结果),同样不需要通过解析来确定第二个端点从第一个响应,因此更简单。此外,可以“免费”(按代码)缓存结果。根据结果​​“有效”的时间长度在结果标头中设置缓存过期时间,在某种意义上,对于您的问题域。

      我希望我可以将其称为“面向资源”方法的教科书示例,但具有讽刺意味的是,“RESTful Web 服务”的第 8 章提出了双端点工厂方法。去图吧。

      【讨论】:

      • 这很有趣,再次感谢分享。我可能需要更多地考虑它,但在我的脑海中,我看到单端点方法的一个缺点是必须定义一个固定时间的缓存持续时间,这意味着“重试”缓存过期之前的整个操作不会导致真正的重试。在某些用例中,这可能会使用户感到困惑
      【解决方案4】:

      如果你控制两端,那么你可以为所欲为。例如。浏览器倾向于使用“连接关闭”标头启动 HTTP 请求,因此您的选择更少;-)

      请记住,如果您之间有一些 NAT/防火墙,如果它们在一段时间内处于非活动状态,您可能会有一些断开连接。

      我可以建议注册一个“回调”程序吗?客户端向服务器发出带有“回调端点”的请求,获得“票证”。一旦服务器完成,它会“回调”客户端......或者客户端可以通过票证标识符检查请求的状态。

      【讨论】:

        猜你喜欢
        • 2013-09-27
        • 1970-01-01
        • 2019-05-07
        • 2020-07-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-16
        相关资源
        最近更新 更多