HTTP(二)幂等性

幂等性是一个数学上的概念, 意思是一次变换和多次变化得到的结果应该是一样的。从IT的角度, http方法的幂等性是指一次和多次请求某一个资源应该具有同样的副作用。幂等性是分布式系统设计中十分重要的概念, 而http的分布式本质也决定了它在http中具有重要地位。

分布式事务 vs 幂等设计

从一个例子说起, 假设有一个从账户取钱的远程API, 暂时用类函数的方式记为

boolean withdrawn(account_id, amount)

withdrawn方法的意思是从account_id对应的账户中扣除amount数额的钱; 如果扣除成功则返回true, 账户余额减少amount; 如果扣除失败则返回false, 账户余额不变。

和本地环境相比, 我们不能轻易假设分布式环境的可靠性。一种典型的情况是withdrawn请求已经被服务器正确处理, 但服务器的返回结果由于网络等原因被丢失掉了, 导致客户端无法得知处理结果。如果是在网页上, 一些不恰当的设计可能会使用户认为上一次操作失败了, 然后刷新页面, 这就导致withdrawn被调用了两次

这个问题的解决是用分布式事务, 通过引入支持分布式事务的中间件来保证withdrawn功能的事务。相对于调用者简单, 复杂性都交给了中间件来处理。缺点是一方面架构太重量级, 容易被绑定在特定的中间件上, 不利于异构系统的集成。

更轻量级的解决方案是幂等设计。可以通过一些技巧把withdrawn变成幂等的

int create_ticket()

boolean idempotent_withdrawn(ticket_id, account_id, amount)

create_ticket方法获取一个服务器生成的唯一的处理号ticket_id, 将用于表示后续的操作。idempotent_withdrawn和withdrawn的区别在于关联了一个ticket_id, 一个ticket_id表示的操作至多只会被处理一次, 每次调用都将返回第一次调用时的处理结果。这样, idempotent_withdraw就符合幂等性了, 客户端就可以放心地多次调用。

基于幂等性的解决方案中一次完整的取钱流程被分解了两个步骤: 1. 调用create_ticket()获取ticket_id; 2. 调用idempotent_withdrawn(ticket_id, account_id, amount). 虽然create_ticket不是幂等的, 但是在这种设计下, 它对系统状态的影响可以忽略, 加上idempotent_withdrawn是幂等的, 所以任何一步由于网络等原因失败或超时, 客户端都可以重试, 直到获得结果

和分布式事务相比, 幂等设计的优势在于它的轻量性, 容器适应异构环境, 以及性能和可用性方面。在某些性能要求比较高的应用, 幂等设计往往是唯一的选择。

Http的幂等性

GET方法用于获取资源, 不应有副作用, 所以是幂等的

比如:GET http://www.bank.com/account/123456,不会改变资源的状态,不论调用一次还是N次都没有副作用。请注意,这里强调的是一次和N次具有相同的副作用,而不是每次GET的结果相同。GET http://www.news.com/latest-news这个HTTP请求可能会每次得到不同的结果,但它本身并没有产生任何副作用,因而是满足幂等性的

DELETE方法用于删除资源, 有副作用, 但它应该满足幂等性

比如:DELETE http://www.forum.com/article/4231,调用一次和N次对系统产生的副作用是相同的,即删掉id为4231的帖子;因此,调用者可以多次调用或刷新页面而不必担心引起错误

POST 方法不具有幂等性

POST和PUT的区别容易被简单地误认为“POST表示创建资源,PUT表示更新资源”;而实际上,二者均可用于创建资源,更为本质的差别是在幂等性方面。POST所对应的URI并非创建的资源本身,而是资源的接收者。比如:POST http://www.forum.com/articles的语义是在http://www.forum.com/articles下创建一篇帖子,HTTP响应中应包含帖子的创建状态以及帖子的URI。两次相同的POST请求会在服务器端创建两份资源,它们具有不同的URI;所以,POST方法不具备幂等性

PUT 方法具有幂等性

而PUT所对应的URI是要创建或更新的资源本身。比如:PUT http://www.forum/articles/4231的语义是创建或更新ID为4231的帖子。第一次PUT方法执行之后,其在服务器上生成的资源,不能被后续的PUT方法更改,所以对同一URI进行多次PUT的副作用和一次PUT是相同的;因此,PUT方法具有幂等性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值