1

在 RESTful 架构中,POST 请求既不是Safe也不是Idempotent

现在,jQuery 的 ajax 调用允许重试失败的请求,方法是设置 ajax 调用以使用该函数来捕获失败,并可选择重试调用(以及相关设置,error例如timeout、和)。tryCountretryAfterretryLimit

重试 GET 调用不是问题(因为它们既安全幂等),但是应该如何重试 POST 调用呢?

例如,假设我们使用 ajax POST 插入一条新记录:

  1. 在客户端上启动 ajax POST 调用。
  2. 服务器接收到调用,并更新数据库。
  3. 服务器响应,但此响应未能传递给客户端。
  4. 所以客户端假设有一个失败,并重试调用。
  5. 服务器再次接收到该调用,这又进行了一次更改。
  6. 等等...

满足这种情况的最佳方法是什么?

4

1 回答 1

2

您的代码可以轻松的唯一方法(请原谅双关语),是确认数据已被接收和接受。

所以答案实际上取决于 POST 的性质。如果 POST 确实是更新,例如将名称设置为“John”,那么您可以安全地重试几次,直到得到确认。

但是,您正在谈论的情况是 POST 确实是 REST 意义上的 POST,这通常意味着它将添加一个新行。在这种情况下,正确的做法取决于客户端和服务器之间更深层次的握手。

最后,数据完整性是处理数据库的代码的工作,服务器代码也是如此。因此,如果不应该重复行,那么场景将如下进行:

  • 客户端为“提交令牌”生成 GET,包括客户端生成的 ID。
  • 服务端根据clientID生成提交token,存入表中
  • 服务器将令牌发送给客户端
  • 客户端提交包含令牌的 POST。
  • 服务器收到token,验证,插入post,响应成功

    1. 因此,如果 GET 令牌请求没有发送到服务器,客户端可以再次请求,始终使用相同的 clientID。
    2. 如果客户端最终取回一个令牌,他可以假设服务器有他的请求的记录,并期待后续的 POST。
    3. 如果客户端在几次失败后最终收到多个令牌响应,它们都将是同一个令牌。
    4. 因此,客户端将发布,并继续发布(使用令牌),直到他收到成功
    5. 如果服务器收到其中一个帖子,它将插入数据并使令牌无效并响应成功。
    6. 如果服务器收到请求并且已经使用了令牌,它会以“重复请求”响应
    7. 客户端只能收到 1 个“成功”,如果客户端碰巧没有收到它,那么在以后的尝试中它将获得“重复请求”并且也知道它已被插入。

现在,如果服务器不关心重复并且您无法控制它,并且它只是客户端,那么最好的解决方案就是等待很长时间再试一次,并且总是交替获取和发布。不过理论上你永远不会知道,因为也许他们有一个队列可以在服务器离线时收集请求,下周他们会处理它们。

于 2015-08-12T18:13:12.017 回答