处理重复 POST 请求引起的副作用

Handle side effects caused by duplicate POST requests

假设我们有一个创建和更新会议室预订的 Web 服务。更新可以更改预订的各个方面,例如时间和房间号。

假设用户与服务的网络连接可能不可靠(例如移动网络),并且两个用户 A 和 B 尝试按顺序更新同一个预订。

用户A发送POST请求将会议时间更改为下午2点,请求到达服务器,服务器成功处理请求。但是返回给用户A的响应由于网络连接丢失,用户A认为请求失败。

在用户 A 再次尝试之前,用户 B 发送了她将会议时间更改为 2:30pm 的请求,并且成功并成功响应了用户 B。

现在用户 A 再次重试(可能是自动)同一个请求,这次请求和响应都成功了,没有问题。也就是说,会议时间改回下午2点。

在上述假设场景中,用户 A 的重复请求导致用户 B 的请求被覆盖,并导致 server-side 上的状态不正确。

一个可能但天真的解决方案是为客户端上的每个请求设置一个 ID,如果请求只是 re-tried/re-sent,则此 ID 不会改变。然后在 server-side 上,服务器维护 collection 收到的请求 ID 并检查重复项。

解决这个问题有什么更好的技术或方法?

这是并发用户的常见问题。解决它的一种方法是强制执行条件请求,要求客户端发送 If-Unmodified-Since header 和他们试图更改的资源的 Last-Modified 值。这保证在他们上次检查和现在之间没有其他人更改它。在您的情况下,这将防止 A 覆盖 B 的更改。

比如用户A想更改会议时间。它发送会议资源的 GET 请求并保留 Last-Modified 响应 header 的值。然后,它在 If-Unmodified-Since header 中发送带有 Last-Modified 值的 POST 请求。按照你的例子,这个请求实际上成功了,但是响应丢失了。

如果 A 立即重复请求,它将失败 412 Precondition Failed,因为条件不再有效。

如果同时 B 做同样的事情并再次更改会议时间,当 A 尝试重复请求时,没有检查与 B 的更改对应的当前 Last-Modified 值,它也会失败 412 Precondition Failed.