最近跟朋友聊起这个话题,想深入了解下,于是学习总结,记录下来,此文章参考以下博客综合而来表示感谢:

http://blog.brucefeng.info/post/api-idempotent

http://825635381.iteye.com/blog/2276077

https://www.cnblogs.com/leechenxiang/p/6626629.html

1. 接口调用存在的问题

现如今我们的系统大多拆分为分布式SOA,或者微服务,一套系统中包含了多个子系统服务,而一个子系统服务往往会去调用另一个服务,而服务调用服务无非就是使用RPC通信或者restful,既然是通信,那么就有可能在服务器处理完毕后返回结果的时候挂掉,这个时候用户端发现很久没有反应,那么就会多次点击按钮,这样请求有多次,那么处理数据的结果是否要统一呢?那是肯定的!尤其在支付场景。

2. 什么是接口幂等性

接口幂等性就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。举个最简单的例子,那就是支付,用户购买商品后支付,支付扣款成功,但是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣款,返回结果成功,用户查询余额返发现多扣钱了,流水记录也变成了两条...,这就没有保证接口的幂等性

3. 什么情况下需要保证接口的幂等性

在增删改查4个操作中,尤为注意就是增加或者修改,

A: 查询操作

查询对于结果是不会有改变的,查询一次和查询多次,在数据不变的情况下,查询结果是一样的。select是天然的幂等操作

B: 删除操作

删除一次和多次删除都是把数据删除。(注意可能返回结果不一样,删除的数据不存在,返回0,删除的数据多条,返回结果多个,在不考虑返回结果的情况下,删除操作也是具有幂等性的)

C: 更新操作

修改在大多场景下结果一样,但是如果是增量修改是需要保证幂等性的,如下例子:

把表中id为XXX的记录的A字段值设置为1,这种操作不管执行多少次都是幂等的
   把表中id为XXX的记录的A字段值增加1,这种操作就不是幂等的

D: 新增操作

增加在重复提交的场景下会出现幂等性问题,如以上的支付问题

4. 那么如何设计接口才能做到幂等呢?

常见的两种实现方案:  1. 通过代码逻辑判断实现    2. 使用token机制实现      下面以支付系统为例,分别对接口的幂等性进行说明与实现

A: 通过代码逻辑判断实现接口幂等性,只能针对一些满足判断的逻辑实现,具有一定局限性

用户购买商品的订单系统与支付系统;订单系统负责记录用户的购买记录已经订单的流转状态(orderStatus),支付系统用于付款,提供如下接口,订单系统与支付系统通过分布式网络交互。

boolean pay(int accountid,BigDecimal amount) //用于付款,扣除用户的   

这种情况下,支付系统已经扣款,但是订单系统因为网络原因,没有获取到确切的结果,因此订单系统需要重试。由上图可见,支付系统并没有做到接口的幂等性,订单系统第一次调用和第二次调用,用户分别被扣了两次钱,不符合幂等性原则(同一个订单,无论是调用了多少次,用户都只会扣款一次)。如果需要支持幂等性,付款接口需要修改为以下接口:

boolean pay(int orderId,int accountId,BigDecimal amount)

通过orderId来标定订单的唯一性,付款系统只要检测到订单已经支付过,则第二次调用不会扣款而会直接返回结果:

在不同的业务中不同接口需要有不同的幂等性,特别是在分布式系统中,因为网络原因而未能得到确定的结果,往往需要支持接口幂等性。

随着分布式系统及微服务的普及,因为网络原因而导致调用系统未能获取到确切的结果从而导致重试,这就需要被调用系统具有幂等性。例如上文所阐述的支付系统,针对同一个订单保证支付的幂等性,一旦订单的支付状态确定之后,以后的操作都会返回相同的结果,对用户的扣款也只会有一次。这种接口的幂等性,简化到数据层面的操作:

update userAmount set amount = amount - 'value' ,paystatus = 'paid' where orderId= 'orderid' and paystatus = 'unpay'其中value是用户要减少的订单,paystatus代表支付状态,paid代表已经支付,unpay代表未支付,orderid是订单号。在上文中提到的订单系统,订单具有自己的状态(orderStatus),订单状态存在一定的流转。订单首先有提交(0),付款中(1),付款成功(2),付款失败(3),简化之后其流转路径如图:当orderStatus = 1 时,其前置状态只能是0,也就是说将orderStatus由0->1 是需要幂等性的
update Order set orderStatus = 1 where OrderId = 'orderid' and orderStatus = 0

当orderStatus 处于0,1两种状态时,对订单执行0->1 的状态流转操作应该是具有幂等性的。这时候需要在执行update操作之前检测orderStatus是否已经=1,如果已经=1则直接返回true即可。

但是如果此时orderStatus = 2,再进行订单状态0->1 时操作就无法成功,但是幂等性是针对同一个请求的,也就是针对同一个requestid保持幂等。

这时候再执行

 update Order set orderStatus = 1 where OrderId = 'orderid' and orderStatus = 0

接口会返回失败,系统没有产生修改,如果再发一次,requestid是相同的,对系统同样没有产生修改。

B: 使用token机制实现接口幂等性,通用性强的实现方法

token机制实现步骤:

1. 生成全局唯一的token,token放到redis或jvm内存,token会在页面跳转时获取.存放到pageScope中,支付请求提交先获取token

2. 提交后后台校验token,执行提交逻辑,提交成功同时删除token,生成新的token更新redis ,这样当第一次提交后token更新了,页面再次提交携带的token是已删除的token后台验证会失败不让提交

     token特点:   要申请,一次有效性,可以限流

注意: redis要用删除操作来判断token,删除成功代表token校验通过,如果用select+delete来校验token,存在并发问题,不建议使用

什么是接口,为什么要做接口,怎么调用接口相关推荐

  1. 全网最全,接口自动化测试怎么做的?精通接口自动化测试详解

    目录:导读 一.前言 二.接口自动化测试的 "能 " 1.接口自动化的目标 2.接口自动化 Case 用例设计原则 3.接口自动化用例定时跑 三.接口自动化测试的 "不能 ...

  2. 调用招商银行接口(手把手教程,附调用接口工具类)

    手把手教你调用招商银行接口 一.下载示例代码 二.申请测试环境.或者生产环境加入到示例代码 三.调用招商银行接口参数拼装 四.调用接口测试 五.最后,贴上我自己改造过的工具类 1.这是获取银行环境参数 ...

  3. api 接口开发理论 在php中调用接口以及编写接口

    如: http://localhost/openUser.php?act=get_user_list&type=json 在这里openUser.php相当于一个接口,其中get_user_l ...

  4. 通过feign调用接口

    feign是声明式WEbService客户端,它的使用方法是定义一个接口,在接口上添加注解,即可完成对服务提供方接口的绑定,Feign可以与Ribbon组合实现负载均衡.它让调用接口更加容易. Dem ...

  5. sm750显卡驱动linux版,M.2接口也能做显卡,慧荣科技提供图形显示芯片支持

    原标题:M.2接口也能做显卡,慧荣科技提供图形显示芯片支持 在人们的认知中, M.2接口基本都是以小巧,高集成度出现的.主要用于安装M.2形态的固态硬盘,以及NGFF接口的WiFi无线网卡.不过最近, ...

  6. php 做支付宝接口 防钓鱼时间戳,ThinkPHP实现支付宝接口功能

    最近做系统,需要实现在线支付功能,毫不犹豫,选择的是支付宝的接口支付功能.这里我用的是即时到帐的接口,具体实现的步骤如下:一.下载支付宝接口包下载地址:https://b.alipay.com/ord ...

  7. 做城市/景区慢直播,EasyNVR平台如何调用接口实现MP3音频上传?

    EasyNVR平台可拓展性强.开放度高,部署轻松.视频能力灵活,平台支持网络探测.设备接入.视频处理与分发.直播与录像.云存储.回放.设备状态监测.定时快照.告警等功能.在项目上,EasyNVR也能支 ...

  8. c语言接口测试方法,如何做API接口测试?

    经常有后端开发会问,后端接口都测试什么?怎么测?简单梳理了一下接口测试的相关内容: 测试什么? 素材来源于网络,侵删. 怎么测? 目前后端调用主要是基于HTTP协议的接口,测试时主要有两种方法: 工具 ...

  9. 请教!C# 做钉钉回调接口,怎么个流程或处理?感谢 !

    C# 做钉钉回调接口,怎么个流程或处理?感谢 事件回调 回调是开发者在钉钉开放平台注册一个HTTP接口,并订阅相关的事件,当事件发生时,钉钉会主动调用开发者注册的HTTP接口,推送对应的事件信息.比如 ...

  10. 个人要做量化获得交易接口的方法有哪些?

    如果我们想要做量化交易,那肯定就要用到量化交易接口了,不过券商官方接口门槛很高,如果我们达不到,有什么其他的方法可以获得交易接口呢? 使用软件商提供的交易接口绝大部分投资者其实都没有千万证券资产,如果 ...

最新文章

  1. 【面试】我是如何面试别人List相关知识的,深度有点长文
  2. Win7中aero peek的关闭与开启
  3. PHP HashTable总结
  4. 魔力宝贝服务器列表修改,魔力宝贝修改代码一览表GM.docx
  5. Filling Shapes
  6. spring mvc 接收List数组类型参数
  7. electron 5.0.3版本 改动的地方
  8. 3分钟让你轻松了解CRM
  9. SQLServer优化资料整理(二)
  10. palapaweb的mysql无法运行_Mysql 服务无法启动 服务没有报告任何错误
  11. matlab2c使用c++实现matlab函数系列教程-load函数
  12. Spark自定义排序
  13. (3)《Head First HTML与CSS》学习笔记---CSS入门
  14. Atiti. Php Laravel 5.1 环境搭建以及  error 排除
  15. 三星研发的另一种解读
  16. 合肥工业大学机器人技术期末_机器人技术试题及答案.doc
  17. TestStand系统框架简介
  18. 软件工程实践 Blog17
  19. 大数据时代,数据的应用场景
  20. 色色教你玩魔方(傻瓜式全程图解教学)

热门文章

  1. Axure学习笔记(十五)-类似于某宝商品界面的实现(利用中继器)
  2. 北京无人驾驶_无需预约!在北京的朋友可以一键呼叫“无人驾驶”出租车了
  3. 汇川工业互联网邀您莅临第十四届南京软博会
  4. Python raise用法
  5. 基于MegEngine实现图像分类【附部分源码及模型】
  6. MQL5源码:智能交易脚本EA结构解读
  7. 操作系统9道经典PV操作
  8. HarmonyOS应用开发-基本控件
  9. 英文长句学习的Python分析法
  10. 指数分布的推导与理解