架構設計(三) 服務降級,限流和熔斷的設計

隨着公司業務不斷的複雜化,隨之而來的就是微服務的爆發式增長,流量一下就起來了,對於網關來說就不得不考慮服務的保護了,也就是下面講到的降級,限流和熔斷

1. 服務降級的設計

什麼是服務降級?

當服務器壓力劇增的情況下,根據實際業務情況及流量,對一些服務和頁面有策略的不處理或換種簡單的方式處理,從而釋放服務器資源以保證核心交易正常運作或高效運作。

服務降級的目標

保證核心服務可用,非核心服務弱可用,甚至不可用

服務降級的層級

服務層降級
- SLB (Service Load Balance)
- Nginx / Apache
- Spring Cloud Gateway
- Microservice

數據層DB降級

1.1 降級分類

降級按照是否自動化可分爲:自動開關降級和人工開關降級。
降級按照功能可分爲:讀服務降級、寫服務降級。
降級按照處於的系統層次可分爲:多級降級。

詳情可參考:架構設計 -- 服務降級策略詳解

1.2 自動降級分類

超時降級 —— 主要配置好超時時間和超時重試次數和機制,並使用異步機制探測恢復情況
失敗次數降級 —— 主要是一些不穩定的API,當失敗調用次數達到一定閥值自動降級,同樣要使用異步機制探測回覆情況
故障降級 —— 如要調用的遠程服務掛掉了(網絡故障、DNS故障、HTTP服務返回錯誤的狀態碼和RPC服務拋出異常),則可以直接降級
限流降級 —— 當觸發了限流超額時,可以使用暫時屏蔽的方式來進行短暫的屏蔽

1.3 服務降級 - 分佈式開關

我們可以設置一個分佈式開關,用於實現服務的降級,然後集中式管理開關配置信息即可。具體方案如下

1.啓動拉取配置,並啓動定時拉取和訂閱配置信息。
2.可視化管理端變更配置項
3.操作配置中心配置信息
4.通知或被定時拉取最新配置,然後變更內存中的配置信息

 

1.4 服務降級 - 配置中心

微服務降級的配置信息是集中式的管理,然後通過可視化界面進行友好型的操作。配置中心和應用之間需要網絡通信,因此可能會因網絡閃斷或網絡重啓等因素,導致配置推送信息丟失、重啓或網絡恢復後不能再接受、變更不及時等等情況,因此服務降級的配置中心需要實現以下幾點特性,從而儘可能的保證配置變更即使達到

啓動主動拉取配置 —— 用於初始化配置(減少第一次定時拉取週期)

發佈訂閱配置 —— 用於實現配置及時變更(可以解決90%左右的配置變更)

定時拉取配置 —— 用於解決發佈訂閱失效或消失丟失的情況(可以解決9%左右的發佈訂閱失效的消息變更)

離線文件緩存配置 —— 用於臨時解決重啓後連接不上配置中心的問題

可編輯式配置文檔 —— 用於直接編輯文檔的方式來實現配置的定義

提供Telnet命令變更配置 —— 用於解決配置中心失效而不能變更配置的常見

1.5 服務降級要考慮的問題

核心和非核心服務(核心服務 - 中臺服務,和錢打交道的服務 非核心 - OA服務) 
是否支持降級,降級策略
業務放通的場景,策略

1.6 處理策略

當觸發服務降級後,新的請求再次到達時,我們該如何來處理這些請求呢?從微服務架構全局的視角來看,我們通常有以下是幾種常用的降級處理方案:

頁面降級 —— 可視化界面禁用點擊按鈕、調整靜態頁面
延遲服務 —— 如定時任務延遲處理、消息入MQ後延遲處理
寫降級 —— 直接禁止相關寫操作的服務請求
讀降級 —— 直接禁止相關度的服務請求
緩存降級 —— 使用緩存方式來降級部分讀頻繁的服務接口

1.6.1 讀寫請求降級的服務降級手段

1.關閉部分服務(業務相關)

2.拒絕部分請求

2.1 拒絕部分老請求 
- 減輕微服務請求處理的數量
- 確保“新”請求正常響應
- RPC 隊列方式  請求入隊,出隊時間處理

2.2 優先級請求方式
- 非核心功能直接丟棄
- 業務緊密

2.3 隨機拒絕方式
- 隨機丟掉一定比例的請求,網站一會可用一會不可用

針對後端代碼層面的降級處理策略,則我們通常使用以下幾種處理措施進行降級處理

拋異常
返回NULL
調用Mock數據
調用Fallback處理邏輯

1.7 服務降級 - 高級特性

我們已經爲每個服務都做好了一個降級開關,也已經在線上驗證通過了,感覺完全沒問題了。

場景一:某一天,運營搞了一次活動,突然跑過來說,現在流量已經快漲到上限了,有沒有批量降級所有不重要服務的方式?開發一臉懵逼的看着,這又不是操作DB,哪裏有批量操作呀。

場景二:某一天,運營又搞事了,說我們等下要搞一個活動,讓我們趕緊提前把不重要的服務都降級了,開發又是一臉懵逼,我怎麼知道要降級哪些服務呀。

反思:服務降級的功能雖然是實現了,可是沒有考慮實施時的體驗。服務太多,不知道該降級哪些服務,單個操作降級速度太慢……

1.7.1 分級降級

當微服務架構發生不同程度的情況時,我們可以根據服務的對比而進行選擇式捨棄(即丟車保帥的原則),從而進一步保障核心的服務的正常運作。

如果等線上服務即將發生故障時,纔去逐個選擇哪些服務該降級、哪些服務不能降級,然而線上有成百上千個服務,則肯定是來不及降級就會被拖垮。同時,在大促或秒殺等活動前纔去梳理,也是會有不少的工作量,因此建議在開發期就需要架構師或核心開發人員來提前梳理好,是否能降級的初始評估值,即是否能降級的默認值。

爲了便於批量操作微服務架構中服務的降級,我們可以從全局的角度來建立服務重要程度的評估模型,如果有條件的話,建議可以使用 層次分析法(The analytic hierarchy process,簡稱AHP) 的數學建模模型(或其它模型)來進行定性和定量的評估(肯定比架構師直接拍腦袋決定是否降級好很多倍,當然難度和複雜度也會高許多,即你需要一個會數學建模人才),而層次分析法的基本思路是人對一個複雜的決策問題的思維和判斷過程大體上是一樣的。

以下是個人給出的最終評價模型,可作爲服務降級的評價參考模型進行設計

我們利用數學建模的方式或架構師直接拍腦袋的方式,結合服務能否降級的優先原則,並根據颱風預警(都屬於風暴預警)的等級進行參考設計,可將微服務架構的所有服務進行故障風暴等級劃分爲以下四種

評估模型

藍色風暴 (S4)—— 表示需要小規模降級非核心服務

黃色風暴 (S3)—— 表示需要中等規模降級非核心服務

橙色風暴(S2) —— 表示需要大規模降級非核心服務

紅色風暴 (S1)—— 表示必須降級所有非核心服務

設計說明

故障嚴重程度爲:S4<S3<S2<S1

建議根據二八原則可以將服務劃分爲:80%的非核心服務+20%的核心服務

以上模型只是整體微服務架構的服務降級評估模型,具體大促或秒殺活動時,建議以具體主題爲中心進行建立(不同主題的活動,因其依賴的服務不同,而使用不同的進行降級更爲合理)。當然模型可以使用同一個,但其數據需要有所差異。最好能建立一套模型庫,然後實施時只需要輸入相關服務即可輸出最終降級方案,即輸出本次大促或秒殺時,當發生藍色風暴時需要降級的服務清單、當發生黃色風暴時需要降級的服務清單……

1.7.2 降級權值

微服務架構中有服務權值的概念,主要用於負載時的權重選擇,同樣服務降級權值也是類似,主要用於服務降級選擇時的細粒度優先級抉擇。所有的服務直接使用以上簡單的四級劃分方式進行統一處理,顯然粒度太粗,或者說出於同一級的多個服務需要降級時的降級順序該如何?甚至我想要人工智能化的自動降級,又該如何更細粒度的控制?

基於上述的這些AI化的需求,我們可以爲每一個服務分配一個降級權值,從而便於更加智能化的實現服務治理。而其評估的數值,同樣也可以使用數學模型的方式進行定性與定量的評估出來,也可以架構師根據經驗直接拍腦袋來確定。

2. 服務限流的設計

限流可以認爲服務降級的一種,限流就是限制系統的輸入和輸出流量已達到保護系統的目的。一般來說系統的吞吐量是可以被測算的,爲了保證系統的穩定運行,一旦達到的需要限制的閾值,就需要限制流量並採取一些措施以完成限制流量的目的。比如:延遲處理,拒絕處理,或者部分拒絕處理等等。

2.1 服務限流應該怎麼做?

對系統服務進行限流,一般有如下幾個模式

1.熔斷:
這個模式是需要系統在設計之初,就要把熔斷措施考慮進去。當系統出現問題時,如果短時間內無法修復,系統要自動做出判斷,開啓熔斷開關,拒絕流量訪問,避免大流量對後端的過載請求。系統也應該能夠動態監測後端程序的修復情況,
當程序已恢復穩定時,可以關閉熔斷開關,恢復正常服務。 2.服務降級: 將系統的所有功能服務進行一個分級,當系統出現問題,需要緊急限流時,可將不是那麼重要的功能進行降級處理,停止服務,這樣可以釋放出更多的資源供給核心功能的去用。 例如在電商平臺中,如果突發流量激增,可臨時將商品評論、積分等非核心功能進行降級,停止這些服務,釋放出機器和CPU等資源來保障用戶正常下單,而這些降級的功能服務可以等整個系統恢復正常後,再來啓動,進行補單
/補償處理。 除了功能降級以外,還可以採用不直接操作數據庫,而全部讀緩存、寫緩存的方式作爲臨時降級方案。 3.延遲處理: 這個模式需要在系統的前端設置一個流量緩衝池,將所有的請求全部緩衝進這個池子,不立即處理。然後後端真正的業務處理程序從這個池子中取出請求依次處理,常見的可以用隊列模式來實現。這就相當於用異步的方式去減少了後端的處理壓力,
但是當流量較大時,後端的處理能力有限,緩衝池裏的請求可能處理不及時,會有一定程度延遲。 4.特權處理: 這個模式需要將用戶進行分類,通過預設的分類,讓系統優先處理需要高保障的用戶羣體,其它用戶羣的請求就會延遲處理或者直接不處理。

那在實際項目中,對訪問流量的限制,可採用如下幾種技術方法

1.熔斷技術
熔斷的技術可以參考Resilience4j的CircuitBreaker

2.計數器方法
系統維護一個計數器,來一個請求就加1,請求處理完成就減1,當計數器大於指定的閾值,就拒絕新的請求。基於這個簡單的方法,可以再延伸出一些高級功能,比如閾值可以不是固定值,是動態調整的。
另外,還可以有多組計數器分別管理不同的服務,以保證互不影響等。 3.隊列方法 就是基於FIFO隊列,所有請求都進入隊列,後端程序從隊列中取出待處理的請求依次處理。基於隊列的方法,也可以延伸出更多的玩法來,比如可以設置多個隊列以配置不同的優先級。 4.令牌桶方法 首先還是要基於一個隊列,請求放到隊列裏面。但除了隊列以外,還要設置一個令牌桶,另外有一個腳本以持續恆定的速度往令牌桶裏面放令牌,後端處理程序每處理一個請求就必須從桶裏拿出一個令牌,
如果令牌拿完了,那就不能處理請求了。我們可以控制腳本放令牌的速度來達到控制後端處理的速度,以實現動態流控。

 這篇博客有一些限流算法:https://www.cnblogs.com/hlkawa/p/13111003.html

2.2 服務限流的注意事項

2.2.1 服務限流時的需要注意的一些原則和事項

實時監控:系統必須要做好全鏈路的實時監控,才能保證限流的及時檢測和處理。

手動開關:除系統自動限流以外,還需要有能手動控制的開關,以保證隨時都可以人工介入。

限流的性能:限流的功能理論上是會在一定程度影響到業務正常性能的,因此需要做到限流的性能優化和控制。

2.2.2 限流算法分佈式改造

相對於單機限流算法,分佈式限流算法的是指: 算法可以分佈式部署在多臺機器上面,多臺機器協同提供限流功能,可以對同一接口或者服務做限流。分佈式限流算法相較於單機的限流算法,最大的區別就是接口請求計數器需要中心化存儲,比如以Redis作爲 中心計數器來實現分佈式限流算法。分佈式限流算法在引入 Redis 中心計數器這個獨立的系統之後,系統的複雜度一下子高了很多,因爲要解決一些分佈式系統的共性技術問題:

1. 數據一致性問題  
接口限流過程包含三步操作:
Step 1:“讀”當前的接口訪問計數n;
Step 2:”判斷”是否限流;
Step 3:“寫”接口計數 n+1, if 接口限流驗證通過

在併發情況下,這3步CAS操作(compare and swap)存在race condition。在多線程環境下,可以通過線程的加鎖或者concurrent開發包中的Atomic原子對象來實現。在分佈式情況下,思路也是類似的,可以通過分佈式鎖,來保證同一時間段只有一個進程在訪問,
但是引入分佈式鎖需要引入新的系統和維護鎖的代碼,代價較大,爲了簡單,我們可以選擇另一種思路:藉助Redis單線程工作模式 +Lua腳本完美的支持了上述操作的原子性。
2. 超時問題  
對於Redis的各種異常情況,我們處理起來並不是很難,catch住,封裝爲統一的exception,向上拋,或者吞掉。但是如果Redis訪問超時,會嚴重影響接口的響應時間甚至導致接口響應超時,這個副作用是不能接受的。
所以在我們訪問Redis時需要設置合理的超時時間,一旦超時,判定爲限流失效,繼續執行接口邏輯。Redis訪問超時時間的設置既不能太大也不能太小,太大可能會影響到接口的響應時間,太小可能會導致太多的限流失效。
我們可以通過壓測或者線上監控,獲取到Redis訪問時間分佈情況,再結合服務接口可以容忍的限流延遲時間,權衡設置一個較合理的超時時間。
3. 性能問題  
分佈式限流算法的性能瓶頸主要在中心計數器Redis,在沒有做Redis sharding的情況下,基於單實例Redis的分佈式限流算法的性能要遠遠低於基於內存的單機限流算法,此處需要進行壓測看到具體參數
所以在應用分佈式限流算法時,一定要考量限流算法的性能是否滿足應用場景,如果微服務接口的TPS已經超過了限流框架本身的TPS,則限流功能會成爲性能瓶頸影響接口本身的性能。 除了TPS之外,網絡延遲也是一個需要特別考慮的問題,特別是如果中心計數器與限流服務跨機房跨城市部署,之間的網絡延遲將會非常大,嚴重影響微服務接口的響應時間。

2.2.3 選擇單機限流還是分佈式限流

首先需要說明一下:這裏所說的單機限流和分佈式限流與之前提到的單機限流算法和分佈式限流算法並不是一個概念!爲了提高服務的性能和可用性,微服務都會多實例集羣部署,所謂單機限流是指:獨立的對集羣中的每臺實例進行接口限流,比如限制每臺實例接口訪問的頻率爲最大 1000 次 / 秒,單機限流一般使用單機限流算法;所謂的分佈式限流是指:提供服務級的限流,限制對微服務集羣的訪問頻率,比如限制 A 調用方每分鐘最多請求 1 萬次“用戶服務”,分佈式限流既可以使用單機限流算法也可以使用分佈式限流算法。

單機限流的初衷是防止突發流量壓垮服務器,所以比較適合針對併發做限制。分佈式限流適合做細粒度限流或者訪問配額,不同的調用方對不同的接口執行不同的限流規則,所以比較適合針對 hits per second 限流。從保證系統可用性的角度來說,單機限流更具優勢,從防止某調用方過度競爭服務資源來說,分佈式限流更加適合。

分佈式限流與微服務之間常見的部署架構有以下幾種

1. 在接入層(api-gateway)集成限流功能  
這種集成方式是在微服務架構下,有api-gateway的前提下,最合理的架構模式。如果api-gateway是單實例部署,使用單機限流算法即可。如果api-gateway是多實例部署,爲了做到服務級別的限流就必須使用分佈式限流算法。

2. 限流功能封裝爲RPC服務  
當微服務接收到接口請求之後,會先通過限流服務暴露的RPC接口來查詢接口請求是否超過限流閾值。這種架構模式,需要部署一個限流服務,增加了運維成本。這種部署架構,性能瓶頸會出現在微服務與限流服務之間的RPC通信上,
即便單機限流算法可以做到
200萬TPS,但經過RPC框架之後,做到10萬TPS的請求限流就已經不錯了。 3. 限流功能集成在微服務系統內 這種架構模式不需要再獨立部署服務,減少了運維成本,但限流代碼會跟業務代碼有一些耦合,不過,可以將限流功能集成在切面層,儘量跟業務代碼解耦。
如果做服務級的分佈式限流,必須使用分佈式限流算法,如果是針對每臺微服務實例進行單機限流,使用單機限流算法就可以。

2.2.4 不同業務使用不同限流熔斷策略

這裏所講的熔斷策略,就是當接口達到限流上限之後,如何來處理接口請求的問題。前面也有提到過一些限流熔斷策略了,所謂否決式限流就是超過最大允許訪問頻率之後就拒絕請求,比如返回 HTTP status code 429 等,所謂阻塞式限流就是超過最大允許訪問頻率之後就排隊請求。除此之外,還有其他一些限流熔斷策略,比如:記錄日誌,發送告警,服務降級等等。

同一個系統對於不同的調用方也有可能有不同的限流熔斷策略,比如對響應時間敏感的調用方,我們可能採用直接拒絕的熔斷策略,對於像後臺 job 這樣對響應時間不敏感的調用方,我們可能採用阻塞排隊處理的熔斷策略。

我們再來看下其他熔斷策略的一些應用場景:比如限流功能剛剛上線,爲了驗證限流算法的有效性及其限流規則的合理性,確保不誤殺請求,可以先採用日誌記錄 + 告警的限流熔斷策略,通過分析日誌判定限流功能正常工作後,再進一步升級爲其他限流熔斷策略。

不同的熔斷策略對於選擇限流算法也是有影響的,比如令牌桶和漏桶算法就比較適合阻塞式限流熔斷場景,如果是否決式的限流熔斷場景就比較適合選擇基於時間窗口的限流算法。

2.2.5 不同層級的限流

限流的原則,是儘量在流量源頭限,並且是需要依據現有團隊所掌握的技能來。

slb節點的限流

slb全稱 Service Load Balancer,slb的限流更準確的描述是攔截

slb流量特點

幾乎來自外部的流量都從這個入口過來,無論是帶業務屬性的還是不帶業務屬性的、ddos的、正常流量、爬蟲等統統從這裏來。

需要攔截是什麼(由於流量過了這個節點就是我們的應用系統了,因此最好是把非業務應用相關的流量擋住,限制住,讓它有序進來,不要衝垮系統)

ddos攻擊流量
其他通用級的不安全流量:sql注入、xss注入等
連接併發限制
每ip請求限流控制
爬蟲流量

上述是slb節點,但是也有團隊考慮到本身技能,以及代碼git化存儲的原則,會把某些配置往後面的nginx/kong移,因爲slb的配置是UI界面化的,代碼化存儲比較不直接;但是nginx/kong這種就相對容易多了,而且恢復時只要腳本到位,分分鐘就恢復一套系統,很方便。

nginx節點的流限的

到了這裏,ddos這種攻擊流量應該算是過濾掉了,常見的sql注入等攻擊也過濾掉了;但是還存在爬蟲流量(有時,這種流量是我們需要的,SEO推廣等);也會包含高級攻擊流量

因此nginx節點需要做的限流是(通用級別的限流)

爬蟲限流、併發控制、或者過濾、又或者重定向到蜜罐系統(專門給爬蟲做的系統,和主業務系統隔離)
每ip請求限流

spring cloud gateway節點的限流

到了這裏,一般普通靜態H5資源的訪問已經沒有了(已經重定向到其他nginx節點分流處理掉了);gateway處理的都是動態編程語言需要處理的流量,這裏指java。

也就是說,到了這個節點,開始進入java系統領域,流量承受能力比nginx降了1個等級,需要做更多的限制

普通場景下的限流

突發流量下的限流,如:秒殺等

CC攻擊+驗籤的過濾(由於公私鑰證書一般加在java節點上,因此此處放java系統範疇,而不是slb之前,或者nginx之前)

可以在gateway動態路由中分別配置各自的限流配置,以及上述自定義的CC+驗籤配置

 隔離性

由於gateway流量會轉發給後端一大堆微服務,假設由於哪個java微服務處理不過來hang住了,又不想影響其他後端爲服務的轉發,因此需要做隔離性。

可選方案:
resilience4j
sentinel
guava

此處的限流和nginx的限流有啥區別?

nginx的閾值要大,因爲nginx覆蓋的範圍不光是java領域,還有H5等其他範圍

nginx的限流配置維度是通用的,但是spring cloud gateway就變化多了,可以通過自定義KeyResolver來決定所需要的維度來限流,如:用戶id維度、ip維度、租戶維度等,靈活度大了。

微服務節點的限流

到了這裏,就是具體的微服務應用了,單個微服務所能承受的流量,做得好的話是能用jmeter測量出來的,可以通過這個值來參考設置。

再然後,到了具體服務中了,其實限流的維度就更多了,當然需要考量下是否需要加很多限流,脆弱敏感的服務就加些,比如計費等,或者用其他技術做限流,如:queue,然後固定住consumer數來消費,穩住速率。

所採用技術和gateway一樣,也可以自己實現,實現難度都還好。

流量大的系統,最好是用特定技術把income請求根據不同的維度劃分好獨立的線程池,不要相互影響;由本服務發起的到其他服務的請求調用,也需要單獨的線程池來處理。總之目標就是都獨立,不互相影響,即便其他服務慢了,自己也不慢。

因此,熔斷又出現了

當其他服務很慢,超時了,我方作爲服務調用方不能被拖垮啊,這時,就斷開吧,用個指定的協議響應暫且認定爲服務不可用之類的,等後續再補償回查。

當然關鍵服務是不能這麼處理的,只能是輔助服務。關鍵服務就必須要jmeter壓測提升性能。
  • 核心服務的梳理

  • 輔助服務熔斷的返回值+應對方式

  • 核心服務的壓側

2.2.6 配置合理的限流規則

限流規則包含三個部分:時間粒度,接口粒度,最大限流值。限流規則設置是否合理直接影響到限流是否合理有效。

對於限流時間粒度的選擇,我們既可以選擇1秒鐘不超過1000次,也可以選擇10毫秒不超過10次,還可以選擇1分鐘不超過6萬次,雖然看起這幾種限流規則都是等價的,但過大的時間粒度會達不到限流的效果,比如限制1分鐘不超過6萬次,就有可能6萬次請求都集中在某一秒內;相反,過小的時間粒度會削足適履導致誤殺很多本不應該限流的請求,因爲接口訪問在細時間粒度上隨機性很大。所以,儘管越細的時間粒度限流整形效果越好,流量曲線越平滑,但也並不是越細越合適。

對於訪問量巨大的接口限流,比如秒殺,雙十一,這些場景下流量可能都集中在幾秒內,TPS 會非常大,幾萬甚至幾十萬,需要選擇相對小的限流時間粒度。相反,如果接口TPS很小,建議使用大一點的時間粒度,比如限制1分鐘內接口的調用次數不超過1000 次,如果換算成:一秒鐘不超過16次,這樣的限制就有點不合理,即便一秒內超過16次,也並沒有理由就拒絕接口請求,因爲對於我們系統的處理能力來說,16次/秒的請求頻率太微不足道了。即便1000次請求都集中在1分鐘內的某一秒內,也並不會影響到系統的穩定性,所以1秒鐘16次的限制意義不大。

除了時間粒度之外,還需要根據不同的限流需求選擇不同接口粒度,比如:

1)限制微服務每個實例接口調用頻率
2)限制微服務集羣整體的訪問頻率
2)限制某個調用方對某個服務的調用頻率
3)限制某個調用方對某個服務的某個接口的訪問頻率
4)限制某服務的某個接口的訪問頻率
5)限制某服務的某類接口的訪問頻率

對於最大允許訪問頻率的設置,需要結合性能壓測數據、業務預期流量、線上監控數據來綜合設置,最大允許訪問頻率不大於壓測 TPS,不小於業務預期流量,並且參考線上監控數據。

在大促,秒殺,或者其他異常流量到來之前,我們需要事先通過實驗來驗證限流功能的有效性,用數據來證明限流功能確實能夠攔截非預期的異常流量。否則,就有可能會因爲限流算法的選擇不夠合適或者限流規則設置不合理,導致真正超預期流量到來的時候,限流不能起到保護服務的作用,超出預期的異常流量壓垮系統。

如何測試限流功能正確有效呢?儘管可以通過模擬流量或者線上流量回放等手段來測試,但是最有效的測試方法還是:通過導流的方式將流量集中到一小組機器上做真實場景的測試。對於測試結果,我們至少需要記錄每個請求的如下信息:對應接口,請求時間點,限流結果 (通過還是熔斷),然後根據記錄的數據繪製成如下圖表:

從圖表中,我們可以一目瞭然的瞭解限流前與限流後的流量情況,可以清晰的看到限流規則和算法對流量的整形是否合理有效。

除了事先驗證之外,我們還需要時刻監控限流的工作情況,實時瞭解限流功能是否運行正常。一旦發生限流異常,能夠在不重啓服務的情況下,做到熱更新限流配置:包括開啓關閉限流功能,調整限流規則,更換限流算法等等。

3. 服務熔斷的設計

在股票市場,熔斷這個詞大家都不陌生,是指當股指波幅達到某個點後,交易所爲控制風險採取的暫停交易措施。相應的,服務熔斷一般是指軟件系統中,由於某些原因使得服務出現了過載現象,爲防止造成整個系統故障,從而採用的一種保護措施,所以很多地方把熔斷亦稱爲過載保護。

3.1 服務熔斷和服務降級比較

兩者其實從有些角度看是有一定的類似性的

1.目的很一致,都是從可用性可靠性着想,爲防止系統的整體緩慢甚至崩潰,採用的技術手段
2.最終表現類似,對於兩者來說,最終讓用戶體驗到的是某些功能暫時不可達或不可用
3.粒度一般都是服務級別,當然,業界也有不少更細粒度的做法,比如做到數據持久層(允許查詢,不允許增刪改)
4.自治性要求很高,熔斷模式一般都是服務基於策略的自動觸發,降級雖說可人工干預,但在微服務架構下,完全靠人顯然不可能,開關預置、配置中心都是必要手段

而兩者的區別也是明顯的:

1.觸發原因不太一樣,服務熔斷一般是某個服務(下游服務)故障引起,而服務降級一般是從整體負荷考慮
2.管理目標的層次不太一樣,熔斷其實是一個框架級的處理,每個微服務都需要(無層級之分),而降級一般需要對業務有層級之分(比如降級一般是從最外圍服務開始)
3.實現方式不太一樣

3.2 雪崩效應

在微服務架構中通常會有多個服務層調用,基礎服務的故障可能會導致級聯故障,進而造成整個系統不可用的情況,這種現象被稱爲服務雪崩效應。服務雪崩效應是一種因“服務提供者”的不可用導致“服務消費者”的不可用,並將不可用逐漸放大的過程。

如果下圖所示:a作爲服務提供者,b爲c的服務消費者,d和e是b的服務消費者。a不可用引起了b的不可用,並將不可用像滾雪球一樣放大到d和e時,雪崩效應就形成了

 

3. 熔斷器(CircuitBreaker)

熔斷器的原理很簡單,如同電力過載保護器。它可以實現快速失敗,如果它在一段時間內偵測到許多類似的錯誤,會強迫其以後的多個調用快速失敗,不再訪問遠程服務器,從而防止應用程序不斷地嘗試執行可能會失敗的操作,使得應用程序繼續執行而不用等待修正錯誤,或者浪費CPU時間去等到長時間的超時產生。熔斷器也可以使應用程序能夠診斷錯誤是否已經修正,如果已經修正,應用程序會再次嘗試調用操作。

熔斷器模式就像是那些容易導致錯誤的操作的一種代理。這種代理能夠記錄最近調用發生錯誤的次數,然後決定使用允許操作繼續,或者立即返回錯誤。 
熔斷器開關相互轉換的邏輯如下圖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章