跟著毛老師學高可用

分類:技術 時間:2016-09-23

HA (High Availability)

(本文根據毛老師(浪客劍心)在b站內部技術分享會總結)

高可用性H.A.(High Availability)指的是通過盡量縮短因日常維護操作(計劃)和突發的系統崩潰(非計劃)所導致的停機時間,以提高系統和應用的可用性。它與被認為是不間斷操作的容錯技術有所不同。HA系統是目前企業防止核心計算機系統因故障停機的最有效手段。

一:網絡高可用

由于網絡存儲的快速發展,網絡冗余技術被不斷提升,提高IT系統的高可用性的關鍵應用就是網絡高可用性,網絡高可用性與網絡高可靠性是有區別的,網絡高可用性是通過匹配冗余的網絡設備實現網絡設備的冗余,達到高可用的目的。

比如冗余的交換機,冗余的路由器等

二:服務器高可用

服務器高可用主要使用的是服務器集群軟件或高可用軟件來實現。

三:存儲高可用

使用軟件或硬件技術實現存儲的高度可用性。其主要技術指標是存儲切換功能,數據復制功能,數據快照功能等。當一臺存儲出現故障時,另一臺備用的存儲可以快速切換,達一存儲不停機的目的。

隔離

由于業務的復雜性,常采用服務組件化的架構策略來達到解耦和可擴展的目的。在服務按業務功能切分后,如何提高整個系統的可用性是一個非常重要的問題。文章在對大型網站服務組件化設計架構研究的基礎上,結合服務組件之間強弱依賴關系的特點與典型場景,總結了服務隔離技術的基本思想和維度,提供了服務調用解耦與隔離方法、容器級別服務故障隔離方法、組件服務間接依賴故障隔離方法等來提高系統的可用性。

服務解耦、物理隔離

大家都知道一個服務的設計,要盡可能小和分離部署,如此,服務之間的耦合會比較小,一旦某個模塊出問題,受到影響的模塊就比較少,容錯能力就會更強。可是,從設計之初,就將每一個服務有序的切割地很小,這個需要設計者具備超前的意識,能夠提前意識到業務和系統的發展形態,而實際上,業務的發展往往是比較難以預知的,因為業務的形態會隨著產品的策略的改變而變化。在業務早期流量比較小的時候,通常也沒有足夠的人力和資源,將服務細細的切分。

輕重分離,物理隔離

以我們支持2016年“手Q春節紅包”活動項目的服務集群。就將負責信息查詢和紅包禮包發貨的集群分別獨立部署,信息查詢的服務相對沒有那么重要,業務流程比較輕量級,而紅包禮包發貨則屬于非常核心的業務,業務流程比較重。

輕重分離的這個部署方式,可以給我們帶來一些好處:

(1) 查詢集群即使出問題,也不會影響發貨集群,保證用戶核心功能正常。

(2) 兩邊的機器和部署的服務基本一致,在緊急的情況下,兩邊的集群可以相互支援和切換,起到容災的效果。

(3) 每個集群里的機器,都是跨機房部署,例如,服務器都是分布在ABC三個機房,假設B機房整個網絡故障了,反向代理服務會將無法接受服務的B機房機器剔除,然后,剩下AC機房的服務器仍然可以正常為外界提供服務。

超時

設置合理超時

調用任何一個服務或者存儲,一個合理的超時時間(超時時間,就是我們請求一個服務時,等待的最長時間),是非常重要的,而這一點往往比較容易被忽視。通常Web系統和后端服務的通信方式,是同步等待的模式。這種模式,它會帶來的問題比較多。

對于服務端,影響比較大的一個問題,就是它會嚴重影響系統吞吐率。假設,我們一個服務的機器上,啟用了100個處理請求的worker,worker的超時時間設置為5秒,1個worker處理1個任務的平均處理耗時是100ms。那么1個work在5秒鐘的時間里,能夠處理50個用戶請求,然而,一旦網絡或者服務偶爾異常,響應超時,那么在本次處理的后續整整5秒里,它僅僅處理了1個等待超時的失敗任務。一旦比較大概率出現這類型的超時異常,系統的吞吐率就會大面積下降,有可能耗盡所有的worker(資源被占據,全部在等待狀態,知道5s超時才釋放),最終導致新的請求無worker可用,只能陷入異常狀態。

快慢分離

比如我們的在app-interface項目中需要聚合不同功能的接口,接口的返回時間都不一樣,有快有慢。所以我們采用了快慢分離方案

[httpClient]
dial= quot;100msquot;
timeout= quot;500msquot;
keepAlive = quot;60squot;
timer= 128

[httpIm9]
dial= quot;100msquot;
timeout= quot;800msquot;
keepAlive = quot;60squot;
timer= 128

[httpSearch]
dial= quot;100msquot;
timeout= quot;800msquot;
keepAlive = quot;60squot;
timer= 128

[httpWrite]
dial= quot;100msquot;
timeout= quot;800msquot;
keepAlive = quot;60squot;
timer= 128

限流

在開發高并發系統時有三把利器用來保護系統:緩存、降級和限流。緩存的目的是提升系統訪問速度和增大系統能處理的容量,可謂是抗高并發流量的銀彈;而降級是當服務出問題或者影響到核心流程的性能則需要暫時屏蔽掉,待高峰或者問題解決后再打開;而有些場景并不能用緩存和降級來解決,比如稀缺資源(秒殺、搶購)、寫服務(如評論、下單)、頻繁的復雜查詢(評論的最后幾頁),因此需有一種手段來限制這些場景的并發/請求量,即限流。

限流的目的是通過對并發訪問/請求進行限速或者一個時間窗口內的的請求進行限速來保護系統,一旦達到限制速率則可以拒絕服務(定向到錯誤頁或告知資源沒有了)、排隊或等待(比如秒殺、評論、下單)、降級(返回兜底數據或默認數據,如商品詳情頁庫存默認有貨)。

一般開發高并發系統常見的限流有:限制總并發數(比如數據庫連接池、線程池)、限制瞬時并發數(如nginx的limit_conn模塊,用來限制瞬時并發連接數)、限制時間窗口內的平均速率(如Guava的RateLimiter、nginx的limit_req模塊,限制每秒的平均速率);其他還有如限制遠程接口調用速率、限制MQ的消費速率。另外還可以根據網絡連接數、網絡流量、CPU或內存負載等來限流。

限流算法

常見的限流算法有:令牌桶、漏桶。計數器也可以進行粗暴限流實現。

令牌桶算法

令牌桶算法是一個存放固定容量令牌的桶,按照固定速率往桶里添加令牌。令牌桶算法的描述如下:

假設限制2r/s,則按照500毫秒的固定速率往桶中添加令牌;

桶中最多存放b個令牌,當桶滿時,新添加的令牌被丟棄或拒絕;

當一個n個字節大小的數據包到達,將從桶中刪除n個令牌,接著數據包被發送到網絡上;

如果桶中的令牌不足n個,則不會刪除令牌,且該數據包將被限流(要么丟棄,要么緩沖區等待)。

漏桶算法

漏桶作為計量工具(The Leaky Bucket Algorithm as a Meter)時,可以用于流量整形(Traffic Shaping)和流量控制(TrafficPolicing),漏桶算法的描述如下:

一個固定容量的漏桶,按照常量固定速率流出水滴;

如果桶是空的,則不需流出水滴;

可以以任意速率流入水滴到漏桶;

如果流入水滴超出了桶的容量,則流入的水滴溢出了(被丟棄),而漏桶容量是不變的。

令牌桶和漏桶對比:

令牌桶是按照固定速率往桶中添加令牌,請求是否被處理需要看桶中令牌是否足夠,當令牌數減為零時則拒絕新的請求;

漏桶則是按照常量固定速率流出請求,流入請求速率任意,當流入的請求數累積到漏桶容量時,則新流入的請求被拒絕;

令牌桶限制的是平均流入速率(允許突發請求,只要有令牌就可以處理,支持一次拿3個令牌,4個令牌),并允許一定程度突發流量;

漏桶限制的是常量流出速率(即流出速率是一個固定常量值,比如都是1的速率流出,而不能一次是1,下次又是2),從而平滑突發流入速率;

令牌桶允許一定程度的突發,而漏桶主要目的是平滑流入速率;

兩個算法實現可以一樣,但是方向是相反的,對于相同的參數得到的限流效果是一樣的。

降級

在進行降級之前要對系統進行梳理,看看系統是不是可以丟卒保帥;從而梳理出哪些必須誓死保護,哪些可降級。 為了保證用戶體驗,在資源有限的條件下,我們必須保證關鍵系統的穩定性。通過對不同業務級別定義不同的降級策略,對除核心主流程以外的功能,根據系統壓力情況進行有策略的關閉,從而達到服務降級的目的

(1)拒絕服務

拒絕優先級應用的調用,減少服務調用并發數,保證核心應用正常使用;或者隨機拒絕部分請求調用。

(2)關閉功能

關閉不重要的服務,或者服務內部關閉不重要的功能,以節約系統開銷,為重要的服務和功能讓出資源。

(2)冪等性設計

應用調用服務失敗后,會將調用請求重新發送到其他服務器,但是這個失敗可能是虛假的,如:處理成功,但未受到相應。

等冪性設計在服務層保證服務重復調用和調用一次產生的結果相同,即服務據有等冪性。

容錯

“火”是永遠救不完的,讓系統能夠自動”滅火”,才是解決問題的正確方向。簡而言之,系統的異常不能總是依賴于“人”去恢復,讓系統本身具備“容錯”能力,才是根本解決之道。

重試機制

最容易也最簡單被人想到的容錯方式,當然就是“失敗重試”,總而言之,簡單粗暴!簡單是指它的實現通常很簡單,粗暴則是指使用不當,很可能會帶來系統“雪崩”的風險,因為重試意味著對后端服務的雙倍請求。

簡單重試

我們請求一個服務,如果服務請求失敗,則重試一次。假設,這個服務在常規狀態下是99.9%的成功率,因為某一次波動性的異常,成功率下跌到95%,那么如果有重試機制,那么成功率大概還能保持在99.75%。而簡單重試的缺陷也很明顯,如果服務真的出問題,很可能帶來雙倍流量,沖擊服務系統,有可能直接將服務沖垮。而在實際的真實業務場景,往往更嚴重,一個功能不可用,往往更容易引起用戶的“反復點擊”,反而制造更大規模的流量沖擊。比起服務的成功率比較低,系統直接被沖擊到“掛掉”的后果明顯更嚴重。

簡單重試,要使用在恰當的場景。或者,主動計算服務成功率,成功率過低,就直接不做重試行為,避免帶來過高的流量沖擊。

主備服務自動切換

既然單一服務的重試,可能會給該帶來雙倍的流量沖擊,而最終導致更嚴重的后果,那么我們不如將場景變為主備服務的自動重試或者切換。例如,我們搭建了兩套獲取openid的服務,如果服務A獲取失敗,則嘗試從服務B中獲取。因為重試的請求壓力是壓到了服務B上,服務A通常不會因為重試而產生雙倍的流量沖擊。

這種重試的機制,看似比較可用,而實際上也存在一些問題:

(1) 通常會存在“資源浪費”的問題。因為備份服務系統,很可能長期處于閑置狀態,只有在主服務異常的時候,它的資源才會被比較充分地使用。不過,如果對于核心的服務業務(例如核心數據、營收相關)進行類似的部署,雖然會增加一些機器成本和預算,但這個付出通常也是物有所值的。

(2) 觸發重試機制,對于用戶的請求來說,耗時必然增加。主服務請求失敗,然后再到備份服務請求,這個環節的請求耗時就至少翻倍增長,假設主服務出現連接(connect)超時,那么耗時就更是大幅度增加。一個服務在正常狀態下,獲取數據也許只要50ms,而服務的超時時間通常會設置到500-1000ms,甚至更多,一旦出現超時重試的場景,請求耗時必然大幅度增長,很可能會比較嚴重地影響用戶體驗。

(3) 主備服務一起陷入異常。如果是因為流量過大問題導致主服務異常,那么備份服務很可能也會承受不住這種級別的流量而掛掉。

熔斷機制

該模式的原理類似于家里的電路熔斷器,如果家里的電路發生短路,熔斷器能夠主動熔斷電路,以避免災難性損失。在分布式系統中應用電路熔斷器模式后,當目標服務慢或者大量超時,調用方能夠主動熔斷,以防止服務被進一步拖垮;如果情況又好轉了,電路又能自動恢復,這就是所謂的彈性容錯,系統有自恢復能力。下圖Fig 8是一個典型的具備彈性恢復能力的電路保護器狀態圖,正常狀態下,電路處于關閉狀態(Closed),如果調用持續出錯或者超時,電路被打開進入熔斷狀態(Open),后續一段時間內的所有調用都會被拒絕(Fail Fast),一段時間以后,保護器會嘗試進入半熔斷狀態(Half-Open),允許少量請求進來嘗試,如果調用仍然失敗,則回到熔斷狀態,如果調用成功,則回到電路閉合狀態。

跟著毛老師學高可用


Tags: 高可用性

文章來源:https://xiequan.info/ha-(high-availability)/


ads
ads

相關文章
ads

相關文章

ad