目录

接口幂等性的含义

幂等性原本是数学中的含义,表达式的是N次变换与1次变换的结果相同。
而RESTFul API中的幂等性是指调用某个方法1次或N次对资源产生的影响结果都是相同的,需要特别注意的是:这里幂等性指的是对资源产生的影响结果,而不是调用HTTP方法的返回结果。
举个例子,RESTFul API中的GET方法是查询资源信息,不会对资源产生影响,所以它是符合幂等性的,但是每次调用GET方法返回的结果有可能不同(可能资源的某个属性在调用GET方法之前已经被其他方法修改了)。
实际上,在分布式架构中的API幂等性不仅仅针对RESTFul接口,而是对所有类型的接口适用,目的是为了确保调用1次或N次接口时对资源的影响结果都是相同的。

接口符合幂等性有什么用处

接口的幂等性确保了无论调用1次还是N次对资源的影响都是相同的,这在某些场合下是非常有用的。
举个例子,有这样一个接口方法:pay(long account, int money),该方法用于银行卡扣款支付,参数account为账户ID,money为需要扣除的钱数。当用户从网页上点击支付按钮时,在该方法的实现逻辑中需要从指定账户中扣除对应的商品价钱。如果支付操作已经成功执行,但是响应消息因为某种原因未能及时返回给客户端,这时候给用户的体验是可能是未支付成功,如果此时再次点击支付按钮,那么将再一次执行该方法,结果可能会导致用户只买了一件商品却花了双份的钱,这当然是不合理的。整个流程如下图所示:

当然,就上述例子的场景,为了避免用户重复支付,是可以通过别的方式解决的,比如:分布式事务,或者根据支付状态提示给予用户进行提示等等。
但是,如果引入了分布式事务,那么将带来实现上的复杂性,而且会影响到接口性能;而采取提示信息的方式并不能百分之百确保用户不会重复支付,存在一定的风险。而如果接口符合幂等性,即:对同一个订单无论是执行一次支付还是多次支付,在服务端都确保只会扣一次款,那么既不需要引入分布式事务的复杂性,也能从根本上解决重复支付的问题,这也就是接口符合幂等性的价值所在。

总而言之,接口符合幂等性在可以降低系统实现的复杂性,并能保证资源状态的一致性。

HTTP方法的幂等性与安全性

RESTFul风格的接口设计本质上使用的是HTTP协议方法,因此,RESTFul接口方法的幂等性指的就是HTTP方法的幂等性。
常用的HTTP方法有:OPTIONS(获取服务器信息),HEAD(请求资源首部信息),GET(获取资源),POST(创建资源),PUT(更新资源全部信息),PATCH(更新资源部分信息),DELETE(删除资源)。那么,这些HTTP方法的幂等性又是什么样的呢?
除了幂等性之外,HTTP方法的安全性是指不对资源产生修改。
如下是常用HTTP方法的幂等性和安全性总结:

HTTP方法名称 是否幂等 是否安全
OPTIONS Y Y
HEAD Y Y
GET Y Y
PUT Y N
DELETE Y N
POST N N
PATCH N N

从上述表格中可以看出,HTTP方法的幂等性和安全性并不是同一个概念,如下是对个各个方法的幂等性和安全性解释:

  • OPTIONS方法常常用于获取服务器信息,不会对资源产生影响,也不会对资源进行修改,因此它是幂等的也是安全的;OPTIONS方法最常见的场景是在浏览器的跨域请求中,如果浏览器发起的是一个跨域访问的API(不论是GET方法还是POST方法),再真正发送业务的GET或POST方法之前会发送一个OPTIONS方法从服务端获取信息,从服务器返回的信息中得知该请求是否支持跨域访问,从而决定下一步是否能成功发送真正的业务请求。
  • HEAD方法用于请求资源的头部信息,不会资源产生影响,也不会对资源进行修改,因此它是幂等的也是安全的。
  • GET方法用于获取资源信息,虽然可能每次返回的结果都不相同,但是GET方法本身不会对资源产生影响,在RESTFul语义里GET方法也不会修改资源,因此它是幂等的,也是安全的。
  • PUT方法在RESTFul语义里表示对资源进行全量更新,因此调用1次或N次的结果都是一致的,所以它是幂等的,但不是安全的。
  • DELETE方法用于删除资源,调用1次或N次的结果都是相同的,因此是幂等的,但不是安全的。
  • POST方法在RESTFul语义里表示新建资源,显然调用1次与调用N次的结果不同(调用1次新建1个资源,调用N次新建N个资源),因此不是幂等的,同时也不是安全的。
  • PATCH方法在RESTFul语义里表示对资源的局部更新,因此不能保证调用1次与调用N次的结果相同(如:被更新的资源某个属性随着不同的调用次数在变化),所以不是幂等的,同时也不是安全的。

如何设计符合幂等性的接口

设计幂等性接口的关键在于保证接口不论是被调用1次还是N次,它对资源所产生的影响都是相同的。
从上述HTTP方法的幂等性总结中可以得知,HTTP协议的POST和PATCH方法都不是幂等性的(但是我们却经常会在RESTFul接口中使用到它们),那是否就意味中无法将POST和PATCH方法设计为幂等性接口了呢?答案显然是否定的。在上述例子中,可以将订单ID也作为方法参数之一,如:pay(long account, int money, long order),这样在服务端确保一个订单只会被支付一次(订单号是全局唯一的),那么无论该方法被调用1次还是N次结果都是一样的,也就保证了接口的幂等性。当然,在哪些没有订单号的场景,可以为接口操作生成一个全局唯一的处理号ID,并把该处理号ID作为方法参数之一,这样在服务端确保一个处理号ID只会被执行一次就保证了接口的幂等性。
符合幂等性的接口调用流程描述如下图所示:

写在最后

虽然说设计符合幂等性的接口在某些场合可以降低系统的复杂性(如:可以不用引入分布式事务),但是并非在所有场合的问题都能通过幂等性接口解决,在必要的时候依然需要引入分布式事务处理这样的框架。我们不要也不能把接口幂等性作为万能的解决办法,但是,我们在设计接口时尽量考虑符合幂等性处理是非常有价值的。

【参考】
http://blog.720ui.com/2016/restful_idempotent/ 如何理解RESTful的幂等性
https://www.cnblogs.com/weidagang2046/archive/2011/06/04/idempotence.html 理解HTTP幂等性
https://sofish.github.io/restcookbook/http%20methods/idempotency/ RESTful 手册

细说RESTful API之幂等性的更多相关文章

  1. 细说RESTFul API之版本管理

    目录 接口实现版本管理的意义 如何实现接口的版本管理 项目实战 接口实现版本管理的意义 API版本管理的重要性不言而喻,对于API的设计者和使用者而言,版本管理都有着非常重要的意义. 首先,对于API ...

  2. 细说RESTful API之文档管理

    目录 API文档格式 文档管理方式 基于注解实现,代码和文档在一起 Swagger Api2Doc 基于API测试工具生成 Postman rest-client 独立编写文档 RAP DOCleve ...

  3. 通过一组RESTful API暴露CQRS系统功能

    命令和查询责任分离(CQRS)是由Greg Young提出的一种将系统的读(查询).写(命令)操作分离为两种独立子系统的架构模式.命令通常是异步执行的,并存储在一个事务型数据库中,而读操作则通常是最终 ...

  4. 利用 Django REST framework 编写 RESTful API

    利用 Django REST framework 编写 RESTful API Updateat 2015/12/3: 增加 filter 最近在玩 Django,不得不说 rest_framewor ...

  5. 拿nodejs快速搭建简单Oauth认证和restful API server攻略

    拿nodejs快速搭建简单Oauth认证和restful API server攻略:http://blog.csdn.net/zhaoweitco/article/details/21708955 最 ...

  6. HTTP methods 与 RESTful API

    Note GET, primarily used to select resources. Other options for an API method include: POST, primari ...

  7. Restful API的设计规范

    原文:https://blog.csdn.net/u013063153/article/details/72828164 本文总结了 RESTful API 设计相关的一些原则,只覆盖了常见的场景.有 ...

  8. restful API 规范(转)

    1. URI URI 表示资源,资源一般对应服务器端领域模型中的实体类. URI规范 不用大写: 用中杠-不用下杠_: 参数列表要encode: URI中的名词表示资源集合,使用复数形式. 资源集合 ...

  9. 我所理解的Restful API最佳实践

    一直在公司负责API数据接口的开发,期间也遇到了不小的坑,本篇博客算是做一个小小的记录. 1. 不要纠结于无意义的规范    在开始本文之前,我想先说这么一句:RESTful 真的很好,但它只是一种软 ...

随机推荐

  1. c# 调用 C++ dll 传入传出类型对应说明(转)

    由于经常使用C#调用 非托管C++ dll 操作一下硬件,出现传入传出类型的问题,现整理了C++ dll 类型与 C#类型对应关系: //C++中的DLL函数原型为        //extern & ...

  2. discuz x3.3标题的最少字数限制设置方法

    Discuz帖子标题默认字数最多是80个字节,却没有最少的字节限制.最近看到很多站长想限制一下帖子标题最少字数,不管是利于seo,还是禁止灌水,都有必要.为此把设置方法发上来分享. 1.找到并打开st ...

  3. 非阻塞IO的实现方式

    1.状态轮询: 2.状态订阅: 3.完成回掉:

  4. 一种动态的样式语言--Less 之 命名空间

    LESS 命名空间 如果想更好的组织CSS或者单纯是为了更好的封闭,将一些变量或者混合模块打包起来,你像下面这样在#bundle中定义一些属性集之后可以重复使用: #bundle{ .button() ...

  5. python - django 项目部署 Ubuntu 服务器后接口访问一直 502 问题

    问题描述:最近有了一台 Ubuntu 的服务器,然后准备部署个项目,结果没想到部署的过程跟用 Centos 的时候还有点不一样,最后一步我是卡在了 uwsgi 这里,访问一直502,且可以访问项目的静 ...

  6. CVE-2017-7494复现 Samba远程代码执行

    Samba是在Linux和Unix系统上实现Smb协议的一个免费软件,由服务器及客户端程序构成,Samba服务对应的TCP端口有139.445等.Smb一般作为文件共享服务器,专门提供Linux与Wi ...

  7. 使用jenkins exporter 监控jenkins 构建任务

    jenkins 提供了rest api,我们可以基于rest api 暴露prometheus metrics,社区已经有了好多 开源的实现了,使用起来也比较方便,以下集成几个进行简单的测试 环境准备 ...

  8. netflix conductor 2.x 版本新功能简单说明

    netflix conductor 2.x 已经发布很长时间了,同时官方也发布了关于2.x 新特性的说明,当前github 行的release 版本为2.14.4 新特性 grpc 框架支持 一个可选 ...

  9. Tomcat8.x的安装与启动

    Tomcat是企业网站的服务器,大多都用于中.小型网站开发和学习开发JSP应用程序中.笔者也是开始学习,下面介绍Tomcat8.x的安装步骤. 进入Tomcat官网,点击左边的download目录下的 ...

  10. LOJ3097 SNOI2019 通信 题解

    题目链接 费用流,当建边需要依靠位置和权值两个偏序关系时,可以用cdq分治优化建边. 代码: #include<bits/stdc++.h> using namespace std; #d ...