用户在下单的时候,会调用我们的后台服务器,我们的后台服务器又会根据不同渠道调用第三方下单接口,完成整个下单流程,但是第三方下单接口可能突然出问题或者不支持,所以目前我们每一种渠道都配置了好几种备用的下单接口,尽可能提高用户下单成功率。
想选择一种更好的方案,来实现同样的效果。
例如: 下单时type = 1 ,后台支持该类型的第三方下单接口有A,B,C。可能A,B,C会突然出问题,或者不支持,或者不稳定等问题。
每次下单轮询A,B,C 3个接口,直到成功为止,此时记录下失败的渠道 ,例如A,当A最近M分钟的失败次数大于N次,则下次下单的时候,只用轮询B,C接口。当最近X分钟内失败的渠道A又开始成功了并且成功次数大于X次,则下单的时候又可以轮询A,B,C,其中A,B,C轮询次数按照优先级排序。
分析:每次都要轮询,但可以保证例如 X= 2 A失败了2次,此时我可以轮询到B去下单,而不会直接失败。
每次下单前直接确定一个接口A或者B或者C,根据优先级最高且最近M分钟内失败次数没有超过N次的。
分析:如果N为10次,那么第11次的时候,才会选择一个合适的渠道,例如B。之所以是N次才剔除掉,是因为避免偶然失败情况。
有没更好的方式,解决多渠道(就类似上面可用的下单接口用A,B,C)下单的问题,尽可能提高下单的成功率,尽可能尝试更多的机会,尽可能让用户成功支付,尽可能预知第三方接口的问题(接口改变、服务器挂了、处理慢、业务类型不支持了等问题)
求大神分享经验。。。
========================================update 2016-7-7============================
需要同步返回给前端是否成功
第三方暂时没提供 比如某个业务类型不支持的错误码
其实大家的回答已经比较接近实际场景了~
感谢~
怪我咯2017-04-18 09:31:21
没太明白你描述的渠道A,B,C和接口A,B,C有何区别.我就当做是一个东西吧.
你遇到的问题,更接近现在互联网服务中经常遇到的服务降级问题, 即:当一个服务依赖的另一服务不可用时,调用fallback备选逻辑.
这种熔断器模式可能会满足你的需求:
当服务不可用(错误率到达一定阈值)时,自动降级到备选服务.
在一定时间窗过后, 重新调用之前不可用的服务.如果连续调用成功, 则恢复, 如果调用失败, 则时间窗口内不再调用失败服务.
你需要一个熔断器组件,来实现自动降级和自动恢复的功能:
定义降级的策略, 比如:调用错误率达到50%以上开始降级
定义错误率收集的时间窗长度. 比如:每1分钟,重新评估请求的错误率.
定义服务超时时间, 防止阻塞的请求占用更久的线程资源.
定义使用线程池隔离服务调用, 避免服务雪崩,其中一个接口不可用,并且资源全被它阻塞, 导致其他所有接口不可用
收集备选接口的调用成功率, 并在调用服务时根据成功率派发请求.
可以使用Netflix的Hystrix来实现, 以上的1,2,3,4, 相当简单.
第5点需要你自己实现.
阿神2017-04-18 09:31:21
楼主的业务场景,在平时的工作中确实没有遇到过,但是可以类比分布式服务系统.
A,B,C
可以类比为三个下单服务,后台服务器会调用下单服务A,B,C
可以类比为三个下单服务,后台服务器会调用下单服务
根据三个接口的下单失败率,比如A > B > C
,那么就可以把请求先路由到A
下单服务上,如果下单失败自动重试N
次,N
次以后还是失败的话,将A
服务降级(下一个订单过来会先路由到B
),然后将请求转至B
,B
的策略和A
一样
启一个后台的线程,去定期探活,比如发现A
被降级了,就不定期的去尝试调用A
接口下单(需要A
接口提供一个单独的探活接口),如果发现A
通了(也可以按照失败率来判断),那么可以将A
上线,那么接下来的请求被再次首先会路由到A
服务器上
可能我这个方案和题主的方案1或者方案二是差不多的思路,但是楼主的方案1和方案2看起来很模糊(看的不是很懂)
这种对接第三方接口的,并且接口不稳定的,建议用户下单动作调用服务器,服务器可以先把这个请求的一些参数储存起来(放MQ
或者数据库),后台可以启动线程慢慢把这些订单,通过A,B,C
A > B > C
,那么就可以把请求先路由到A
下单服务上,如果下单失败自动重试N
次,N
次以后还是失败的话,将A
服务降级(下一个订单过来会先路由到B
),然后将请求转至B
,B
的策略和A
一样
A
被降级了,就不定期的去尝试调用A
接口下单(需要A
接口提供一个单独的探活接口),如果发现A
通了(也可以按照失败率来判断),那么可以将A
上线,那么接下来的请求被再次首先会路由到A
服务器上🎜🎜
🎜🎜可能我这个方案和题主的方案1或者方案二是差不多的思路,但是楼主的方案1和方案2看起来很模糊(看的不是很懂)🎜🎜
🎜🎜这种对接第三方接口的,并且接口不稳定的,建议用户下单动作调用服务器,服务器可以先把这个请求的一些参数储存起来(放MQ
或者数据库),后台可以启动线程慢慢把这些订单,通过A,B,C
接口推送,而返回给用户的提示可以提示下单中.这里采用异步的方式,主要的一个好处就是如果接口全部挂了,同步方式给用户的感觉就是一直下单失败,而异步可以隔一段时间重试,当第三方出现:第三方接口的问题(接口改变、服务器挂了、处理慢、业务类型不支持了等问题)的时候,容错率更加高🎜🎜
🎜🎜重试机制有一个坑,可能下单成功了,但是接口返回的是失败,所以这里可能需要依赖第三方商家的去重策略了🎜🎜
🎜ringa_lee2017-04-18 09:31:21
泻药。
这个问题你换种角度考虑其实无非就是个负载均衡
的问题,不同的是,这里的因素比较随机,并不能直观的去获得负载情况,这种情况下只能自己去设置rank机制了。负载均衡
的问题,不同的是,这里的因素比较随机,并不能直观的去获得负载情况,这种情况下只能自己去设置rank机制了。
机制如下,假设保存最近100次的下单成功队列
机制如下,假设保存最近100次的下单成功队列
其中A的可用性为53%,B的可用性为30%,C的可用性为17%。那么就以A>B>C的优先级来依次轮询。假如此次A失败了,而B成功了。则可用性变为52%,31%,17%。
直至B的可用性超越A,则优先B,此方法可实现自动rank机制,自动平衡使用情况来调整最优策略。
高洛峰2017-04-18 09:31:21
题主也知道不管用什么方法都没法避免调用失败的问题,从大部分的回答里面也能看到,如果要在最少的调用次数下调用成功的话,就需要根据以往的调用结果对A B C分配优先级,在调用时采用策略。上面回答的也挺多的,我再提点思路,题主可以人为的分析一下接口调用失败是呈什么分布,比如对于某个接口而言是不是失败一次之后会连续失败,还是只是偶尔呈点状失败,又比如是不是你对某个调用太频繁的时候才容易出现失败。根据这些再做出来合理的策略估计效果会更接近你所希望的。
迷茫2017-04-18 09:31:21
如果客户对下单的响应有非常高的要求的话,你就按照第一种方法,但是可以三个同时下单,只要有一个成功了,另外两个就相应取消,不过这种方法对第三方接口有要求,而且第三方接口的各种问题可能影响你也业务服务,比如接口没响应的话会导致你的业务服务处理能力指数级下降。
如果客户对下单响应的时间不是非常敏感的话,可以用MQ来做,把下单任务丢给MQ,MQ的消费者可以去下单,成功后将结果回调业务服务。
PHP中文网2017-04-18 09:31:21
楼主你除了第二种那个方案,其他的方案做要出问题啊,用户绝对要被重复扣款,比如说你调用A渠道,这个时候A渠道如果出现超时等错误,但是这个情况有可能用户已经被扣款了,俗称掉单,(有时你冲正都退不了款,只能发起退货请求),你只能通过补单查询看看用户是否付款成功,有一定的延迟,你这个时候再把用户分发到B渠道,用户又被扣款一次了,这在三方支付中经常出现的问题,我们的做法是对下游的渠道做个统计,优先选择渠道质量好的进行分发,想楼主这样设计很容易出问题
ps:楼上的回答大部分都没做过三方支付,不可能像楼主这样设计,三方支付不可能像分布式服务那样调用接口做的,涉及到钱的问题很敏感,一不小心公司账户上面就会出现短款,白白损失钱