天天看點

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

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

SOFA

Scalable Open Financial Architecture

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

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

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

項目代号:,官方目錄目前已經全部認領完畢。

一. 前言

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

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

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

  • 單機故障和服務降級介紹
  • SOFARPC 單機故障剔除原理

二. 單機故障和服務降級

在分布式架構中常見可用性方案的是 叢集(備援),即将一個服務部署在多個機器上,通過硬負載或軟負載實作服務的均衡負載。

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

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

軟負載則提供注冊中心,并将負載能力轉移到服務調用方( Consumer ),注冊中心隻有在 Consumer 首次訂閱或服務發生變化時才會發生互動,避免了并發通路下的單點問題。下圖是基于軟負載的服務調用:

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

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

  • 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 架構】系列之 SOFARPC 單機故障剔除剖析

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

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

注冊中心剔除的是粒度針對單機上的某個服務程序,屬于程序級别。一旦這個程序和注冊中心斷開連接配接或心跳無感應,則将其從注冊中心剔除。

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 子產品包含了兩個重要部分:

subscriber 事件訂閱器 。 通過訂閱事件總線 EventBus 的事件,以零侵入方式完成 RPC 調用的統計和資訊收集。

regulator 調節器 。 根據收集的 RPC 調用資訊,完成服務調用或服務權重的調節,達到服務降級和服務恢複的目的。内置了資訊收集器、計算政策、度量政策、恢複政策, 是單機故障剔除的核心實作。

FaultToleranceModule 主要關心兩種調用事件:

同步結果事件: ClientSyncReceiveEvent, 收集和統計 RPC 同步 調用次數和出現異常的次數。

異步結果事件: ClientAsyncReceiveEvent,收集和統計 RPC 異步 調用次數和出現異常的次數。

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

【剖析 | SOFARPC 架構】系列之 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)服務 , 如圖所示:

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

如上圖所示 InvokeStat 是基于 consumer + provider + service 次元,InvokeStat1 表示 ApiGateway1 調用了 TransCenter-1 的 TransQueryService 服務。 是以 TransCenter 的MeasureModel 資料模型結構如下:

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

視窗計算

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

在每個視窗到期時,則會從 MeasueModel 的各個 InvokeStat 建立一份鏡像資料,表示目前序列槽内的調用情況。而原 InvokeStat 進入到下一個視窗,進行統計,由于此刻為扣除上一個視窗的統計資訊是以該視窗的資料包含了上一個視窗的統計資料。當度量政策将本視窗的鏡像資料統計完成以後,會将 InvokeStat 的資料扣除掉目前視窗的鏡像資料,使得 InvokeStat 中的資料為下一個視窗調用資料。

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

3.3 度量政策

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

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

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

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

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

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

  • 首先統計該服務下所有 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,則時間視窗中,該服務提供方權重被設定為12=2,随着時間的流動,下個時間視窗的時候,如果該服務提供方繼續正常,則繼續恢複,恢複為22=4,以此類推。恢複會越來越快,直到達到預設權重100。

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

四. 總結

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

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

事件訂閱,負責訂閱同步和異步結果事件,作為入口統計手機 RPC 調用資訊。

調節器。根據收集的資訊,以及内置的一些政策完成服務的降級和恢複操作。其中包含了資訊收集器、計算政策、度量政策、降級政策和恢複政策。