搜索

首页  >  问答  >  正文

java - 调用多个第三方接口哪一种方案更好?

目的

用户在下单的时候,会调用我们的后台服务器,我们的后台服务器又会根据不同渠道调用第三方下单接口,完成整个下单流程,但是第三方下单接口可能突然出问题或者不支持,所以目前我们每一种渠道都配置了好几种备用的下单接口,尽可能提高用户下单成功率。

问题

想选择一种更好的方案,来实现同样的效果。

方案

例如: 下单时type = 1 ,后台支持该类型的第三方下单接口有A,B,C。可能A,B,C会突然出问题,或者不支持,或者不稳定等问题。

  1. 每次下单轮询A,B,C 3个接口,直到成功为止,此时记录下失败的渠道 ,例如A,当A最近M分钟的失败次数大于N次,则下次下单的时候,只用轮询B,C接口。当最近X分钟内失败的渠道A又开始成功了并且成功次数大于X次,则下单的时候又可以轮询A,B,C,其中A,B,C轮询次数按照优先级排序。
    分析:每次都要轮询,但可以保证例如 X= 2 A失败了2次,此时我可以轮询到B去下单,而不会直接失败。

  2. 每次下单前直接确定一个接口A或者B或者C,根据优先级最高且最近M分钟内失败次数没有超过N次的。
    分析:如果N为10次,那么第11次的时候,才会选择一个合适的渠道,例如B。之所以是N次才剔除掉,是因为避免偶然失败情况。

  3. 有没更好的方式,解决多渠道(就类似上面可用的下单接口用A,B,C)下单的问题,尽可能提高下单的成功率,尽可能尝试更多的机会,尽可能让用户成功支付,尽可能预知第三方接口的问题(接口改变、服务器挂了、处理慢、业务类型不支持了等问题)

求大神分享经验。。。

========================================update 2016-7-7============================

  1. 需要同步返回给前端是否成功

  2. 第三方暂时没提供 比如某个业务类型不支持的错误码

其实大家的回答已经比较接近实际场景了~

感谢~

PHP中文网PHP中文网2802 天前1320

全部回复(7)我来回复

  • 怪我咯

    怪我咯2017-04-18 09:31:21

    没太明白你描述的渠道A,B,C和接口A,B,C有何区别.我就当做是一个东西吧.

    你遇到的问题,更接近现在互联网服务中经常遇到的服务降级问题, 即:当一个服务依赖的另一服务不可用时,调用fallback备选逻辑.

    这种熔断器模式可能会满足你的需求:

    • 当服务不可用(错误率到达一定阈值)时,自动降级到备选服务.

    • 在一定时间窗过后, 重新调用之前不可用的服务.如果连续调用成功, 则恢复, 如果调用失败, 则时间窗口内不再调用失败服务.

    你需要一个熔断器组件,来实现自动降级和自动恢复的功能:

    1. 定义降级的策略, 比如:调用错误率达到50%以上开始降级

    2. 定义错误率收集的时间窗长度. 比如:每1分钟,重新评估请求的错误率.

    3. 定义服务超时时间, 防止阻塞的请求占用更久的线程资源.

    4. 定义使用线程池隔离服务调用, 避免服务雪崩,其中一个接口不可用,并且资源全被它阻塞, 导致其他所有接口不可用

    5. 收集备选接口的调用成功率, 并在调用服务时根据成功率派发请求.

    可以使用Netflix的Hystrix来实现, 以上的1,2,3,4, 相当简单.

    第5点需要你自己实现.

    回复
    0
  • 阿神

    阿神2017-04-18 09:31:21

    楼主的业务场景,在平时的工作中确实没有遇到过,但是可以类比分布式服务系统.

    1. A,B,C可以类比为三个下单服务,后台服务器会调用下单服务A,B,C可以类比为三个下单服务,后台服务器会调用下单服务

    2. 根据三个接口的下单失败率,比如A > B > C,那么就可以把请求先路由到A下单服务上,如果下单失败自动重试N次,N次以后还是失败的话,将A服务降级(下一个订单过来会先路由到B),然后将请求转至B,B的策略和A一样

    3. 启一个后台的线程,去定期探活,比如发现A被降级了,就不定期的去尝试调用A接口下单(需要A接口提供一个单独的探活接口),如果发现A通了(也可以按照失败率来判断),那么可以将A上线,那么接下来的请求被再次首先会路由到A服务器上

    4. 可能我这个方案和题主的方案1或者方案二是差不多的思路,但是楼主的方案1和方案2看起来很模糊(看的不是很懂)

    5. 这种对接第三方接口的,并且接口不稳定的,建议用户下单动作调用服务器,服务器可以先把这个请求的一些参数储存起来(放MQ或者数据库),后台可以启动线程慢慢把这些订单,通过A,B,C

    6. 根据三个接口的下单失败率,比如A > B > C,那么就可以把请求先路由到A下单服务上,如果下单失败自动重试N次,N次以后还是失败的话,将A服务降级(下一个订单过来会先路由到B),然后将请求转至B,B的策略和A一样

    启一个后台的线程,去定期探活,比如发现A被降级了,就不定期的去尝试调用A接口下单(需要A接口提供一个单独的探活接口),如果发现A通了(也可以按照失败率来判断),那么可以将A上线,那么接下来的请求被再次首先会路由到A服务器上🎜🎜 🎜🎜可能我这个方案和题主的方案1或者方案二是差不多的思路,但是楼主的方案1和方案2看起来很模糊(看的不是很懂)🎜🎜 🎜🎜这种对接第三方接口的,并且接口不稳定的,建议用户下单动作调用服务器,服务器可以先把这个请求的一些参数储存起来(放MQ或者数据库),后台可以启动线程慢慢把这些订单,通过A,B,C接口推送,而返回给用户的提示可以提示下单中.这里采用异步的方式,主要的一个好处就是如果接口全部挂了,同步方式给用户的感觉就是一直下单失败,而异步可以隔一段时间重试,当第三方出现:第三方接口的问题(接口改变、服务器挂了、处理慢、业务类型不支持了等问题)的时候,容错率更加高🎜🎜 🎜🎜重试机制有一个坑,可能下单成功了,但是接口返回的是失败,所以这里可能需要依赖第三方商家的去重策略了🎜🎜 🎜

    回复
    0
  • ringa_lee

    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机制,自动平衡使用情况来调整最优策略。

    回复
    0
  • 高洛峰

    高洛峰2017-04-18 09:31:21

    题主也知道不管用什么方法都没法避免调用失败的问题,从大部分的回答里面也能看到,如果要在最少的调用次数下调用成功的话,就需要根据以往的调用结果对A B C分配优先级,在调用时采用策略。上面回答的也挺多的,我再提点思路,题主可以人为的分析一下接口调用失败是呈什么分布,比如对于某个接口而言是不是失败一次之后会连续失败,还是只是偶尔呈点状失败,又比如是不是你对某个调用太频繁的时候才容易出现失败。根据这些再做出来合理的策略估计效果会更接近你所希望的。

    回复
    0
  • 迷茫

    迷茫2017-04-18 09:31:21

    使用activemq我觉得应该可以满足你

    回复
    0
  • 迷茫

    迷茫2017-04-18 09:31:21

    如果客户对下单的响应有非常高的要求的话,你就按照第一种方法,但是可以三个同时下单,只要有一个成功了,另外两个就相应取消,不过这种方法对第三方接口有要求,而且第三方接口的各种问题可能影响你也业务服务,比如接口没响应的话会导致你的业务服务处理能力指数级下降。
    如果客户对下单响应的时间不是非常敏感的话,可以用MQ来做,把下单任务丢给MQ,MQ的消费者可以去下单,成功后将结果回调业务服务。

    回复
    0
  • PHP中文网

    PHP中文网2017-04-18 09:31:21

    楼主你除了第二种那个方案,其他的方案做要出问题啊,用户绝对要被重复扣款,比如说你调用A渠道,这个时候A渠道如果出现超时等错误,但是这个情况有可能用户已经被扣款了,俗称掉单,(有时你冲正都退不了款,只能发起退货请求),你只能通过补单查询看看用户是否付款成功,有一定的延迟,你这个时候再把用户分发到B渠道,用户又被扣款一次了,这在三方支付中经常出现的问题,我们的做法是对下游的渠道做个统计,优先选择渠道质量好的进行分发,想楼主这样设计很容易出问题

    ps:楼上的回答大部分都没做过三方支付,不可能像楼主这样设计,三方支付不可能像分布式服务那样调用接口做的,涉及到钱的问题很敏感,一不小心公司账户上面就会出现短款,白白损失钱

    回复
    0
  • 取消回复