`

【转】理解HTTP幂等性

阅读更多
原文地址:http://www.cnblogs.com/weidagang2046/archive/2011/06/04/2063696.html


cat todd.log | grep programming | sort -r
理解HTTP幂等性

基于HTTP协议的Web API是时下最为流行的一种分布式服务提供方式。无论是在大型互联网应用还是企业级架构中,我们都见到了越来越多的SOA或RESTful的Web API。为什么Web API如此流行呢?我认为很大程度上应归功于简单有效的HTTP协议。HTTP协议是一种分布式的面向资源的网络应用层协议,无论是服务器端提供Web服务,还是客户端消费Web服务都非常简单。再加上浏览器、Javascript、AJAX、JSON以及HTML5等技术和工具的发展,互联网应用架构设计表现出了从传统的PHP、JSP、ASP.NET等服务器端动态网页向Web API + RIA(富互联网应用)过渡的趋势。Web API专注于提供业务服务,RIA专注于用户界面和交互设计,从此两个领域的分工更加明晰。在这种趋势下,Web API设计将成为服务器端程序员的必修课。然而,正如简单的Java语言并不意味着高质量的Java程序,简单的HTTP协议也不意味着高质量的Web API。要想设计出高质量的Web API,还需要深入理解分布式系统及HTTP协议的特性。

幂等性定义

本文所要探讨的正是HTTP协议涉及到的一种重要性质:幂等性(Idempotence)。在HTTP/1.1规范中幂等性的定义是:

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.

从定义上看,HTTP方法的幂等性是指一次和多次请求某一个资源应该具有同样的副作用。幂等性属于语义范畴,正如编译器只能帮助检查语法错误一样,HTTP规范也没有办法通过消息格式等语法手段来定义它,这可能是它不太受到重视的原因之一。但实际上,幂等性是分布式系统设计中十分重要的概念,而HTTP的分布式本质也决定了它在HTTP中具有重要地位。

分布式事务 vs 幂等设计

为什么需要幂等性呢?我们先从一个例子说起,假设有一个从账户取钱的远程API(可以是HTTP的,也可以不是),我们暂时用类函数的方式记为:

bool withdraw(account_id, amount)

withdraw的语义是从account_id对应的账户中扣除amount数额的钱;如果扣除成功则返回true,账户余额减少amount;如果扣除失败则返回false,账户余额不变。值得注意的是:和本地环境相比,我们不能轻易假设分布式环境的可靠性。一种典型的情况是withdraw请求已经被服务器端正确处理,但服务器端的返回结果由于网络等原因被掉丢了,导致客户端无法得知处理结果。如果是在网页上,一些不恰当的设计可能会使用户认为上一次操作失败了,然后刷新页面,这就导致了withdraw被调用两次,账户也被多扣了一次钱。如图1所示:


这个问题的解决方案一是采用分布式事务,通过引入支持分布式事务的中间件来保证withdraw功能的事务性。分布式事务的优点是对于调用者很简单,复杂性都交给了中间件来管理。缺点则是一方面架构太重量级,容易被绑在特定的中间件上,不利于异构系统的集成;另一方面分布式事务虽然能保证事务的ACID性质,而但却无法提供性能和可用性的保证。

另一种更轻量级的解决方案是幂等设计。我们可以通过一些技巧把withdraw变成幂等的,比如:

int create_ticket()
bool idempotent_withdraw(ticket_id, account_id, amount)

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

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


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

HTTP的幂等性

HTTP协议本身是一种面向资源的应用层协议,但对HTTP协议的使用实际上存在着两种不同的方式:一种是RESTful的,它把HTTP当成应用层协议,比较忠实地遵守了HTTP协议的各种规定;另一种是SOA的,它并没有完全把HTTP当成应用层协议,而是把HTTP协议作为了传输层协议,然后在HTTP之上建立了自己的应用层协议。本文所讨论的HTTP幂等性主要针对RESTful风格的,不过正如上一节所看到的那样,幂等性并不属于特定的协议,它是分布式系统的一种特性;所以,不论是SOA还是RESTful的Web API设计都应该考虑幂等性。下面将介绍HTTP GET、DELETE、PUT、POST四种主要方法的语义和幂等性。

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

HTTP DELETE方法用于删除资源,有副作用,但它应该满足幂等性。比如:DELETE http://www.forum.com/article/4231,调用一次和N次对系统产生的副作用是相同的,即删掉id为4231的帖子;因此,调用者可以多次调用或刷新页面而不必担心引起错误。

比较容易混淆的是HTTP POST和PUT。POST和PUT的区别容易被简单地误认为“POST表示创建资源,PUT表示更新资源”;而实际上,二者均可用于创建资源,更为本质的差别是在幂等性方面。在HTTP规范中对POST和PUT是这样定义的:

The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line. ...... If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header.
The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.

POST所对应的URI并非创建的资源本身,而是资源的接收者。比如:POST http://www.forum.com/articles的语义是在http://www.forum.com/articles下创建一篇帖子,HTTP响应中应包含帖子的创建状态以及帖子的URI。两次相同的POST请求会在服务器端创建两份资源,它们具有不同的URI;所以,POST方法不具备幂等性。而PUT所对应的URI是要创建或更新的资源本身。比如:PUT http://www.forum/articles/4231的语义是创建或更新ID为4231的帖子。对同一URI进行多次PUT的副作用和一次PUT是相同的;因此,PUT方法具有幂等性。

在介绍了几种操作的语义和幂等性之后,我们来看看如何通过Web API的形式实现前面所提到的取款功能。很简单,用POST /tickets来实现create_ticket;用PUT /accounts/account_id/ticket_id&amount=xxx来实现idempotent_withdraw。值得注意的是严格来讲amount参数不应该作为URI的一部分,真正的URI应该是/accounts/account_id/ticket_id,而amount应该放在请求的body中。这种模式可以应用于很多场合,比如:论坛网站中防止意外的重复发帖。

总结

上面简单介绍了幂等性的概念,用幂等设计取代分布式事务的方法,以及HTTP主要方法的语义和幂等性特征。其实,如果要追根溯源,幂等性是数学中的一个概念,表达的是N次变换与1次变换的结果相同,有兴趣的读者可以从Wikipedia上进一步了解。

参考

RFC 2616, Hypertext Transfer Protocol -- HTTP/1.1, Method Definitions
The Importance of Idempotence
stackoverflow -  PUT vs POST in REST
分享到:
评论

相关推荐

    理解HTTP幂等性

    HTTP幂等性的相关介绍,什么是幂等性,HTTP幂等性又是什么?

    分布式系统(微服务架构)的一致性和幂等性问题相关概念解析

    要想更好的理解分布式系统,并正确使用甚至构建分布式系统,需要理解其中的两个关键概念——分布式系统的数据一致性和分布式系统的幂等性。如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis...

    Java面试题-Web相关.pdf

    二、如何理解 RESTful API 幂等性 1、什么是幂等性? HTTP幂等方法,是指无论调用多少次都不会有不同结果的HTTP方法。不管你调用一次,还是调用一百次,一千次,结果都是相同的。 GET /tickets # 获取ticket列表 ...

    模逆和模幂计算与应用

    使学生切实掌握作为大多数公钥密码计算基础的“模逆”与“模幂”算法,并学会运用上述两个基本算法来实现诸如 RSA、ElGamal 等公钥密码的各主要需求和功能,最终对“一个公钥密码体制如何应用”形成一定的认识和理解...

    09.避免重复扣款:分布式支付系统的幂等性原理与实践_V20240116.pdf

    汇集了我十多年支付系统架构设计的经验总结,以实战为导向,深入浅出讲解支付系统的架构设计与实现,涵盖基础概念、核心流程、核心子系统设计、核心技术专题等。这些知识点以实用为目标,可直接应用到日常研发设计中...

    论文研究 - 刚果盆地热带森林地上生物量预测建模幂函数的准确性分析

    必须避免直径对数的幂作为预测变量,因为这会导致最差的调整和更高的预测不确定性。 树高作为第三个预测变量,可提供最佳调整,并比采用其他两个预测变量(直径和木材比重)的模型少约8 t / ha,降低了生物量预测的...

    RocketMQ高级原理:深入剖析消息系统的核心机制

    《RocketMQ高级原理:深入剖析消息系统的核心...此外,还探讨了RocketMQ在负载均衡、消息重试、死信队列处理和保证消息幂等性方面的策略和实现方式,为开发人员和架构师提供了深入理解RocketMQ内部工作机制的宝贵资料。

    Tσ(G)理论的幂等轨道和库仑分支:特殊的正交与正交量规群因子

    一组3d N $$ \ mathcal {N} $$ = 4个超对称轨距理论的库仑分支是代数子$$ \ mathfrak {so}(n)$$的幂等轨道的闭合。 从弦论的观点来看,这些量子场论可以理解为有效量规理论,它描述了具有取向平面[1]的麸构型的...

    若依RuoYi框架剖析笔记,该笔记是在学习江南一点雨所录课程再结合自己的理解所写

    7、处理幂等性的思路与防止表单重复提交 8、数据权限 9、分布式事务解决方案(Seata) 10、分布式事务总结 11、自定义注解+AOP 12、权限中的概念梳理 13、登录.授权流程梳理 14、RuoYi-Vue3 15、动态菜单加载思路 16...

    论文研究-基于重复消费动力学的用户网络消费模式分析.pdf

    为了更好地理解时效性对重复消费的影响,提出了一种包含质量和时效性的重复消费混合模型。在重复消费动力学中,用户对重复项的选取取决于先前所有相同项的时效性权重之和。在混合模型的参数求解过程中,提出了一种...

    有效场论的弹性边界

    固体材料中的声子可以理解为自然打破的时空对称的戈德斯通玻色子。 这样,它们的低能量动力学受到很大的限制,并且可以通过标准的有效场论方法来捕获。 尤其是,非线性应力-应变曲线的知识可以完全有效地将全有效...

    论文研究 - 时空演化中的对称性及其与高频引力波产生的联系

    我们声称,一个缩小的先验宇宙通过约10到负44幂秒的虫洞桥解决方案与我们自己的联系,可以形成一个短期的典型标量场。 对称性允许在膨胀开始时产生高频引力波,这在我们当前的宇宙学时代产生了影响。 当前宇宙之间的...

    关于Boussinesq方程Barenblatt幂级数解的注记 (2007年)

    通过幂级数展开的方法推求...也没有证明该幂级数解的收敛性),并对该级数的收敛性进行了证明,同时对解的实际应用作了讨论这些研究结论易于理解,方便工程技术人员应用于流域水文学和基流研究及解决农业排水等实际问题

    用于SQCD的Brane腹板和电磁颤抖

    我们将这种方法与使用希尔伯特级数技术计算超凯勒商的方法进行比较,如果通过计算所谓的根基来消除幂等算子,则会找到完美的一致性。 我们研究了幂等算子的性质,并给出了完整希格斯分支的希尔伯特级数的猜想,从而...

    Java中间件-RabbitMQ教程

    3. 掌握消息的可靠性、幂等性、顺序消息、延迟消息、事务消息等进阶的知识,以及大规模生产 环境中的使用经验,轻松应对各种复杂的业务场景 4. 掌握顶级开源消息中间件核心源码,理解其背后的架构设计思想以及在高...

    matlab如何用代码拟合幂函数-Regularized-Linear-Regression-and-Bias-v.s.-Variance:正

    这种分配有助于我们理解偏差和方差如何与模型的可预测性不同。 本练习中包含的文件 ex5.m-引导您完成练习的Octave / MATLAB脚本ex5data1.mat-数据集Submit.m-将解决方案发送到我们服务器的提交脚本featureNormalize....

    论文研究 - 用格子Boltzmann方法模拟华而不实的牙龈(动力流体)

    根据HaakeRT20粘度计在4%的芳香性口香糖分散液的流变性中获得的结果,在pH = 3.0和9.0,温度5°C,25°C和45°C的不同条件下,得到的流变行为数据胶分散体适合幂律模型。 为了理解和预测这种口香糖的行为,除了使用...

    在两个循环中克服颜色运动学对偶的障碍

    颜色运动学对偶的发现使我们对重力UV结构的理解有了长足的进步。 但是,事实证明在某些情况下很难找到满足颜色运动学对偶性的分子。 我们讨论了在五胶子峰振幅的背景下构建一组这样的分子的障碍,所有螺旋线在两个...

    python项目数学函数绘图软件cs.zip

    3. **绘图功能**:用户可以在系统中绘制一次、二次、多次函数、三角函数、幂函数、指数函数、对数函数、圆锥曲线以及任意多边形等。用户还可以自由输入表达式,并随时调整函数的取值范围、图形的放大缩小、翻转平移...

Global site tag (gtag.js) - Google Analytics