并发环境下的幂等PUT请求

6

背景

我有一个REST API,多个客户端(应用程序)可以使用PUT更新资源的状态。例如,这个资源是一盏可以打开或关闭的灯。

当系统检测到停电时,这个资源也会自动更新,导致灯处于“坏掉”的状态。我想区分“坏掉”和“关闭”,处于“坏掉”状态的灯不能被打开!

问题

我使用PUT方法来做这件事,类似于 PUT http://address:port/my_lamp { "state": "ON"}

但我不确定是否遵守了PUT方法的幂等性属性。实际上,我有三种情况:

  • 灯是打开的。上面的代码将导致灯处于打开状态。
  • 灯是打开的。上面的代码将导致灯处于打开状态....很酷!此时,幂等性仍然得到保证:-)!
  • 灯是坏掉的。上面的代码将导致错误,如503服务不可用

问题

我不确定是否正确理解幂等性的概念。相信我,我读了很多关于它的东西,但仍然有点困惑。

在我的理解中,多个PUT总是导致资源的相同状态:由于“坏掉”,在我的情况下不能保证

但我也可以用另一种方式理解它:多个PUT总是导致相同的副作用:保证,我的请求要么产生打开状态,要么不做任何事情(对于“坏掉”的情况,它已经存在)。

编辑:

我的意思是:唯一的副作用是打开灯,这是有保证的(它要么打开,要么在此处不做任何事情)

请参见:REST DELETE真的幂等吗?

哪一个是正确的?根据理解,我的REST API是否确保幂等性...

编辑2:

W3C的定义中

方法还可以具有“幂等性”属性,即(除了错误或过期问题),N > 0个相同请求的副作用与单个请求的副作用相同。

当灯泡是 BROKEN 状态时,打开灯是否算错误?

1个回答

10

幂等性意味着在一个隔离的环境中,来自同一客户端的多个请求对资源状态没有任何影响。如果来自另一个客户端的请求更改了资源的状态,则不会违反幂等性原则。但是,如果您确实希望确保put请求不会被来自不同客户端的同时请求覆盖更改,则应始终使用ETags。简而言之,put请求应始终提供上次资源状态的ETag(从get请求获取),仅当ETag最新时才应更新资源,否则应引发412(前提条件失败)状态代码。在412的情况下,客户端应该重新获取资源,然后尝试更新。根据REST,这对于防止竞争条件至关重要。

更进一步解释:

根据W3C(http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html),'方法也可以具有“幂等性”属性,即(除错误或过期问题外),N> 0个相同请求的副作用与单个请求相同。'

Get request - {'state': 'ON'} Etag-header(say)- 123
PUT request - {'state': 'OFF'} Etag-header - 123

某些内部活动会改变其状态,使新状态为{'state': 'BROKEN'}。在这种情况下,etag应该被更改为124。

put request - {'state': 'ON'} Etag-header - 123.

由于ETag头已更改,会返回412错误,这不会破坏API的幂等性(除了错误或过期问题)。

Get request - {'state': 'BROKEN'} Etag-header - 124
Put request - {'state': 'ON'} Etag-header - 124

你说的“不会对资源状态产生任何影响”是什么意思?这就让我感到困惑了。请注意,系统自己会将状态更新为BROKEN...因此不需要通过REST接口进行更新。即使客户端在我的情况下收到412,如果它再次使用正确的ETag发出相同的请求...它仍然会收到503 - 服务不可用。所以我们又回到了同样的问题。 - AilurusFulgens
1
我的意思是,如果除了您的PUT请求之外的某个事件更新了资源,那并不意味着幂等原则被破坏。这仅意味着在单用户环境中(没有其他人可以更改资源),由于多个请求,资源的状态不应该发生变化。此外,如果资源状态出于任何原因发生更改,则客户端应该先获取更新后的资源,然后发送PUT请求(这就是ETag的作用)。 - hspandher
如果您觉得这篇文章有帮助,请将其标记为正确答案。 - hspandher
是的。但如果您能使用正确的ETag标头编辑最后一个PUT请求,那将非常好...这会导致503错误,但不会破坏幂等性(与412错误相同的原因)。 - AilurusFulgens
我在谈论最后一次带有效ETag(124)的PUT请求的响应。假设您无法从BROKEN状态到达ON状态,服务器将响应错误(无论是5xx还是其他错误)。 - AilurusFulgens
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接