假设我们有一个创建和更新会议室预订的Web服务。更新可以改变预订的各个方面,例如时间和房间号。
让我们假设用户与服务的网络连接可能不可靠(例如移动网络),两个用户A和B尝试按顺序更新相同的预订。
用户A发送POST请求以将会议时间更改为下午2点,请求到达服务器并且服务器成功处理了请求。但是,由于网络连接,用户A的响应会丢失,而用户A认为请求失败。
在用户A再次尝试之前,用户B发送请求将会议时间更改为下午2:30,并且成功并成功响应用户B.
现在用户A再次(可能自动)重试相同的请求,这次请求和响应都成功而没有问题。换句话说,会议时间会改回到下午2点。
在上面的假设场景中,用户A的重复请求会导致用户B的请求被覆盖,并导致服务器端的状态不正确。
一种可能但天真的解决方案是为客户端上的每个请求设置一个ID,如果只是重新尝试/重新发送请求,则此ID不会更改。然后在服务器端,服务器维护一组收到的请求ID并检查重复项。
解决此问题的更好技巧或方法是什么?
答案 0 :(得分:2)
这是并发用户的常见问题。解决此问题的一种方法是强制执行条件请求,要求客户端发送If-Unmodified-Since
标头,并为其尝试更改的资源发送Last-Modified
标头。这保证了在他们最后一次检查和现在之间没有其他人改变它。在您的情况下,这将阻止A覆盖B的更改。
例如,用户A想要更改会议时间。它发送会议资源的GET请求并保留Last-Modified
响应头的值。然后,它会在POST
标头中发送带有Last-Modified
值的If-Unmodified-Since
请求。按照您的示例,此请求实际上成功,但响应丢失。
如果A立即重复请求,它将失败412 Precondition Failed
,因为条件不再有效。
如果在此期间B执行相同的操作并再次更改会议时间,当A尝试重复请求时,不检查与B的更改对应的当前Last-Modified
值,它也会失败{{1 }}