1. 程式人生 > >【剖析 | SOFARPC 框架】之SOFARPC 單機故障剔除剖析

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

一. 前言

對於金融業務而言每個環節都涉及到大量的資金操作,若因為網路、硬體等原因導致系統不穩定性,不僅影響使用者體驗,更重要的是可能會引起資損問題,因此係統可用性至關重要。在微服務分散式架構中提高系統可用性的常見方案是 __叢集(冗餘)。 __叢集方式將一個服務部署在多個機器上,通過硬負載或軟負載實現服務的均衡負載,雖然可以有效避免單點問題,但是仍然避免不了某些場景單機故障引起服務呼叫失敗的問題。

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

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

二. 單機故障和服務降級

在分散式架構中常見可用性方案的是 __叢集(冗餘),__即將一個服務部署在多個機器上,通過硬負載或軟負載實現服務的均衡負載。硬體負載因每次請求都需要經過硬體負載,承擔所有的訪問壓力,當叢集規模增加、流量增多,硬體負載可能因無法支撐所有流量而導致系統不可用。

image.png | center | 483x176

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

image.png | center | 482x152

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

  1. Provider 出現單點故障或宕機,與 Consumer 的長連線已斷開,但註冊中心尚未摘除或未及時通知Consumer。
  2. Consumer 和 Provider的長連線還在,註冊中心未下發摘除,但伺服器端由於某些原因,例如長時間的 Full GC, 硬體故障(後文中為避免重複,統一描述為機器假死)等場景,處於假死狀態。

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

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

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

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

  1. 故障剔除的時機
  2. 故障剔除的細粒度

故障剔除的時機

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

image.png | center | 493x262

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

image.png | center | 479x239

故障剔除的細粒度

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

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

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

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

SOFARPC 的服務降級,是指當某些個別機器因為存在機器假死,導致處於假死狀態,導致一些服務介面響應異常,通過 SOFARPC 的故障剔除和服務權重降級來減少對這些異常機器介面的訪問,而將更多的流量打到正常的機器上。 這裡針對的維度主要還是 IP + 服務維度,如部署在 xxx 機器上交易系統對外提供的TransQueryService 服務。

三. 原理解析

通常一個服務有多個服務提供者,其中__部分提供者可能由於機器假死等導致長連線還存活但是程式已經無法正常響應__ 。 故障剔除功能會將這部分異常的服務提供者進行降級,使得客戶端的請求更多地指向健康節點。當異常節點的表現正常後,故障剔除功能會對該節點進行恢復,使得客戶端請求逐漸將流量分發到該節點。

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

  1. __入口設計__: 進行RPC呼叫的時候,增加一個資訊統計的傳遞入口。SOFARPC 採用無縫插入設計,在不破壞開放封閉原則前提下引入單機故障剔除能力。
  2. 資訊收集器 : 維護和管理從入口傳進來的統計資訊。
  3. 計算策略 :  主要是根據度量結果,判斷是否需要執行降級或者恢復服務。如果命中降級規則,則觸發降級行為。如果命中恢復規則,則觸發恢復行為。
  4. 度量策略 : 負責按一定維度對呼叫資訊做度量,判斷服務正常或異常。
  5. 降級策略 : 如果服務異常,需要進行降級處理,降級策略指定了處理邏輯,比如按列印日誌或降低服務權重。
  6. 恢復策略 :當一個異常服務恢復正常時,如何恢復該服務,例如提高服務權重等。

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 故障自動剔除功能的整體結構:

image.png | left | 747x567

整體流程如下:

  1. 在 RPC 同步或非同步呼叫完成後會向事件匯流排 EventBus 傳送對應事件。
  2. FaultToleranceModule 的訂閱者收到對應事件,開始進行呼叫統計,將統計結果儲存到 資訊收集器中。並在第一次儲存時觸發 Measure 定時任務。
  3. Measure 定時任務會在指定視窗時間定時執行。獲取資訊收集器的所有資訊並交給 度量策略 做度量計算,並開啟計算執行緒負責進行計算和服務調節。
  4. 計算執行緒首先會 呼叫 計算策略,計算策略根據 度量策略的計算結果判斷是否執行降級或恢復。
  5. 如果進行降級,則呼叫降級策略執行降級操作,如列印日誌或降低故障服務權重。
  6. 如果進行恢復,則呼叫恢復策略執行恢復操作,如列印日誌或恢復故障服務權重。
  7. 最後在 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)服務 , 如圖所示:

image.png | center | 480x187

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

image.png | center | 497x361

視窗計算

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

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

image.png | center | 591x208

3.3 度量策略

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

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

image.png | center | 247x219

繼續以 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. 調節器。根據收集的資訊,以及內建的一些策略完成服務的降級和恢復操作。其中包含了資訊收集器、計算策略、度量策略、降級策略和恢復策略。

image | left | 216x216

長按關注,獲取分散式架構乾貨

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