并发环境中的幂等 PUT [英] Idempotent PUT in a concurrent environment

查看:27
本文介绍了并发环境中的幂等 PUT的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景

我有一个 REST API,其中多个客户端(应用程序)可以使用 PUT 更新资源的状态.例如,此资源是一盏灯,您可以打开ONOFF.

当系统检测到发生断电时,该资源也会自动更新,导致灯处于BROKEN状态.我想区分BROKENOFFBROKEN中的灯不能ON

问题

我使用 PUT 方法来做到这一点,比如 PUT http://address:port/my_lamp { "state": "ON"}

但我不确定我是否尊重 PUT 方法的幂等性.事实上,我有 3 种情况:

  • ON.上面的代码导致 ON 状态.
  • ON.上面的代码导致 ON 状态......很酷!此时,幂等性还是有保证的 :-) !
  • 灯是BROKEN.上面的代码导致一个错误,比如503 Service Unavailable

问题

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

在我的理解中,多个 PUT 总是导致资源的相同状态:由于 BROKEN

但我也可以用另一种方式理解它:多个 PUT 总是会导致相同的副作用:保证,我的请求要么产生转 ON,要么什么都没有(对于 BROKEN 情况,它已经在了).

我的意思是:唯一的副作用是打开ON灯,这是有保证的(它要么打开要么在这里什么都不做)

参见此处:REST DELETE 真的是幂等的吗?

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

来自W3C的定义

<块引用>

方法也可以具有幂等性"的特性,因为(除了错误或过期问题)N > 0 个相同请求的副作用与单个请求相同.

我可以认为在 BROKEN 时打开 ON 灯是错误的吗?

解决方案

幂等性意味着在隔离环境中,来自同一客户端的多个请求不会对资源状态产生任何影响.如果来自另一个客户端的请求更改了资源的状态,则不会违反幂等性原则.虽然,如果您真的想确保 put 请求最终不会被来自不同客户端的另一个同时请求覆盖更改,您应该始终使用 etags.详细说明,放置请求应始终提供最后一个资源状态的 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)- 123PUT 请求 - {'state': 'OFF'} Etag-header - 123

某些内部活动更改状态,新状态为 {'state': 'BROKEN'}.在这个甚至 etag 应该更改为 124.

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

由于 etag 标头已更改,因此返回 412 错误,这不会破坏 api 的幂等性(除了错误或过期问题).

获取请求 - {'state': 'BROKEN'} Etag-header - 124放置请求 - {'state': 'ON'} Etag-header - 124

Context

I have a REST API where multiple clients (applications) can update the state of a resource with PUT. For the example, this resource is a lamp that you can turn ON or OFF.

This resource is also automatically updated by the system when it detects that an electricity failure has occurs, leading to have a lamp in a BROKEN state. I want to made the distinction between BROKEN and OFF, a lamp in BROKEN can not be turn ON !

Problem

I use PUT method to do this, something like PUT http://address:port/my_lamp { "state": "ON"}

But I am not sure if i respect the idempotent property of PUT method. In fact, i have 3 cases:

  • The lamp is ON. The above code leads to the ON state.
  • The lamp is ON. The above code leads to the ON state.... cool! At this moment, idempotency is still guaranteed :-) !
  • The lamp is BROKEN. The above code leads to an error, like 503 Service Unavailable

Question

I am not sure to correctly understand the notion of idempotency. Trust me, I read a lot of thing about it but still a little bit confused.

In my understanding, multiple PUT always leads to a same state of the resource: not guaranteed in my case due to BROKEN

But I could also understand it in an other way: multiple PUT always leads to the same side-effect: guaranteed, my request either produce to turn ON, either nothing (for the BROKEN case, it was already in).

EDIT:

I mean: the only side-effect is to turn ON the lamp, which is guaranteed (it either turn-on or do nothing here)

See here: Is REST DELETE really idempotent?

Which one is correct ? Depending of the understanding, my REST API ensure idempotency or not...

EDIT2:

From the definition of the W3C

Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.

Can i consider that it's an error to turn ON the lamp when it is BROKEN ?

解决方案

Idempotency means that in an isolated environment multiple requests from a same client does not have any effect on the state of resource. If request from another client changes the state of the resource, than it does not break the idempotency principle. Although, if you really want to ensure that put request does not end up overriding the changes by another simultaneous request from different client, you should always use etags. To elaborate, put request should always supply an etag (it got from get request) of the last resource state, and only if the etag is latest the resource should be updated, otherwise 412 (Precondition Failed) status code should be raised. In case of 412, client is suppose to get the resource again, and then try the update. According to REST, this is vital to prevent race conditions.

To elaborate even more:-

According to W3C(http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html), 'Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.'

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

Some internal activity changes state such that new state is {'state': 'BROKEN'}. In this even etag should be changed to say 124.

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

Since etag header has changed, 412 error is returned which does not break idempotence of api (aside from error or expiration issues).

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

这篇关于并发环境中的幂等 PUT的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆