理解HTTP幂等性

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

理解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所示:

non-idempotent

图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所示:

idempotent

图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上进一步了解。


转载于:https://my.oschina.net/stephenzhang/blog/646243

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/543531.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

控件UI性能调优 -- SizeChanged不是万能的

简介 我们在之前的“UWP控件开发——用NuGet包装自己的控件“一文中曾提到XAML的布局系统 和平时使用上的一些问题(重写Measure/Arrange还是使用SizeChanged?),这篇博文就来为大家简单地描述一下XAML布局系统的行为,并…

android 跨进程多实例播放demo

2019独角兽企业重金招聘Python工程师标准>>> 客户端进程需要实现,其中notify方法需要service 跨进程调用,通知客户端播放消息 IMediaPlayerClient.aidl package com.example.demo; import com.example.demo.ParcelableParcel; interface IM…

java 获取service_Java service层获取HttpServletRequest工具类的方法

Java service层获取HttpServletRequest工具类的方法大家都知道 能在Controller/action层获取HttpServletRequest,但是这里给大家备份的是从代码内部service层获取HttpServletRequest工具类。具体如下:package com.base.common.sessionutils;import javax…

Linux使用jstat命令查看jvm的GC情况

2019独角兽企业重金招聘Python工程师标准>>> 命令格式 jstat命令命令格式: jstat [Options] vmid [interval] [count] 参数说明: Options,选项,我们一般使用 -gcutil 查看gc情况 vmid,VM的进程号&#x…

python写一段脚本代码自动完成输入(目录下的所有)文件的数据替换(修改数据和替换数据都是输入的)【转】...

转自:http://blog.csdn.net/lixiaojie1012/article/details/23628129 初次尝试python语言,感觉用着真舒服,简单明了,库函数一调用就OK了[python] view plain copy 在CODE上查看代码片派生到我的代码片 import sys,os,os.path de…

java混合分页_坑,MySQL中 order by 与 limit 混用,分页会出现问题!

在Mysql中我们常常用order by来进行排序,使用limit来进行分页,当需要先排序后分页时我们往往使用类似的写法select * from 表名 order by 排序字段 limt M,N。但是这种写法却隐藏着较深的使用陷阱。在排序字段有数据重复的情况下,会很容易出现…

OSG开发概览

1 OSG基础知识 OSG是Open Scene Graphic 的缩写,OSG于1997年诞生于以为滑翔机爱好者之手,Don burns 为了对滑翔机的飞行进行模拟,对openGL的库进行了封装,osg的雏形就这样诞生了,1998年Don burns 遇到了同样喜欢滑翔…

hbuilder php xdebug,Hbuilder使用xdebug配置php断点调试

2019独角兽企业重金招聘Python工程师标准>>>##1. 背景不得不说Hbuilder是免费的前端开发工具中比较好用的,而且配合aptana开发php也马马虎虎(毕竟写前端的时候多些)。本人原是搞java的,后来打算用php做些个人项目(因为服务器成本低)&#xff0c…

mx播放器有没有投屏功能_无线投屏、即插即用,投影仪其实可以更智能:明基 E580T...

无论是简单的办公室会议还是小型的线下活动,投影仪都是必不可少的利器:既能有不错的显示效果,也不用受屏幕尺寸的约束。尽管越来越多的智能电视可供电脑连接,但真正派上用场的时候,拎箱就走的投影仪显然是最佳选择。很…

特殊矩阵-对角矩阵

2019独角兽企业重金招聘Python工程师标准>>> 挖坑。 转载于:https://my.oschina.net/aslanjia/blog/651503

vs运行时候冒了这个错:无法启动IIS Express Web 服务器~Win10

后期会在博客首发更新:http://dnt.dkill.net 异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983.html 网上的方法多种,有让安装扩展插件的,有让在程序里面添加Http系列的组件,有其它其它的,可是。。。…

matlab脚本 定时停止_一触即发是什么软件?它是手机上极其强大的一款脚本辅助精灵...

一触即发app是手机上极其强大的一款免root的脚本辅助软件,堪称一键秒杀脚本精灵,除自动化、运行、管理外,还提供了脚本制作文字教程/视频教程,学习社区和图色处理、定时执行、王者荣耀、变量等命令参数和多点找色、多点找图、京东…

笔记本电脑处理器_高通提示低成本5G芯片更强大的笔记本电脑处理器

高通公司总裁克里斯蒂亚诺阿蒙(Cristiano Amon)在今天的柏林IFA贸易展览会的虚拟主题演讲中说,我们将很快看到更便宜的5G手机,以及更多具有更好应用兼容性的Windows-on-Snapdragon笔记本电脑。欧洲主要的电子产品展览会IFA今年被分成​​几个小组活动&am…

为什么6lowpan 要有四个地址_大型监控网络系统如何规划ip地址

本文转自网络对于监控项目来说,很多故障的原因都是跟ip地址设置不当有关,如ip冲突,或者有几路监控图像没有显示等,都是跟ip有一定关联,合理的分配ip地址十分重要。一、为什么要合理分配IP对于小型监控项目来说&#xf…

JAVA中的命令模式实例教程

原文链接 作者&#xff1a;Pankaj Kumar 译者&#xff1a;f0tlo <1357654289qq.com> 命令模式是一种行为模式&#xff0c;因此&#xff0c;它处理的是对象的行为。命令模式为系统中不同的对象提供中性化的交流媒介。根据GoF的定义&#xff0c;命令模式是&#xff1a; 通…

bugku 管理员系统 后台代码_不会吧,这也行?iOS后台锁屏监听摇一摇

[toc] 背景介绍 一般情况下&#xff0c;出于省电、权限、合理性等因素考虑&#xff0c;给人的感觉是很多奇怪的需求安卓可以实现&#xff0c;但是iOS就无法实现&#xff01;今天要介绍的需求也有这种感觉&#xff0c;就是“当 APP 处于后台或锁屏状态时&#xff0c;依旧可以监听…

windows php5.3升级,Windows10系统将PHPNOW升级PHP版本为5.3.5

Windows 10发布很久了&#xff0c;现在大多数人都在使用&#xff0c;在WIN10中使用PHPNOW&#xff0c;觉得自带的PHP版本有点低&#xff0c;所以就想升级下&#xff0c;在网上搜索了一些方法&#xff0c;然后结合自己的实际操作&#xff0c;在这里分享下。1、首先要下载PHP5.3.…

igs无法分配驱动器映射表_硬盘无法使用,用DiskPart进行分区和格式化,非常简单...

如果计算机硬盘出现问题&#xff0c;有时不是硬件上出现了错误&#xff0c;很可能只是逻辑上出现了问题&#xff0c;这时就可以使用DiskPart来快速解决。在Windows 10上&#xff0c;当外部存储(例如U盘、可移动硬盘或SD卡)由于数据损坏或其他问题而停止工作时&#xff0c;可以使…

硬件nat关闭还是开启_超能课堂(173):AfterBurner不止超频,还是绝佳的游戏伴侣...

微星AfterBurner软件可以说是一个相当好用的显卡工具&#xff0c;它好用的超频功能估计都不用我多说了吧&#xff1f;微星并没有把这款软件限制在自己品牌的显卡能用&#xff0c;各个品牌的显卡都能用&#xff0c;无论A卡还是N卡都可以用AfterBurner来超频&#xff0c;软件在超…

mx350显卡天梯图_CPU天梯图与显卡天梯图2020年最新版

最新CPU天梯图较之以往没有太大的变化&#xff0c;前十位置还是那几款。但是继阿里之后&#xff0c;腾讯也开始准备自己制作芯片了&#xff0c;毕竟自研AI芯片的诱惑还是很大的&#xff0c;2020年有不少的厂商都推出了新鲜美味的显卡&#xff0c;有些是老卡翻新做性价比。有的则…