之前講到了資料庫層和快取層的改造思路,而對於業務層的改造,採用了集中式服務轉微服務的架構方案。既然是微服務,就意味著面臨大量的服務間的內部呼叫及服務依賴,這就意味著,如果一次請求的呼叫涉及到兩個或多個微服務之間的呼叫,恰好有下游的微服務呼叫失敗,我們就必須要考慮到回滾及服務間保證資料一致性的問題。所以,今天我將列出可能出現的失敗情況及對應的解決方案,希望對大家正在做微服務改造的團隊有所幫助。
首先,我們對微服務間呼叫做一個分類:
服務間沒有直接依賴,採用非同步化呼叫,上游服務完成後,發一個訊息非同步通知下游服務,下游服務成功與否對上游服務沒有影響。
上游服務弱依賴於某個下游服務的處理結果,可降級。降級時可以不返回這部分的資料。同步呼叫降級時轉為非同步。
上下游微服務強依賴,上游服務依賴於下游服務的返回或者回撥,下游必須正常執行,如果下游服務失敗了,本次請求判定為失敗。
服務間純非同步呼叫,需保證冪等性和佇列重試機制
對於Case1, 只需要考慮2點:冪等性和訊息佇列重試機制,冪等性意味著,重複訊息不會對下游服務的結果產生任何影響;訊息佇列重試機制保證了,訊息本身不會出現丟失,即便訊息佇列在發給下游佇列前掛掉了,重啟後,能繼續傳送對應的訊息。
上下游同步執行失敗,通過訊息執行非同步呼叫
對於Case2, 採用的方案如下圖所示,主服務依賴於A,B,C 三個下游服務,同步呼叫過程中,服務C呼叫失敗。由於服務C不是強依賴,我們便可以給訊息佇列傳送一條訊息,保證主服務可以正常返回,同時保證服務C能繼續被執行,保證資料的一致性。
採用TCC進行提交與回滾,保證資料的一致性
Case3是服務間呼叫最嚴格的情況,意味著如果下游服務中有一個服務呼叫失敗,上下游的所有服務必須回滾。意味著服務間必須保證同一個事務。業界公認的一個解決方案就是 TCC (Try-Confirm-Cancel) 模式:
主業務服務分別呼叫下游業務執行try操作,並在活動管理器中登記所有下游服務。當所有下游微服務的try操作都呼叫成功,或者某個下游微業務服務的try操作失敗。
業務活動管理器根據第1步的執行結果來執行confirm或cancel操作。如果之前所有try操作都成功,則活動管理器呼叫所有下游微業務,執行confirm操作。否則呼叫所有下游微服務的cancel操作。
如果第2步,執行confirm或concel操作出現失敗,活動管理器會啟動重試機制,保證所有微服務最終提交或者回滾操作成功。
小結
上文對微服務間呼叫的3種情況的資料一致性方案做了說明:
1. 確保介面冪等性,訊息佇列具備重試機制,實際上幾乎現在所有的MQ都支援重試。
2. 服務呼叫同步轉非同步,確保上游服務成功執行,並保證服務間的資料一致性。
3. 利用TCC方案解決服務間呼叫強依賴的資料一致性。
掃描二維碼或手動搜尋微信公眾號: ForestNotes
歡迎轉載,帶上以下二維碼即可