【问题标题】:How to deal with timed out POST requests如何处理超时的 POST 请求
【发布时间】:2012-10-30 06:17:09
【问题描述】:

在 RESTful SOA 中,假设我通过 AJAX 发出 POST 请求,但在请求超时之前我没有得到响应。进一步假设重新提交请求将是有害的。 POST 不是幂等的。例如,也许我正在发布银行转账。如果我没有得到响应,我不知道服务器是否处理了请求。

假设我可以控制客户端和服务端,那么处理这个问题的最佳做法是什么?

我最初的想法是在每个 POST 请求中包含一个随机数(即伪 ID;某种唯一标识符);例如可能是 If-None-Match 标头中的一个值。使用这种方法,客户端可以以编程方式重新发出具有相同伪 id 的超时请求,如果它包含重复值,服务器可以拒绝它。

【问题讨论】:

  • 如果您在某个超时后没有得到响应,则假设它失败并要求客户端重试或中止。显然,服务器上的代码无论如何都应该检查相同的 id。
  • 需要明确的是,这个伪 id 并不意味着是 the 资源 id——我不是直接寻址资源。我按预期使用 POST;即,发布到资源处理程序(例如 /Transfers,而不是 /Transfers/)。否则,我一开始就不会做 POST。
  • 这是一个与“Avoid duplicate POSTs with REST”类似的问题。

标签: rest timeout http-post soa


【解决方案1】:

我听说有很多方法可以尝试解决这个问题

  1. 获取当前状态。

    设计服务,如果 POST 失败,客户端可以在同一资源上发出 GET,并根据返回的数据确定 POST 是否成功。

    这种方法的问题在于,如果 POST 在集合中创建了一个新项目,客户端可能很难确定该帖子是否成功(即,我的帖子是否添加了该项目或有人别人的?)

  2. 如果匹配

    使用 If-Match 标头来防止重复 POST。例如,如果 POST 正在向集合添加项目,并且集合当前具有 ETag737060cd8c284d8af7ad3082f209582d。如果在 POST 上使用了 737060cd8c284d8af7ad3082f209582dIf-Match ,那么只有当集合的 ETag 仍然是 737060cd8c284d8af7ad3082f209582d 时,POST 才会成功,这将添加项目并为集合生成一个新的 ETag。在这个阶段重复 POST 只会返回 412 Precondition Failed

    这种方法的问题在于,当您收到 412 Precondition Failed 时,您无法确定您的 POST 修改了集合还是其他人的集合。

  3. POST 然后 PUT

    将您的服务设计为从不保留 POST 中的数据。相反,POST 会使用 POST 内容创建一个临时资源,该资源处于“待处理”状态。然后使用 PUT “提交”此临时资源。使用这种方法,您不必关心您的 POST 时间是否已过,只需再次请求 POST,这一次您有望获得临时资源。如果 PUT 提交资源的时间到了,你也不在乎,因为 PUT 是幂等的。

    这种方法唯一真正的缺点是管理临时资源所需的额外工作以及客户端所需的额外工作。

    更新

  4. 随机数

    在请求中使用 nonce(又名 Message ID、Transaction ID、Request ID、Correlation ID)是解决此问题的常用方法;但是它可能存在可扩展性问题。 如果您承诺拒绝所有使用先前 nonce 的 POST,则需要扫描现有的 POST 记录以确定之前是否使用过 nonce。当您只有几千个 POST 时这不是问题,但当您拥有数百万个 POST 时可能会出现问题(尤其是如果您没有以快速查询的方式存储随机数)。

    您可以通过减少在特定时间范围内(例如,过去 24 小时)拒绝所有使用先前随机数的 POST 的承诺来缓解这种情况,但如果第一个 POST 超时并且客户端在该时间范围内断开连接,那么它们是回到原来的位置,他们不知道第一次 POST 是否成功,也无法确定是否应该重新 POST。

【讨论】:

  • 我提议的方式怎么样?你觉得可行吗?
  • +1。我个人更喜欢第三种选择;先创建资源,然后使用 PUT :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多