背景,接口请求有成功,失败和超时三种场景,前面两种都有明显的结果可明确处理,但超时的不好直接处理,因为不确定业务方是否成功。
三种处理方案
超时结果给用户,让用户选择是否重试。缺点,业务无法区分这个请求是因为失败导致还是新请求。
查询业务的处理结果,然后根据结果进行处理。缺点,需要明确知道业务方的结果数据是可查的。
调用方发现失败后直接重试。缺点:需要接口支持幂等。
进一步按照时间敏感分析
敏感,超时返回给用户,让用户知道状态,决定是否重试。比如移动端的直播,抢购等
不敏感,比如定时任务或者异步任务,用后面两种方式
查结果的,业务方要做支持,限制比较明显
接口幂等的,要做通用性的幂等设计
幂等含义
同一个接口,同一个数据,请求多次,业务只执行一次
怎么确定是否同一请求,因为参数完全一致,也就是区分是否重试,增加幂等号
幂等号同代表出现过,而出现过的肯定是重复请求。这就相当于假如只有一个请求,没有发起过没有标识,发起过加个标识,你请求过了,这次是重试。
设计的难点在于全局统一
业务敏感型,比如注册的业务,用户手机号可以是幂等号,但这种不通用
通用性设计
幂等流程设计
调用方请求发出前增加幂等号
业务方检查幂等号是否存在,区别处理
幂等的非功能设计
易用,与具体业务无关,维护在框架层,加中间件或者配置
低时延,因为属于增长请求链路,所以生成获取并增加幂等号的过程要准时快
容错性,尽量不因为幂等异常导致业务不可用
场景
微信消息重发
ngnix重试
电脑重启
秒杀
轮询重试
心跳检查
支付和退款是否重试
幂等设计,用户token,业务主键
我的一个小案例(使用方案二)
电商订单的微信支付,当时唤起微信支付后不确定微信支付是否成功,也不确定我们的业务方数据是否成功。所以当时和后端定的方案是,先把流程确认为每次下单先生成订单号,然后用订单号发起支付,微信的异步支付如果成功会修改业务方的支付状态,而前端界面在确认唤起后端并生成订单号并唤起微信支付后,只要做订单支付状态的轮询即可,连续三次巡逻,每次一秒,如果成功,那么到订单成功页,如果失败,那么到购买页,重新下单,并把历史订单作废,与此同时,历史订单针对微信超时或者异常未改变支付状态的数据也会对其订单号增加定时轮询,并做软删除和异常记录。
案例支付背景,由于我们产品的特殊性,每人每商品限制1,所以可在业务方接口设置再次请求时,购买页直接提示已在购买状态,不可重复购买。