微服務的重試與彈性設計

banq發表於2018-03-26
本文是開源工作流引擎Camunda聯合創始人Rücker對微服務呼叫進行彈性設計的改進建議,類似谷歌的gRPC和阿里的Dubbo都可以看成是RPC微服務,Spring提供了REST服務,這些服務雖然形式不同,本質都是同步呼叫。這種同步呼叫在生產環境可能遭遇各種意外情況發生堵塞延遲,怎麼辦?下面他提出了幾種設計方案。


以簡單的網路購物為案例:

客戶端 ---->支付微服務 ---->信用卡微服務

這種簡單的呼叫鏈非常普遍,以它為案例闡述有狀態的彈性模式。

假設信用卡服務變得瘋狂,也就是說它雖然還能響應,但非常緩慢。那麼支付服務呼叫信用卡服務會被阻塞在這裡,因為支付服務一直等待信用卡響應,而信用卡服務延遲響應了。由於延遲過程需要很長時間,所有從支付服務出發的執行緒都會被堵塞在這裡,支付服務最終會超時出錯。在你的系統中出現這樣一個很微小的故障可能會癱瘓整個系統,這是一種沒有彈性的設計。

下面是改進設計演進版本:

快速失敗fail fast
這裡可以應用一個快速失敗模式,比如使用斷路器。在這個例子中,使用了Netflix Hystrix斷路器。如果信用卡服務響應減慢,斷路器就會立即中斷支付服務的呼叫並且讓支付服務馬上發生故障。這樣,即使功能無法實現了(我無法向信用卡充值),但仍然可以確保整個系統可響應。

快速失敗是不夠的
但快速失敗是不夠的。在信用卡服務被修復後,經常會進行重試。此重試需要具有狀態性,不僅可以立即重試,而且可以在幾分鐘,幾小時甚至幾天內重試。對信用卡服務進行有狀態的重試,也就是重試帶著信用卡服務的輸入引數。

保持同步響應
在這種情況下,通常不需要非同步處理,只要信用卡服務可用,就可以很好地返回同步響應,但只有在不能同步時才切換到非同步。

區分能否同步響應,使用HTTP返回碼來支援(200 OK意味著所有OK,202 ACCEPTED意味著同步失敗)。

沒有訊息的非同步工作分配
相比同步呼叫服務的另一種方法是非同步通訊。預設是使用訊息。

但是非同步不一定使用訊息,可以使用工作流引擎作為工作分配,表現得像一個佇列。工作流引擎會提供一個支付是否完成的查詢,如果沒有,會讓客戶更換另外一張信用卡,然後再次呼叫支付服務,這個過程只要指定流程後,流程會負責重試。


使用補償的業務交易
分散式系統中,ACID事務不適用(或者至少不能很好地擴充套件)。使用補償是另一種選擇 - 這意味著如果以後發生失敗時可以撤​​銷已執行的工作。

在這個案例中,基於上面的流程重試,重試幾次後就不再無限次重試了,而是作為支付失敗處理,然後將支付之前的流程進行回退,呼叫回退環節的各個回退方法執行補償,最終將狀態恢復到這次支付活動沒有發生以前的狀態。

flowing-retail/payment-rest at master · flowing/fl

[該貼被admin於2018-03-27 10:39修改過]

相關文章