歡迎光臨
每天分享高質量文章

【剖析 | SOFARPC 框架】系列之 SOFARPC 單機故障剔除剖析

SOFA

Scalable Open Financial Architecture

是螞蟻金服自主研發的金融級分佈式中間件,包含了構建金融級雲原生架構所需的各個組件,是在金融場景里錘煉出來的最佳實踐。


本文為《剖析 | SOFARPC 框架》第六篇,作者暢為

《剖析 | SOFARPC 框架》系列由 SOFA 團隊和原始碼愛好者們出品,

專案代號:,官方目錄目前已經全部認領完畢。


我們同樣期待大家根據自己的實際應用,編寫 SOFARPC 相關內容,可以留言提供相關鏈接,我們也會選擇性的給大家寄送禮物哦 ^_^

  一. 前言

對於金融業務而言每個環節都涉及到大量的資金操作,若因為網絡、硬體等原因導致系統不穩定性,不僅影響用戶體驗,更重要的是可能會引起資損問題,因此系統可用性至關重要。


在微服務分佈式架構中提高系統可用性的常見方案是 集群(冗餘)。 集群方式將一個服務部署在多個機器上,通過硬負載或軟負載實現服務的均衡負載,雖然可以有效避免單點問題,但是仍然避免不了某些場景單機故障引起服務呼叫失敗的問題。


SOFARPC 提供了自動單機故障剔除能力,能夠自動監控 RPC 呼叫的情況,對故障節點進行權重降級,併在節點恢復健康時進行權重恢復,提高系統可用性。本文將從以下兩個方面進行剖析:

  • 單機故障和服務降級介紹

  • SOFARPC 單機故障剔除原理

  二. 單機故障和服務降級

在分佈式架構中常見可用性方案的是 集群(冗餘),即將一個服務部署在多個機器上,通過硬負載或軟負載實現服務的均衡負載。


硬體負載因每次請求都需要經過硬體負載,承擔所有的訪問壓力,當集群規模增加、流量增多,硬體負載可能因無法支撐所有流量而導致系統不可用。


軟負載則提供註冊中心,並將負載能力轉移到服務呼叫方( Consumer ),註冊中心只有在 Consumer 首次訂閱或服務發生變化時才會發生交互,避免了併發訪問下的單點問題。下圖是基於軟負載的服務呼叫:



雖然軟負載可以避免單點問題,但可能存在以下場景導致服務不可用:

  • Provider 出現單點故障或宕機,與 Consumer 的長連接已斷開,但註冊中心尚未摘除或未及時通知Consumer。

  • Consumer 和 Provider 的長連接還存在,註冊中心未下發摘除,但服務器端由於某些原因,例如長時間的 Full GC、硬體故障、壓力瓶頸等,處於亞健康狀態,具體表現為超時、異常率高等。(為避免重覆,文中此類現象的服務節點統稱為亞健康服務節點)。


這兩種場景都是服務端出現故障,但由於長連接還保留等原因註冊中心未摘除服務,導致服務呼叫失敗。針對第一種情況 Consumer 不應呼叫出現故障的 Provider,否則會引起部分服務不可用;針對第二種情況,這個 Consumer 應該不呼叫或少呼叫該 Provider,可以通過權重的方式來進行控制。


目前 SOFARPC 5.3.0 以上的版本支持 RPC 單機故障剔除能力。SOFARPC 通過服務權重控制方式來減少異常服務的呼叫,將更多流量打到正常服務機器上,提高服務可用性。

2.1 SOFARPC故障剔除 vs 註冊中心故障剔除

SOFARPC 的故障剔除與註冊中心故障服務剔除不同,它們從不同的維度來完成故障剔除提高服務可用性。主要兩方面的區別:

  • 故障剔除的時機

  • 故障剔除的細粒度

故障剔除的時機

SOFARPC 的故障剔除與註冊中心故障服務剔除不同,它們從不同的維度來完成故障剔除提高服務可用性。註冊中心服務管理關註 Provider 與註冊中心的心跳或長連接。如果 Provider 出現心跳異常或長連接不存在,則及時將服務從註冊中心剔除,並告知 Consumer 移除本地快取的故障 Provider 信息。Comsumer 在負載均衡選擇時則不考慮被剔除的 Provider,如圖所示:

SOFARPC 單機故障剔除針對的場景不同,針對的是註冊中心還未剔除的服務,這些服務與 Consumer 仍然保持長連接,但由於處於亞健康狀態不能提供正常服務。 如下圖所示:


故障剔除的細粒度

註冊中心剔除的是粒度針對單機上的某個服務行程,屬於行程級別。一旦這個行程和註冊中心斷開連接或心跳無感應,則將其從註冊中心剔除。


SOFARPC 故障剔除並控制精度會更精細一些,會細緻到行程對外暴露的服務,如部署在某個機器上的交易系統對外提供的交易查詢服務 TransQueryService.   管理的維度是 IP + 服務, 這裡的服務特指行程中的服務接口。

2.2 服務權重降級 vs 服務降級

服務降級是當服務器壓力劇增的情況下,根據當前業務情況及流量對一些服務和頁面有策略的降級,以此釋放服務器資源以保證核心任務的正常運行。這裡的降級級別是整個系統服務,而不是針對接口級別。


SOFARPC 的服務降級,是指當某些服務的多個服務節點里存在亞健康節點,導致一些服務接口響應異常,通過 SOFARPC 的故障剔除和服務權重降級來減少對這些異常機器接口的訪問,而將更多的流量打到正常的機器上。 這裡針對的維度主要還是 IP + 服務維度,如部署在 xxx 機器上交易系統對外提供的TransQueryService 服務。

  三. 原理解析

通常一個服務有多個服務提供者,包括健康節點以及亞健康節點。故障剔除功能會將亞健康節點進行降級,使得客戶端的請求更多地指向健康節點。當異常節點的表現正常後,故障剔除功能會對該節點進行恢復,使得客戶端請求逐漸將流量分發到該節點。


SOFARPC 5.3.0 以上支持故障剔除的功能,故障剔除功能採用自動化監控和降級,因此可以減少人工干預,提供系統可用率。SOFARPC 剔除的維度是服務 + IP 級別。為了支持單機故障剔除能力,SOFARPC 提供了以下幾個方面的設計:

  • 入口設計: 進行RPC呼叫的時候,增加一個信息統計的傳遞入口。SOFARPC 採用無縫插入設計,在不破壞開放封閉原則前提下引入單機故障剔除能力。

  • 信息收集器 :  維護和管理從入口傳進來的統計信息。

  • 計算策略 :  主要是根據度量結果,判斷是否需要執行降級或者恢復服務。如果命中降級規則,則觸發降級行為。如果命中恢復規則,則觸發恢復行為。

  • 度量策略 : 負責按一定維度對呼叫信息做度量,判斷服務正常或異常。

  • 降級策略 : 如果服務異常,需要進行降級處理,降級策略指定了處理邏輯,比如按打印日誌或降低服務權重。  

  • 恢復策略 :當一個異常服務恢復正常時,如何恢復該服務,例如提高服務權重等。

3.1 整體結構和入口

《SOFARPC 鏈路追蹤剖析》中已介紹 SOFARPC 的 內核設計和總線設計。和鏈路追蹤功能一樣,SOFARPC 單機故障剔除能力也是基於內核設計和總線設計,做到可插拔、零侵入。


SOFARPC 單機故障剔除模塊是 FaultToleranceModule, 通過 SOFARPC 的 SPI 機制完成模塊的自動化加載,以完成該功能的插入。 FaultToleranceModule 模塊包含了兩個重要部分:

  1. subscriber 事件訂閱器 。 通過訂閱事件總線 EventBus 的事件,以零侵入方式完成 RPC 呼叫的統計和信息收集。

  2. regulator 調節器 。 根據收集的 RPC 呼叫信息,完成服務呼叫或服務權重的調節,達到服務降級和服務恢復的目的。內置了信息收集器、計算策略、度量策略、恢復策略, 是單機故障剔除的核心實現。

FaultToleranceModule 主要關心兩種呼叫事件:

  1. 同步結果事件: ClientSyncReceiveEvent, 收集和統計 RPC 同步 呼叫次數和出現異常的次數。

  2. 異步結果事件: ClientAsyncReceiveEvent,收集和統計 RPC 異步 呼叫次數和出現異常的次數。


雖然SOFAPRC 5.3.0 以上版本已經內置了 FaultToleranceModule, 但預設情況下單機故障剔除功能是關閉的,需要開啟 regulationEffective 全域性開關,才能開啟整個單點故障自動剔除功能,否則完全不進入該功能。如圖所示是整個 SOFARPC 故障自動剔除功能的整體結構:


整體流程如下:

  • 在 RPC 同步或異步呼叫完成後會向事件總線 EventBus 發送對應事件。

  • FaultToleranceModule 的訂閱者收到對應事件,開始進行呼叫統計,將統計結果儲存到 信息收集器中。併在第一次儲存時觸發 Measure 定時任務。

  • Measure 定時任務會在指定視窗時間定時執行。獲取信息收集器的所有信息並交給 度量策略 做度量計算,並開啟計算執行緒負責進行計算和服務調節。

  • 計算執行緒首先會 呼叫 計算策略,計算策略根據 度量策略的計算結果判斷是否執行降級或恢復。

  • 如果進行降級,則呼叫降級策略執行降級操作,如打印日誌或降低故障服務權重。

  • 如果進行恢復,則呼叫恢復策略執行恢復操作,如打印日誌或恢復故障服務權重。

  • 最後在 RPC 呼叫的時候,負載均衡器(預設是 random + weight 負載均衡)會根據根據權重來選擇服務。權重越低的服務被呼叫概率越小,流量流入更少;權重越大的服務,被呼叫概率越大,流量流入增多。

3.2 信息收集器

信息收集器負責是 RPC 呼叫的信息收集和儲存工作,瞭解信息收集器的儲存結構有利於瞭解故障剔除的維度和 RPC呼叫統計管理。

資料結構

TimeWindowRegulator 中維護了一個 MeasureModel 的串列結構,採用 CopyOnWriteArrayList 資料結構,保證執行緒安全。

private final CopyOnWriteArrayList<MeasureModel> measureModels

MeasureModel 是按 app + service 的維度儲存,即一個應用下的某個服務,如交易系統中的交易查詢服務 TransQueryService.  正常一個服務會部署在多個機器上,MeasureModel 會維護這些所有服務,  在資料結構內部使用 InvocationStat 串列來維護這些機器上的服務呼叫關係。

private final String appName;

private final String service;
/** * all dimension statics stats of measure model */
private final ConcurrentHashSet<InvocationStat> stats;


假設有兩個服務 ApiGateWay 和 TransCenter,分別都部署在兩台機器上。 TransCenter 向ApiGateWay提供了交易查詢(TransQueryService)服務 , 如圖所示:


如上圖所示 InvokeStat 是基於 consumer + provider + service 維度,InvokeStat1 表示 ApiGateway1 呼叫了 TransCenter-1 的 TransQueryService 服務。 因此 TransCenter 的MeasureModel 資料模型結構如下:


視窗計算

為了保證併發呼叫環境下的資料安全性,InvokeStat 中的資料採用原子類作為變數型別。事件訂閱器收到同步或異步結果事件後,就會從工廠中獲取這次呼叫的 InvokeStat(如果 InvokeStat 已經存在則直接傳回,如果沒有則創建新的並保持到快取中)。通過呼叫 InvokeStat 的 invoke 和 catchException 方法統計呼叫次數和異常次數。


在每個視窗到期時,則會從 MeasueModel 的各個 InvokeStat 創建一份鏡像資料,表示當前串口內的呼叫情況。而原 InvokeStat 進入到下一個視窗,進行統計,由於此刻為扣除上一個視窗的統計信息因此該視窗的資料包含了上一個視窗的統計資料。當度量策略將本視窗的鏡像資料統計完成以後,會將 InvokeStat 的資料扣除掉當前視窗的鏡像資料,使得 InvokeStat 中的資料為下一個視窗呼叫資料。


3.3 度量策略

度量策略會計算模型 MeasureModel 里的資料進行度量,選出正常和異常節點。 預設採用服務水平 IP 資源度量策略,如果某個 IP 的異常率大於該服務所有 IP 的平均異常率到一定比例,則判定為異常。 


度量策略將計算模型設置為三種狀態:HEALTH(正常)、ABNORMAL(異常)、IGNORE(忽略)。這三種狀態根據異常率情況相互轉化。



繼續以 TransQueryService 為例,闡述度量策略的操作過程:


invokeCount

expCount

invokeStat 1

5

4

invokeStat 2

10

1

invokeStat 3

10

0

結合上述例子,度量策略的大致邏輯如下:

  • 首先統計該服務下所有 IP 的平均異常率,並用 averageExceptionRate 表示。平均異常率比較好理解,即異常總數 / 總呼叫次數,上例中 averageExceptionRate =(1 + 4) / (5 + 10 + 10) = 0.2

  • 當某個IP 的視窗呼叫次數小於該服務的最小視窗呼叫次數( leastWindCount )則忽略並將狀態設置為 IGNOGRE。否則進行降級和恢復度量。 如 invokeStat 1 的 invokeCount 為5,如果 leastWindCount 設置為6 則 invokeStat 1 會被忽略

  • 當某個 IP 的 時間視窗內的異常率和服務平均異常比例 windowExceptionRate 大於 配置的 leastWindowExceptionRateMultiplte (最小時間視窗內異常率和服務平均異常率的降級比值),那麼將該 IP 設置為 ABNORMAL, 否則設置為 HEALTH


windowExceptionRate 是異常率和服務平均異常比例,invokeStat 1 的異常率為 4/5 = 0.8,  則其對應的 windowExceptionRate = 0.8 / 0.2 = 4。 假設  leastWindowExceptionRateMultiplte =4, 那麼 invokeStat 1 是一次服務,則需要進行降級操作。

3.4 計算策略

主要是根據度量結果,判斷是否需要執行降級或者恢復服務。如果度量的結果命中了用戶設置的降級閾值,比如當前度量的異常率是2,用戶設置的是是異常率為1,則判定為命中降級規則,進行則觸發降級行為。如果命中恢復規則,則觸發恢復行為。

3.5 降級策略

預設的降級策略是按比例降級出現單機故障的服務權重,首先,降級策略執行器,會獲取到當前正在度量的接口和度量結果,根據當前度量的接口,根據度量結果信息,獲取到當前記憶體中的服務方信息。然後對其權重進行逐步降級,以初始權重 100 為例

如果用戶設置的降級速率是 2,那麼第一個視窗觸發降級策略後,在降級策略執行的時候,當前有問題的服務提供方的權重將被降級到 100/2=50 。第二次繼續觸發,則降級到50/2=25,以此類推,最後達到最小權重,則不再降級。當對權重進行降級之後,每次 Consumer 進行呼叫操作時能夠被負載均衡擊中的幾率就會對應的小很多,甚至無法擊中。

3.6 恢復策略

當異常服務恢復正常後需要呼叫恢復策略,預設恢復策略是增加該服務的權重,增大其每次在均衡負載是被呼叫的概率。以某個服務處提供方被降級為例,此時正常權重為100,當前異常機器權重被設置為1,在下個時間視窗中,異常率小於平均異常率,觸發恢復策略,恢復速率預設為2,則時間視窗中,該服務提供方權重被設置為1*2=2,隨著時間的流動,下個時間視窗的時候,如果該服務提供方繼續正常,則繼續恢復,恢復為2*2=4,以此類推。恢復會越來越快,直到達到預設權重100。


其中,有兩種情況,一種是當 Consumer 客戶端重啟後,收集器的資料因儲存記憶體都會訊息,所有權重的計算都會重新開始。另一種當異常服務端(Provider)重啟後,服務端能夠提供正常服務,客戶端在時間視窗內呼叫正常,此時其權重也會恢復。

  四. 總結

SOFARPC 5.3.0 支持故障剔除功能,能夠將存在長連接但因為處於亞健康狀態的服務進行降級,使得客戶端的請求更多地指向健康節點。當這些異常節點恢復正常後,故障剔除功能會對該節點進行恢復,使得客戶端請求逐漸將流量分發到該節點。這種策略類似軟負責,所有的邏輯都在客戶端執行。


SOFARPC 的內核設計和事件總線設計,能夠在不破壞開發封閉性的情況下輕鬆引入故障剔除功能。FaultToleranceModule 包含了兩部分:

  1. 事件訂閱,負責訂閱同步和異步結果事件,作為入口統計手機 RPC 呼叫信息。

  2. 調節器。根據收集的信息,以及內置的一些策略完成服務的降級和恢復操作。其中包含了信息收集器、計算策略、度量策略、降級策略和恢復策略。

                  

  One more thing

歡迎加入 ,參與 SOFABolt 原始碼解析


SOFABolt 原始碼解析目錄:

我們會逐步詳細介紹每部分的代碼設計和實現,預計會按照如下的目錄進行,以下也包含目前的原始碼分析文章的認領情況:

  • 【已認領】SOFABolt 的鏈接管理功能分析

  • 【已認領】SOFABolt 的超時控制機制及心跳機制

  • 【待認領】SOFABolt 的設計與私有協議解析

  • 【待認領】SOFABolt 編解碼機制(Codec)

  • 【待認領】SOFABolt 序列化機制(Serializer)

  • 【待認領】SOFABolt 協議框架解析


領取方式:

直接回覆本公眾號想認領的文章名稱,我們將會主動聯繫你,確認資質後,即可加入,It’s your show time!


相關鏈接

SOFA 文件: http://www.sofastack.tech/

SOFA: https://github.com/alipay

SOFARPC: https://github.com/alipay/sofa-rpc

SOFABolt: https://github.com/alipay/sofa-bolt


    與 SOFA 相遇     



2018/9/19 – 9/21,螞蟻金服將在杭州雲棲大會暨螞蟻 ATEC 科技大會期間打造螞蟻開發者樂園,其中包含螞蟻金融科技雲+端一站式體驗以及支付寶小程式挑戰賽兩大環節,歡迎廣大開發者們報名參與,SOFA 團隊將在這裡與你相約,我們更是準備了精美的禮品等待大家 ^_^

舉辦地點:杭州雲棲小鎮國際會展中心場館 B 場館 – ATEC 開發者樂園展區


長按關註,獲取分佈式架構乾貨

歡迎大家共同打造 SOFAStack https://github.com/alipay


  

赞(0)

分享創造快樂