0

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

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

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

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

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

在上面的假设场景中,用户 A 的重复请求导致用户 B 的请求被覆盖,并导致服务器端的状态不正确。

一种可能但幼稚的解决方案是为客户端上的每个请求设置一个 ID,如果只是重新尝试/重新发送请求,则此 ID 不会更改。然后在服务器端,服务器维护接收到的请求 ID 的集合并检查重复项。

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

4

1 回答 1

2

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

例如,用户 A 想要更改会议时间。它发送对会议资源的 GET 请求并保留Last-Modified响应标头的值。然后,它使用标头中的值发送POST请求。按照您的示例,此请求实际上成功了,但响应丢失了。Last-ModifiedIf-Unmodified-Since

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

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

于 2015-04-24T21:16:40.643 回答