東漢末年,他們把「服務雪崩」玩到了極致(乾貨)

這是個人第 66 篇原創文章
git

做者 | 悟空聊架構github

來源 | 悟空聊架構(ID:PassJava666)web

轉載請聯繫受權(微信ID:PassJava)
滾滾長江東逝水,浪花淘盡英雄。

是非成敗轉頭空。青山依舊在,幾度夕陽紅。算法

-- 來自《三國演義》數據庫

本篇將會經過三國中的赤壁之戰來說述周瑜、黃蓋和諸葛亮是怎麼把服務雪崩玩到極致的。c#

本文已收錄到個人 Github,點擊文末的閱讀原文打開。給個Star吧~緩存

https://github.com/Jackson0714/PassJava-Learning服務器

赤壁之戰

話說東漢末年,曹操、孫權、劉備在長江赤壁(今湖北蒲圻西北)進行了一次爭奪老大位置的大戰,這就是有名的赤壁之戰微信

1、還原赤壁之戰

曹操統一北方後,南下戰勝了劉備,佔領荊襄之地後,還想幹掉東邊的孫權,因而劉備和孫權一塊兒聯合抗擊曹軍八十萬大軍。網絡

曹操的軍隊大部分都是北方的,對於水上做戰的經驗很是欠缺,並且不少士兵暈船,因而曹操命令軍隊將船尾用鐵索相連,減弱了風浪顛簸,利於士兵演練。

鐵索連環-圖片來源網絡

咱們來看看周瑜、黃蓋、諸葛亮的對話:

三人對話@悟空聊架構

黃蓋:曹操是真的蠢啊,把船連着,若是船燒着了,其餘船會跟着一塊兒燒着的。鎖鏈不易解開,船都逃不了了。咱們用火攻,直接把曹軍幹趴下。
周瑜:但如何接近他們的船呢?
黃蓋:我用詐降帶幾艘船出發,船上載浸油的乾草,等接近曹軍時,點燃乾草,衝向曹軍的連環船,引燃他們的船隻。
周瑜:妙啊!但是哪來的東風?
諸葛亮:我來借東風~

赤壁之戰那天,火船乘風闖入曹軍船陣,頓時一片火海。聯軍乘勢攻擊,曹軍傷亡慘重,最後以聯軍大勝結束,成爲了以少勝多的經典戰役。

引燃連鎖船-圖片來源網絡

2、戰情分析

周瑜和黃蓋看出了連環船的弱點:「若是一隻船被燒着了,也會把連着的船燒着」

這就很像咱們的系統中出現的服務雪崩問題。

假定咱們系統引進了微服務的思想,將多個服務進行拆分,每一個服務都是經過接口調用來完成的,看似功能經過微服務化後,功能和職責單一,正是咱們想要的.

但隨着業務的增加,服務的數量也是隨之增多,邏輯也會更加複雜,一個服務的某個邏輯須要依賴多個其餘服務才能完成。假如一個被依賴的服務不能向上遊的服務提供服務,則極可能形成雪崩效應,最後致使整個服務不可訪問

就像雪山上某一處出現積雪崩塌的現象,慢慢地帶動其餘片區的積雪崩塌,產生了級聯反應,最後形成大片的積雪崩塌,這就是常見的雪崩場景。

「小結」 一個服務失敗,致使整條鏈路的服務都失敗的場景,稱爲服務雪崩。

那曹軍應該怎麼避免這個問題呢?別急,後面再看答案。

3、系統中的雪崩效應

微服務之間每每採用 RPC 或者 HTTP 調用,通常都會設置調用超時的限制,或者經過失敗重試機制來確保服務成功執行。但若是不考慮服務的熔斷和限流,仍是很容易產生服務雪崩的。下面用例子來說解下雪崩效應是怎麼產生的。

雪崩效應
  • 咱們系統中三個服務:訂單服務商品服務庫存服務

  • 下單場景:用戶下單了一個商品,客戶端調用訂單服務來生成預付款訂單,訂單服務調用商品服務查看下單的哪款商品,商品服務調用庫存服務判斷這款商品是否有庫存,若有庫存,則能夠生成預付款訂單。

  • 假定因雙十一流量暴增,庫存服務不可用(如響應超時等),庫存服務收到的不少請求都未處理完,它將沒法處理更多請求。

  • 而上游的商品服務依賴庫存服務,商品服務的超時重試機制會被執行。商品服務新的調用不斷產生,會致使商品服務的調用被大量積壓,產生大量的調用等待重試調用,慢慢耗盡商品服務的資源,好比內存,結果致使商品服務也宕機了。

  • 而訂單服務也會重走商品服務的老路。結果就是三個服務都不可用了

4、形成雪崩的真實場景

1.4.1 服務提供者不可用

  • 硬件故障:如網絡故障、硬盤損壞等。

  • 程序的 bug:如算法須要佔用大量 CPU 的計算時間致使 CPU 使用率太高。

  • 緩存擊穿:好比應用剛重啓,短期內緩存是失效的,致使大量請求直接訪問到了數據庫,數據庫不堪重負,服務不可用。

  • 秒殺和大促:服務短期承載不了那麼多請求量。

1.4.2 重試加大流量

  • 用戶連續重試:好比用戶看到界面上沒有響應,因此又操做了一遍,結果又增長了一倍請求量。

  • 程序重試機制:好比代碼中有屢次重試的邏輯,一次失敗後,過幾秒後再重試,重試個三次就取消重試,走異常處理分支了。也是增長了請求量。

5、如何防止雪崩

方案

出問題前預防:限流、主動降級、隔離

出問題後修復:熔斷、被動降級

「本篇主要來說解熔斷機制。」 後續幾篇會講解其餘方案。

6、熔斷原理和算法

1.6.1 熔斷概念

保險絲熔斷

熔斷這個概念來源於電路系統中的保險絲熔斷。當電流過大時,保險絲熔斷,防止因電流過大損壞電器元器件,或因電流過大,致使元器件熱度太高,發生火災。

保險絲長啥樣

「物理公式」 電功率 P = I^2 * R,I 表明電流,元器件的電阻 R 不變的狀況下,電流越大,電功率約大,電阻作的電功大部分都用來發熱了,因此電功率越大,發熱越嚴重。(還好高中物理沒忘。)

放到咱們系統中,怎麼理解熔斷?

若是在某段時間內,調用某個服務很是慢甚至超時,就能夠將這個服務熔斷,後續其餘服務再調用這個服務就直接返回,告訴其餘服務:「「已經熔斷了,你別調用我了,過段時間再來試下吧。」」

1.6.2 如何熔斷

「熔斷有個原則」 一段時間內,統計失敗的次數或者失敗請求的佔比超過必定閾值,就進行熔斷。

詳細的原理以下圖所示:

熔斷原理圖&悟空聊架構

1.6.3 統計請求的算法

  • 請求訪問到後臺服務後,首先判斷熔斷開關是否打開。

  • 若是熔斷開關已打開,則代表當前請求不能被處理。

  • 若是熔斷開關未打開,則判斷時間窗口是否已滿。

  • 若是時間窗口未滿,則請求桶中的請求數加 1。

  • 若是返回的響應有異常,則失敗桶的失敗數加 1,若是返回的響應沒有異常,則成功桶的成功數加 1

  • 若是時間窗口已滿,則開始判斷是否須要熔斷。

1.6.4 熔斷的恢復算法

  • 當熔斷後,開關切換到斷開狀態

  • 過一段時間後,開關切換爲半斷開狀態(Half-Open)。半斷開狀態下,容許對應用程序的必定數量的請求能夠去調用服務,若是調用成功,則認爲服務能夠正常訪問了,因而將開關切換爲閉合狀態

  • 若是半斷開狀態下,仍是有調用失敗的狀況,則認爲服務尚未恢復,開關從半斷開狀態切換到斷開狀態

1.6.5 統計失敗率的時間窗口

統計失敗率的時間窗口@悟空聊架構
  • 時間窗口能夠比喻爲人坐在窗戶邊,看外面來往的車輛,必定時間內從窗戶外通過的車輛。

  • 每次請求,都會判斷時間窗口是否已滿(如5分鐘),若是時間窗口已滿,則從新開始計時,且清理請求數/成功數/失敗數。

  • 注意:第一次開始的起始時間默認爲當前時間。

1.6.6 嘗試恢復服務的時間窗口

嘗試恢復服務的時間窗口@悟空聊架構
  • 開關爲斷開的狀態,通過必定時間後,好比 1 分鐘,設置爲半斷開的狀態,嘗試發送請求檢測服務是否恢復。

  • 若是已恢復,則切換狀態爲關閉狀態。若是未恢復,則切換狀態爲斷開的狀態,通過 1 分鐘後,重複上面的步驟。

  • 這裏的時間窗口能夠根據環境的運行狀態進行動態調整,好比第一次是 1 分鐘,第二次是 3 分鐘,第三次是 10 分鐘。

7、熔斷中間件

確定有人會問了,你這上面講的原理,難道還真的本身去寫這套算法?

「答案:是的,項目中咱們本身造了一個輪子:熔斷器。」

但這裏我不推薦你們這麼作。市面上還有更優秀的開源組件供你們使用,好比阿里系的 Sentinel(推薦),Netflix 的 Hystrix(已中止更新)。

固然 Sentinel 就不在這篇講了,後續奉上~

8、扭轉戰局

曹操大敗是由於連鎖船的緣由,那如何給曹操提供一妙計,助他扭轉戰局呢?

「方案有以下幾個」

  • 能夠用麻繩代替鎖鏈,因繩子更容易割斷。(熔斷機制)

  • 將船劃分到幾個區域,區域之間保持必定距離,即便某個區域燒着了,也不會影響其餘區域。(熔斷+資源隔離)

  • 在湖面上提早設關卡,黃蓋過來的話,先檢查船和人,有問題不予通行。(熔斷)

妙啊

9、限流、降級

原本是想在這篇把限流降級也寫完的,發現熔斷的內容越寫越多了,那就把限流和降級放在後面幾篇吧。也是三國故事哦~

寫在最後

《三國演義》也是我很是喜歡的一部文學做品,書大概看了 80 %,電視劇是看完了的。

最喜歡的角色固然是軍師諸葛亮啦,還有梟雄曹操~~

- END -

我建了一個學習交流羣「在羣裏不說話都能進步哦~」 掃碼加我,備註[加羣]

我的二維碼


更多內容

我是一個秒殺請求,正在逃離這顆星球...


若是把四個消息隊列都拉到一個羣裏,他們會聊些什麼?


這三年被分佈式坑慘了,曝光十大坑


我是悟空,努力變強,變身超級賽亞人!

點亮,服務器三年不宕機

本文分享自微信公衆號 - 悟空聊架構(PassJava666)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索