首頁  >  問答  >  主體

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中文网2763 天前1297

全部回覆(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可以類比為三個下單服務,後台伺服器會呼叫下單服務

    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或資料庫),後台可以啟動線程慢慢把這些訂單,通過MQ或者数据库),后台可以启动线程慢慢把这些订单,通过A,B,C接口推送,而返回給用戶的提示可以提示下單中.這裡採用異步的方式,主要的一個好處就是如果接口全部掛了,同步方式給用戶的感覺就是一直下單失敗,而異步可以隔一段時間重試,當第三方出現:第三方介面的問題(介面改變、伺服器掛了、處理慢、業務類型不支援了等問題)的時候,容錯率更加高

    6. 重試機制有一個坑,可能下單成功了,但是接口返回的是失敗,所以這裡可能需要依賴第三方商家的去重策略了

    回覆
    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
  • 取消回覆