`
nesta2001zhang
  • 浏览: 68965 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

HTTP幂等性概念和应用

    博客分类:
  • REST
 
阅读更多

基于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的,也可以不是),我们暂时用类函数的方式记为

1
bool withdraw(account_id, amount);

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

image

图1

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

另一种更轻量级的解决方案是幂等设计。上面的withdraw显然不满足幂等性,但我们可以一些技巧将它变成幂等的,比如:

1
2
3
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所示:

image

图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

分享到:
评论

相关推荐

    高并发系统数据幂等的解决方案

    在系统开发过程中,经常遇到数据重复插入、重复更新、消息重发发送等等问题,因为应用系统的复杂逻辑以及网络交互存在的不确定性,会导致这一重复现象,但是有些逻辑是需要有幂等特性的,否则造成的后果会比较严重,...

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

    《RocketMQ高级原理:深入剖析消息系统的核心机制》的关键内容,涵盖RocketMQ的基础组件、消息存储机制、刷盘方式、主从复制、负载均衡、消息重试、死信队列和幂等性等核心概念。RocketMQ作为一款高性能、高可用的...

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

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

    响应式架构 消息模式Actor实现与Scala.Akka应用集成

    其中包括:Actor模型和响应式软件的主要概念、Scala语言的基础知识、Akka框架与Akka集群功能、Actor模型中的通道机制和技术、降低消息源与消息目的地之间耦合性的方式、持久化Actor对象和幂等接收者。附录A中还介绍...

    数学分析理论及应用 [许尔伟,毛耀忠,安乐 主编] 2014年版

    《数学分析理论及应用》结构合理、阐述准确、通俗易懂、深入浅出、条理清楚、逻辑性强,易于学习和理解。本书既可作为数学专业学生的参考书,可也作为非数学专业学生的参考书,对其他课程的学习也具有很好的参考价值...

    论文研究-区间二元语义Bonferroni集成算子及其决策应用.pdf

    在此基础上,给出了组合形式的区间二元语义值的加权Bonferroni平均算子的概念,并研究了算子的幂等性、单调性等数学性质,给出了基于C-I2TLWBA算子区间二元语义值的集成模型和决策应用。实例表明了该模型具有较好的...

    响应式架构 消息模式Actor实现与Scala.Akka应用集成.rar

    其中包括:Actor模型和响应式软件的主要概念、Scala语言的基础知识、Akka框架与Akka集群功能、Actor模型中的通道机制和技术、降低消息源与消息目的地之间耦合性的方式、持久化Actor对象和幂等接收者。附录A中还介绍...

    复分析及其在数值数学中的应用 [匡蛟勋,田红炯 著] 2012年版

    幂级数理论及Laurent展开,残数理论及幅角原理,解析函数的最大模原理及调和函数的极值原理,解析函数的唯一性定理及零点理论,整函数与半纯函数,Riemann曲面及代数函数理论,复分析在矩阵分析、常微分方程及泛函...

    同济大学高等数学(第七版)下册第12章习题答案详解

     习题12-1 常数项级数的概念和性质  习题12-2 常数项级数的审敛法  习题12-3 幂级数  习题12-4 函数展开成幂级数  习题12-5 函数的幂级数展开式的应用  习题12-6 函数项级数的一致收敛性及一致收敛级数...

    论文研究 - 小波在检测巴西股市趋势反转中的应用

    应用对数周期幂律的概念,当临界时刻临近(市场下跌的可能性较高时),其振荡会出现振幅和周期的减小(在市场下跌的可能性较高的情况下),它使用连续小波变换来检测振荡频率的增加。股票价格,时间序列并产生卖出...

    论文研究-布尔决策表的属性约简新方法:应用于欺诈识别.pdf

    基于欺诈识别中的布尔型决策表,提出了属性幂的概念,据此可以快速计算划分,缩短运算时间。应用粗糙集相关理论,并结合排序思想,提出一种新的决策表属性约简方法。实例计算及应用于信用数据上的实验验证了算法的...

    复变函数与常用变换 [黄大奎,陶德元 著] 2013年版

    为适应目前计划为48-64学时的课程安排,《复变函数与常用变换/高等学校教材》的编写没有追求理论系统的完备性和普适性,而是力求准确讲述后继专业课中最需要的内容,注重揭示数学概念和数学方法的思想实质,适当解释...

    《高等学校教材:复变函数与常用变换》作者: 黄大奎,陶德元 著 出版时间: 2013年

    为适应目前计划为48-64学时的课程安排,《复变函数与常用变换/高等学校教材》的编写没有追求理论系统的完备性和普适性,而是力求准确讲述后继专业课中最需要的内容,注重揭示数学概念和数学方法的思想实质,适当解释...

    复变函数与积分变换 [王志勇] 2014年版

    内容设计简明,叙述通俗易懂,定位应用和能力培养,具有针对性、先进性和系统性。本书内容包括复变函数与解析函数、复变函数的积分、级数与留数、傅立叶变换、拉普拉斯变换、Z变换与小波变换。每章习题配有基础和...

    极限环分支理论 英文 [HanMaoan] 2013年版

    首先引入了中心、闭轨以及同宿环的环性数概念,之后建立寻求这些环性数的一般方法,对含幂零奇点的Hamiltonian系统的扰动分支进行了深入研究,包括幂零中心的扰动分支、尖点环的扰动分支、含幂零鞍点的同宿环的扰动...

    《 法兰西数学精品译丛:解析函数论初步》作者: H.嘉当 译者: 余家荣 出版年: 2008年

    该书先讲收敛幂级数,后讲可导函数及积分,精确地引进了解析空间和黎曼面等概念,讲述了多复变解析函数的概念,在使用工具方面,引进了拓扑及抽象代数中的一些概念。书中还包括很多练习。. 原书已被翻译成中、日、...

    企业级消息队列Kafka视频教程

    7.1 幂等性 第八章 分区和副本机制 8.1 生产者分区写入策略 8.2 消费者组Rebalance机制 8.3 消费者分区分配策略 8.4 副本机制 第九章 高级(High Level)API与低级(Low Level)API 9.1 高级API 9.2 低级API 9.3 ...

    网络安全知识点.doc

    比如:从用户 (个人、 企业等 )的角度来说,他们希望涉及个人隐私或商业利益的信息在网 络上传输时受到机密性、完整性和真实性的保护,避免其他人或对 手利用窃听、冒充、篡改、抵赖等手段侵犯用户的利益和隐私。...

    论文研究 - 关于古典到量子Weyl对应

    当次泊松统计和超级泊松统计的概念用于定义状态的非经典性时,这是有问题的,因为在正常顺序中提到的度量并不能以唯一的方式确定泊松统计在其中间,而是仅确定大量统计从希尔伯特-施密特距离的意义上讲,这与所讨论...

    阿贝尔群性分类的初步研究 (2011年)

    利用正交幂等类系统在处理实际问题时十分方便,而且结果比较准确,所以在实际生活中应用...在正交幂等类系统及有效分类的基础上,引入了阿贝尔群性分类的概念,并对阿贝尔群性分类进行 了初步的研究,得到了一些基本的性质。

Global site tag (gtag.js) - Google Analytics