如何处理超时POST请求

时间:2012-11-09 21:34:10

标签: rest timeout http-post soa

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

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

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

1 个答案:

答案 0 :(得分:11)

我听过很多方法试图解决这个问题

  1. 获取当前状态。

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

    这种方法的问题是在POST在集合中创建新项目的情况下,客户可能难以确定帖子是否成功(即,我的帖子是否添加了该项目或做了某人更多的东西?)

  2. 如果-匹配

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

    这种方法的问题是当你得到412 Precondition Failed时,你无法确定你的POST是否修改了该集合或其他人的。

  3. POST然后PUT

    将您的服务设计为永不保留POST中的数据。而是POST创建一个具有POST内容的临时资源,该内容处于“待处理”状态。然后,使用PUT“提交”此临时资源。使用这种方法你不关心你的POST时间是否结束,只是再次请求POST,这次你希望得到你的临时资源。如果PUT提交资源时间,你也不关心,因为PUT是幂等的。

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

    <强>更新

  4. 现时标志

    在请求中使用随机数(a.k.a消息ID,交易ID,请求ID,关联ID)是解决此问题的常用方法;但它可能存在可扩展性问题。 如果您承诺拒绝使用先前nonce的所有POST,则需要扫描现有的POST记录以确定之前是否已使用过nonce。当你只有几千个POST时没有问题,但是当你有数百万的时候它会成为问题(特别是如果你没有以一种快速查询的方式存储nonce)。

    您可以通过减少拒绝在特定时间范围内(例如,过去24小时)使用之前的nonce的所有POST的承诺来缓解此问题,但如果第一个POST超时并且客户端在该时间范围内断开连接,则它们是回到同一个旧位置,他们不知道第一次POST是否成功,无法确定是否应该重新发布。