`
nesta2001zhang
  • 浏览: 70754 次
  • 性别: 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

分享到:
评论

相关推荐

    幂等性和支付订单防重复

    幂等性源自数学领域,后被广泛应用于计算机科学中,特别是网络通信和分布式系统中。在HTTP协议中,幂等性被定义为:“一次和多次请求某一个资源对于资源本身应具有同样的结果(网络超时等问题除外)。”换言之,幂等...

    RabbitMQ消费端幂等性概念及解决方案.docx

    ### RabbitMQ消费端幂等性概念及解决方案 #### 一、幂等性的基本概念 **幂等性**是指用户对于同一个操作发起一次请求或多次请求的结果保持一致的特性。例如,在数据库操作中,通过实现乐观锁机制来确保幂等性。...

    分布式架构中的幂等性

    ### 分布式架构中的幂等性 ...通过对幂等性的理解和应用,可以在保证系统性能的同时提高系统的可靠性和稳定性。特别是在电商领域,通过实现幂等性可以有效防止重复操作带来的问题,同时确保系统的最终一致性。

    系统接口幂等性规范

    在IT行业中,系统接口幂等性是一个至关重要的概念,尤其对于设计高可用、高可靠性的分布式系统来说。本文将深入探讨这个主题,并基于提供的“幂等.pptx”文件内容进行详细阐述。 幂等性(Idempotency)是指一个操作...

    38_分布式系统中接口的幂等性该如何保证?比如不能重复扣款?.zip

    在分布式系统设计中,接口的幂等性是一个关键概念,尤其是在金融系统或者订单处理系统中,确保操作的唯一性和不可重复执行是至关重要的。例如,我们提到的“不能重复扣款”的需求,就直接涉及到幂等性的应用。下面将...

    02、接口幂等性1

    在本文中,我们将深入探讨接口幂等性的概念、应用场景以及实现策略。 一、接口幂等性的定义 接口幂等性是指用户对同一操作发起的单个请求或多个请求,其结果始终保持一致,不会因多次请求而产生额外的影响。在支付...

    幂等矩阵的性质毕业论文.doc

    幂等矩阵的性质毕业论文 ...本论文对幂等矩阵的概念、主要性质、等价性命题、线性组合的相关性质、与其他特殊矩阵的关系等进行了详细的研究和讨论,为幂等矩阵的应用和研究提供了重要的参考价值。

    分布式事务-幂等

    分布式事务-幂等 在分布式系统中,幂等性(Idempotence)是一个重要的概念,它确保了同一个操作无论执行多少次,结果始终相同。...在设计和实现分布式事务时,充分理解和应用幂等性原则至关重要。

    3.2)幂等性以及消息的幂等性1

    幂等性是分布式系统设计中的一个重要概念,特别是在接口调用和消息传递中。它指的是对于同一个操作,无论执行一次还是多次,结果始终相同,不会产生额外的影响。这种特性在确保系统稳定性和一致性方面起着关键作用。...

    互联网API接口幂等设计

    在互联网服务开发中,API接口的设计是至关重要的。API接口幂等性是一个核心概念,尤其在高并发、数据一致性的场景下...在实际应用中,需要根据业务需求和场景选择合适的幂等性实现策略,并注意其可能带来的挑战和影响。

    java如何实现接口的幂等

    #### 二、幂等性概念解析 幂等性是指对于同一操作,无论执行多少次,其结果都是一致的。具体到接口设计中,它意味着无论客户端发送多少次相同的请求,服务器端的处理结果都应该是相同的,并且不会引发副作用。这种...

    高并发场景下如何保证接口幂等性?综合比较了防重令牌(token)、随机字符串(noncestr)、幂等表、防重表、数据库唯一索引

    在高并发场景中,接口幂等性是一个至关重要的概念,它确保同一个请求无论被调用多少次,结果始终一致,避免出现重复操作导致的数据不一致问题。本文将深入探讨几种常见的幂等性实现策略,包括防重令牌(Token)、...

    分布式系统的接口幂等性设计.docx

    幂等性源自数学概念,指的是一个操作或函数重复执行多次与执行一次的效果相同。在软件工程中,特别是分布式系统中,幂等性对于处理网络延迟、请求重复发送等问题至关重要。 HTTP协议中明确规定了GET方法是幂等的,...

    幂的运算性质及应用PPT学习教案.pptx

    通过课本上的例题和练习,如P51的例2、P54的Ex3、P59的Ex4等,学生可以巩固对这些性质的理解并提升应用能力。 最后,课后作业包括课本P59的Ex2和Ex4以及P82的Ex2,这些都是检验学习成果并深化理解的重要环节。总的...

    分布式系统一致性(ACID、CAP、BASE、二段提交、三段提交、TCC、幂等性)原理详解1

    在本文中,我们将深入探讨几种重要的理论和实践方法,包括ACID特性、CAP定理、BASE原则,以及几种常见的分布式事务处理协议:二段提交、三段提交和TCC(Try-Confirm-Cancel)模式,同时也会提到幂等性这一关键概念。...

    如何保证接口幂等性的方法

    ### 如何保证接口幂等性的方法 #### 1. 为什么要保证幂等性? 幂等性是指一个操作或指令无论被执行多少次,其结果都与只执行...开发人员应根据具体的应用需求选择合适的幂等性实现策略,以确保系统的稳定性和可靠性。

    幂函数的基本概念与性质PPT模板.pptx

    幂函数的基本概念与性质PPT模板 幂函数是数学中一种特殊的函数形式,形式为y = x^n,其中n为...了解幂函数的基本概念与性质、图像、应用和证明等方面的知识点,对于数学、物理、经济学等领域的研究和应用非常重要。

    44弹力设计篇之“幂等性设计”1

    幂等性设计是构建可靠系统的关键原则之一,特别是在分布式系统和微服务架构中。这个概念源于数学中的幂等函数,即一个函数无论执行多少次,其结果...在实际应用中,应根据系统需求和性能考虑选择合适的幂等性实现方案。

    基于springboot幂等性框架.zip

    幂等性是分布式系统中的一个重要概念,意味着一个操作无论执行多少次,其结果始终一致,不会因为重复调用而产生副作用。在SpringBoot应用中,这通常涉及到RESTful API的设计,确保请求的重复发送不会导致数据状态的...

    模逆与模幂计算与应用

    文章将详细介绍模逆元、模幂运算的概念及其算法实现,并通过两个具体的密码学应用实例——RSA加密算法和ElGamal加密算法来阐述这些数学工具的重要性。 ### 模逆元 模逆元是模数理论中的一个重要概念,通常在求解同...

Global site tag (gtag.js) - Google Analytics