search
尋找貓咪~QQ 地點 桃園市桃園區 Taoyuan , Taoyuan

如何解決微服務架構中的雪崩問題?

作者|魏春雷 編輯|Gary

記得在三年前公司因為業務發展需要,就曾經將單體應用遷移到分散式框架上來。當時就遇到了這樣一個問題:系統僅有一個控制單元,它會調用多個運算單元,如果某個運算單元(作為服務提供者)不可用,將導致控制單元(作為服務調用者)被阻塞,最終導致控制單元崩潰,進而導致整個系統都面臨著癱瘓的風險。

那個時候還不知道這其實就是服務的雪崩效應,雪崩效應好比就是蝴蝶效應,說的都是一個小因素的變化,卻往往有著無比強大的力量,以至於最後改變整體結構、產生意想不到的結果。雪崩效應也是我們目前研發的產品直面的一道坎,下面我們來看有哪些場景會引發雪崩,又如何避免?對於無法避免的雪崩效應,我們又有哪些應對措施?

1. 星火燎原1.1農民眼中的微服務

近年來,微服務就象一把燎原的大火,竄了出來並在整個技術社區燒了起來,微服務架構被認為是IT軟體服務化架構演進的目標。為什麼微服務這麼火,微服務能給企業帶來什麼價值?

1.1.1 以種植農作物的思想來理解微服務

我們以耕種為例來看如何充分利用一塊田地的:

  • 先在地里種植了一排排玉米;

  • 後來發現玉米腳下空地可以利用,再間隔一段距離再種上豆角,豆角長大后順著玉米桿往上爬,最後緊緊地纏繞在玉米桿上;

  • 再後來發現每排玉米之間的空隙地還可以再種些土豆,土豆蔓藤以後會交織在一起,肆虐在玉米腳下吞食營養物質;

表面看來一塊土地得到了充分利用,實際上各農作物得不到充分的光照和適宜的營養,如此一來加大了後期除草、鬆土、施肥、灌溉及收割的成本。

下面的耕植思路是不是更好點呢? 一整塊地根據需要分配為若干大小土地塊,每塊地之間清晰分界,這樣就有了玉米地、土豆地、豆角地,再想種什麼划塊地再耕作就可以了。

這樣種植好處很多,比如玉米、豆角和土豆需要的營養物質是不一樣的,可由專業技術人員施肥;玉米,豆角和土豆分離,避免豆角藤爬上玉米,纏繞玉米不能自由生長。土豆又汲取玉米需要的營養物質等等問題。

軟體系統實現與農作物的種植方式其實也很類似,傳統的應用在擴展性,可靠性,維護成本上表現都不盡人意。如何充分利用大量系統資源,管理和監控服務生命周期都是頭疼的事情,軟體系統設計迫切需要上述的「土地分割種植法」。微服務架構應運而生:在微服務系統中,各個業務系統間通過對消息(字元序列)的處理都非常友好的RestAPI進行消息交互。如此一來,各個業務系統根據Restful架構風格統一成一個有機系統。

1.2 微服務架構下的冰山

泰坦尼克號曾經是世界最大的客輪,在當時被稱為是」永不沉沒「的,但卻在北大西洋撞上冰山而沉沒。我們往往只看到它浮出水面的絢麗多彩,水下的基礎設施如資源規劃、服務註冊發現、部署升級,灰度發布等都是需要考慮的因素。

1.2.1 優勢

  • 複雜應用分解:複雜的業務場景可被分解為多個業務系統,每個業務系統的每個服務都有一個用消息驅動API定義清楚的邊界。

  • 契約驅動:每個業務系統可自由選擇技術,組建技術團隊利用Mock服務提供者和消費者,并行開發,最終實現依賴解耦。

  • 自由擴展:每個系統可根據業務需要獨自進行擴展。

  • 獨立部署:每個業務系統互相獨立,可根據實際需要部署到合適的硬體機器上。

  • 良好隔離:一個業務系統資源泄漏不會導致整個系統宕掉,容錯性較好。

1.2.2 面臨的挑戰

  • 服務管理:敏捷迭代后的微服務可能越來越多,各個業務系統之間的交互也越來越多,如何做高效集群通信方案也是問題。

  • 應用管理: 每個業務系統部署后對應著一個進程,進程可以啟停。如果機器掉電或者宕機了,如何做無縫切換都需要強大的部署管理機制。

  • 負載均衡:為應對大流量場景及提供系統可靠性,同一個業務系統也會做分散式部署即一個業務實例部署在多台機器上。如果某個業務系統掛掉了,如何按需做自動伸縮分散式方案方案也需要考慮。

  • 問題定位:單體應用的日誌集中在一起,出現問題定位很方便,而分散式環境的問題定界定位,日誌分析都較為困難。

  • 雪崩問題:分散式系統都存在這樣一個問題,由於網路的不穩定性,決定了任何一個服務的可用性都不是 100% 的。當網路不穩定的時候,作為服務的提供者,自身可能會被拖死,導致服務調用者阻塞,最終可能引發雪崩效應。

Michael T. Nygard 在精彩的《Release It!》一書中總結了很多提高系統可用性的模式,其中非常重要的兩條是:使用超時策略和使用熔斷器機制

  • 超時策略:如果一個服務會被系統中的其它部分頻繁調用,一個部分的故障可能會導致級聯故障。例如,調用服務的操作可以配置為執行超時,如果服務未能在這個時間內響應,將回復一個失敗消息。然而,這種策略可能會導致許多併發請求到同一個操作被阻塞,直到超時期限屆滿。這些阻塞的請求可能會存儲關鍵的系統資源,如內存、線程、資料庫連接等。因此,這些資源可能會枯竭,導致需要使用相同的資源系統的故障。在這種情況下,它將是優選的操作立即失敗。設置較短的超時可能有助於解決這個問題,但是一個操作請求從發出到收到成功或者失敗的消息需要的時間是不確定的。

  • 熔斷器模式:熔斷器的模式使用斷路器來檢測故障是否已得到解決,防止請求反覆嘗試執行一個可能會失敗的操作,從而減少等待糾正故障的時間,相對與超時策略更加靈活。

一年一度的雙十一已經悄然來臨,下面將介紹某購物網站一個Tomcat容器在高併發場景下的雪崩效應來探討Hystrix的線程池隔離技術和熔斷器機制。

2. 從雪崩看應用防護

2.1 雪崩問題的本質:Servlet Container在高併發下崩潰

我們先來看一個分散式系統中常見的簡化的模型。Web伺服器中的Servlet Container,容器啟動時後台初始化一個調度線程,負責處理Http請求,然後每個請求過來調度線程從線程池中取出一個工作者線程來處理該請求,從而實現併發控制的目的。

Servlet Container是我們的容器,如Tomcat。一個用戶請求有可能依賴其它多個外部服務。考慮到應用容器的線程數目基本都是固定的(比如Tomcat的線程池默認200),當在高併發的情況下,如果某一外部依賴的服務(第三方系統或者自研系統出現故障)超時阻塞,就有可能使得整個主線程池被佔滿,增加內存消耗,這是長請求擁塞反模式(一種單次請求時延變長而導致系統性能惡化甚至崩潰的惡化模式)。

更進一步,如果線程池被佔滿,那麼整個服務將不可用,就又可能會重複產生上述問題。因此整個系統就像雪崩一樣,最終崩塌掉。

2.2 雪崩效應產生的幾種場景

  • 流量激增:比如異常流量、用戶重試導致系統負載升高;

  • 緩存刷新:假設A為client端,B為Server端,假設A系統請求都流向B系統,請求超出了B系統的承載能力,就會造成B系統崩潰;

  • 程序有Bug:代碼循環調用的邏輯問題,資源未釋放引起的內存泄漏等問題;

  • 硬體故障:比如宕機,機房斷電,光纖被挖斷等。

  • 線程同步等待:系統間經常採用同步服務調用模式,核心服務和非核心服務共用一個線程池和消息隊列。如果一個核心業務線程調用非核心線程,這個非核心線程交由第三方系統完成,當第三方系統本身出現問題,導致核心線程阻塞,一直處於等待狀態,而進程間的調用是有超時限制的,最終這條線程將斷掉,也可能引發雪崩;

2.3 雪崩效應的常見解決方案

針對上述雪崩情景,有很多應對方案,但沒有一個萬能的模式能夠應對所有場景。

  • 針對流量激增,採用自動擴縮容以應對突發流量,或在負載均衡器上安裝限流模塊。

  • 針對緩存刷新,參考Cache應用中的服務過載案例研究

  • 針對硬體故障,多機房容災,跨機房路由,異地多活等。

  • 針對同步等待,使用Hystrix做故障隔離,熔斷器機制等可以解決依賴服務不可用的問題。

通過實踐發現,線程同步等待是最常見引發的雪崩效應的場景,本文將重點介紹使用Hystrix技術解決服務的雪崩問題。後續再分享流量激增和緩存刷新等應對方案。

3. 隔離和熔斷

Hystrix 是由Netflix發布,旨在應對複雜分散式系統中的延時和故障容錯,基於Apache License 2.0協議的開源的程序庫,目前託管在GitHub上。

Hystrix採用了命令模式,客戶端需要繼承抽象類HystrixCommand並實現其特定方法。為什麼使用命令模式呢?使用過RPC框架都應該知道一個遠程介面所定義的方法可能不止一個,為了更加細粒度的保護單個方法調用,命令模式就非常適合這種場景。

命令模式的本質就是分離方法調用和方法實現,在這裡我們通過將介面方法抽象成HystricCommand的子類,從而獲得安全防護能力,並使得的控制力度下沉到方法級別。

Hystrix核心設計理念基於命令模式,命令模式UML如下圖:

可見,Command是在Receiver和Invoker之間添加的中間層,Command實現了對Receiver的封裝。那麼Hystrix的應用場景如何與上圖對應呢?

API既可以是Invoker又可以是Reciever,通過繼承Hystrix核心類HystrixCommand來封裝這些API(例如,遠程介面調用,資料庫的CRUD操作可能會產生延時),就可以為API提供彈性保護了。

3.1 資源隔離模式

Hystrix之所以能夠防止雪崩的本質原因,是其運用了資源隔離模式,我們可以用蓄水池做比喻來解釋什麼是資源隔離。生活中一個大的蓄水池由一個一個小的池子隔離開來,這樣如果某一個水池的水被污染,也不會波及到其它蓄水池,如果只有一個蓄水池,水池被污染,整池水都不可用了。軟體資源隔離如出一轍,如果採用資源隔離模式,將對遠程服務的調用隔離到一個單獨的線程池后,若服務提供者不可用,那麼受到影響的只會是這個獨立的線程池。

(1)線程池隔離模式:使用一個線程池來存儲當前的請求,線程池對請求作處理,設置任務返回處理超時時間,堆積的請求堆積入線程池隊列。這種方式需要為每個依賴的服務申請線程池,有一定的資源消耗,好處是可以應對突發流量(流量洪峰來臨時,處理不完可將數據存儲到線程池隊里慢慢處理)。這個大家都比較熟悉,參考Java自帶的ThreadPoolExecutor線程池及隊列實現。線程池隔離參考下圖:

線程隔離的優點:

  • 請求線程與依賴代碼的執行線程可以完全隔離第三方代碼;

  • 當一個依賴線程由失敗變成可用時,線程池將清理后並立即恢復可用;

  • 線程池可設置大小以控制併發量,線程池飽和后可以拒絕服務,防止依賴問題擴散。

線程隔離的缺點:

  • 增加了處理器的消耗,每個命令的執行涉及到排隊(默認使用SynchronousQueue避免排隊)和調度;

  • 增加了使用ThreadLocal等依賴線程狀態的代碼複雜性,需要手動傳遞和清理線程狀態。

(2)信號量隔離模式:使用一個原子計數器來記錄當前有多少個線程在運行,請求來先判斷計數器的數值,若超過設置的最大線程個數則丟棄該類型的新請求,若不超過則執行計數操作請求來計數器+1,請求返回計數器-1。這種方式是嚴格的控制線程且立即返回模式,無法應對突發流量(流量洪峰來臨時,處理的線程超過數量,其他的請求會直接返回,不繼續去請求依賴的服務),參考Java的信號量的用法。

Hystrix默認採用線程池隔離機制,當然用戶也可以配置 HystrixCommandProperties為隔離策略為ExecutionIsolationStrategy.SEMAPHORE。

信號隔離的特點:

  • 信號隔離與線程隔離最大不同在於執行依賴代碼的線程依然是請求線程,該線程需要通過信號申請;

  • 如果客戶端是可信的且可以快速返回,可以使用信號隔離替換線程隔離,降低開銷。

線程池隔離和信號隔離的區別見下圖,使用線程池隔離,用戶請求了15條線程,10條線程依賴於A線程池,5條線程依賴於B線程池;如果使用信號量隔離,請求到C客戶端的信號量若設置了15,那麼圖中左側用戶請求的10個信號與右邊的5個信號量需要與設置閾值進行比較,小於等於閾值則執行,否則直接返回。

建議使用的場景:根據請求服務級別劃分不同等級業務線程池,甚至可以將核心業務部署在獨立的伺服器上。

3.2 熔斷器機制

熔斷器與家裡面的保險絲有些類似,當電流過大時,保險絲自動熔斷以保護我們的電器。假設在沒有熔斷器機制保護下,我們可能會無數次的重試,勢必持續加大服務端壓力,造成惡性循環;如果直接關閉重試功能,當服務端又可用的時候,我們如何恢復?

熔斷器正好適合這種場景:當請求失敗比率(失敗/總數)達到一定閾值后,熔斷器開啟,並休眠一段時間,這段休眠期過後熔斷器將處與半開狀態(half-open),在此狀態下將試探性的放過一部分流量(Hystrix只支持single request),如果這部分流量調用成功后,再次將熔斷器閉合,否則熔斷器繼續保持開啟並進入下一輪休眠周期。

建議使用場景:Client端直接調用遠程的Server端(server端由於某種原因不可用,從client端發出請求到server端超時響應之間佔用了系統資源,如內存,資料庫連接等)或共享資源。

不建議的場景如下:

  • 應用程序直接訪問如內存中的數據,若使用熔斷器模式只會增加系統額外開銷。

  • 作為業務邏輯的異常處理替代品。

總結思考

本文從自己曾經開發的項目應用的分散式架構引出服務的雪崩效應,進而引出Hystrix(當然了,Hystrix還有很多優秀的特性,如緩存,批量處理請求,主從分擔等,本文主要介紹了資源隔離和熔斷)。主要分三部分進行說明:

第一部分:以耕種田地的思想引出軟體領域設計的微服務架構, 簡單的介紹了其優點,著重介紹面臨的挑戰:雪崩問題。

第二部分:以Tomcat Container在高併發下崩潰為例揭示了雪崩產生的過程,進而總結了幾種誘發雪崩的場景及各種場景的應對解決方案,針對同步等待引出了Hystrix框架。

第三部分:介紹了Hystrix背景,資源隔離(總結了線程池和信號量特點)和熔斷機制工作過程,並總結各自使用場景。

如Martin Fowler 在其文中所說,儘管微服務架構未來需要經歷時間的檢驗,但我們已經走在了微服務架構轉型的道路上,對此我們可以保持謹慎的樂觀,這條路依然值得去探索。

作者介紹

魏春雷,現任高級軟體工程師,為普元新一代數字化企業雲平台開發團隊的一員,先後參與SRM(軟體資源管理)和負責SCM(軟體配置管理)領域系統的開發。2011年碩士畢業於西安交通大學電信學院,後進入華為西安研究所固定網路接入部門,先後開發了接入網的智能光纖規劃和分散式網路評估系統。2016年進入普元信息,業餘愛好:平時喜歡騎行、籃球、羽毛球和唱歌。

推薦一個對技術人員的成長很有幫助的線下會議,將於4月16~18日舉行的QCon全球軟體開發大會(北京站),目前已經邀請來自Google、Facebook、LinkedIn、Airbnb、百度、阿里巴巴、騰訊等公司的100多位一線技術專家,是難得的線下交流學習的機會。具體詳戳 「 閱讀原文 」驚喜不停!



熱門推薦

本文由 yidianzixun 提供 原文連結

寵物協尋 相信 終究能找到回家的路
寫了7763篇文章,獲得2次喜歡
留言回覆
回覆
精彩推薦