近年來,各大廠Google、微軟、阿里、騰訊等都在提高可用的概念。高可用(High Availability,簡稱HA)是指系統(tǒng)或服務(wù)在遭受故障或異常情況時仍能持續(xù)提供穩(wěn)定和可靠的運行能力。
在武俠世界里,“利器”通常指的是武器中的上乘、出色之物;武器對于武者的重要性不言而喻,擁有一把優(yōu)秀的武器可以讓武者在戰(zhàn)斗中更加得心應(yīng)手,威力更強。
在分布式系統(tǒng)追求高可用的背景下,熔斷、限流和降級這三個重要的策略可以稱得上三大利器。
熔斷(Circuit Breaker):熔斷是一種防止故障擴散的策略。當(dāng)一個服務(wù)出現(xiàn)故障或超時,熔斷器會打開并快速失敗,拒絕后續(xù)的請求,避免請求堆積和資源耗盡。熔斷器會暫時屏蔽該服務(wù),并在一段時間后嘗試恢復(fù)。熔斷器的狀態(tài)變化可用于監(jiān)控系統(tǒng)健康和提供告警信息。
限流(Rate Limiting):限流是一種控制系統(tǒng)請求流量的策略。通過設(shè)置一個請求速率閾值,限流可以限制每個客戶端或用戶在特定時間內(nèi)的請求次數(shù)。這樣可以防止過多的請求涌入系統(tǒng),保護系統(tǒng)免受過載和壓力沖擊。限流可以平滑流量,避免系統(tǒng)突發(fā)流量的影響。
降級(Fallback):降級是一種在面對特殊業(yè)務(wù)或異常情況時保持系統(tǒng)可用的策略。當(dāng)服務(wù)不可用時,降級服務(wù)會代替提供一些基本功能或返回預(yù)設(shè)的默認(rèn)值,以確保系統(tǒng)依然能夠提供有限的功能或服務(wù);又或者某些特定活動場景(例如:雙十一)下優(yōu)先保障計算資源投入到 業(yè)務(wù)傾向的服務(wù),降級邊緣服務(wù)。
熔斷(Circuit Breaker)
在分布式架構(gòu)中,一個服務(wù)通常會與多個外部服務(wù)進行交互,這些外部服務(wù)可能是RPC接口、數(shù)據(jù)庫、第三方API等。例如,在支付過程中,可能需要調(diào)用銀聯(lián)提供的API;而查詢某個商品的價格,則可能需要進行營銷活動查詢。然而,除了自身服務(wù)外,依賴的外部服務(wù)的穩(wěn)定性是無法絕對保證。
當(dāng)依賴的第三方服務(wù)出現(xiàn)不穩(wěn)定的情況時,例如三方服務(wù)器過載,會導(dǎo)致服務(wù)自身調(diào)用第三方服務(wù)的響應(yīng)時間也變長,甚者形成級聯(lián)效應(yīng)。這樣一來,服務(wù)自身的線程可能會積壓,最終可能耗盡業(yè)務(wù)自身的線程池,導(dǎo)致服務(wù)本身變得不可用。
熔斷(Circuit Breaker)就是應(yīng)對這種三方服務(wù)不穩(wěn)定的設(shè)計,它可以幫助系統(tǒng)在出現(xiàn)問題時保持高可用,防止故障進一步擴散,同時也能在一段時間后重新嘗試恢復(fù)正常操作。避免局部不穩(wěn)定因素導(dǎo)致整個分布式系統(tǒng)的雪崩。作為保護服務(wù)自身的手段,通常在客戶端(調(diào)用端)進行配置。
熔斷器模式(Circuit Breaker Pattern),是Michael Nygard在他的著作《Release It!》中開始推薦使用的。其可以防止應(yīng)用程序反復(fù)嘗試執(zhí)行可能會失敗的操作,使其能夠繼續(xù)進行而無需等待故障被修復(fù),也無需浪費CPU周期來確定故障是否持久。Circuit Breaker模式還使應(yīng)用程序能夠檢測故障是否已解決。如果問題似乎已經(jīng)解決,應(yīng)用程序可以嘗試調(diào)用該操作。
注:這種設(shè)計也是典型的 快速失敗原則(Fail-Fast Principle) 的應(yīng)用。強調(diào)在面對錯誤或異常情況時,系統(tǒng)應(yīng)該盡早地檢測并快速失敗,而不是繼續(xù)執(zhí)行可能導(dǎo)致更嚴(yán)重后果的操作。這個原則的目的是盡早發(fā)現(xiàn)問題并及時處理,避免故障進一步擴大,從而提高系統(tǒng)的穩(wěn)定性和可靠性。
熔斷器模式中最關(guān)鍵的設(shè)計在于熔斷器的三種狀態(tài):
-
Closed狀態(tài):來自應(yīng)用程序的請求被 Proxy 操作。Proxy 維護最近故障次數(shù)的計數(shù),如果對操作的調(diào)用不成功,Proxy 會增加這個計數(shù)。如果在給定的時間段內(nèi)最近故障的次數(shù)超過了指定的閾值,Proxy 將進入Open狀態(tài)。此時,Proxy 啟動一個超時計時器,當(dāng)計時器到達閾值時,Proxy 將進入Half-Open狀態(tài)。(這里 Proxy 代指 Resilience4j、Sentinel、Hystrix類似框架)
-
Open狀態(tài):來自應(yīng)用程序的請求立即失敗,并向應(yīng)用程序返回異常。
-
Half-Open狀態(tài):應(yīng)用程序允許有限數(shù)量的請求通過并調(diào)用操作。如果這些請求成功,假定之前導(dǎo)致失敗的故障已經(jīng)修復(fù),將切換到Closed狀態(tài)(故障計數(shù)器被重置)。如果任何請求失敗,會認(rèn)為故障仍然存在,因此它會回退到Open狀態(tài),并重新啟動超時計時器,為系統(tǒng)提供進一步的時間來從故障中恢復(fù)。。
許多開源的框架都基于這三個狀態(tài)進行了熔斷實現(xiàn)的設(shè)計,比如:Resilience4j、Sentinel、Hystrix;就實際使用上推薦 Sentinel 和 Resilience4j ,因為 Hystrix 已經(jīng)宣布不維護了。附上,一張網(wǎng)上廣泛流傳的對比表格 [1]
開源框架僅僅只是熔斷機制的代碼實現(xiàn),更重要的在于結(jié)合具體業(yè)務(wù)常見來設(shè)計相關(guān)的熔斷策略。這里列出一些通常具體業(yè)務(wù)設(shè)計熔斷時候的考量點:
熔斷異常應(yīng)該如何處理:三方服務(wù)處于在熔斷 Open狀態(tài)下,應(yīng)該如何進行服務(wù)的返回。比如:用一個默認(rèn)值來替代三方服務(wù)的返回結(jié)果;返回異常頁面告知用戶稍后再重試;調(diào)用其他的服務(wù)來替代原來的功能等。異常往往多樣的,也可以考慮不同異常下設(shè)置不同的處理方式。
應(yīng)該記錄詳細日志:注意異常日志的記錄,確保關(guān)鍵信息都寫入日志,往往線上故障異常的多樣的;好的日志格式/日志設(shè)計能夠快速的定位問題、監(jiān)控熔斷策略符合預(yù)期。熔斷狀態(tài)的轉(zhuǎn)換需要詳細寫入,方便復(fù)盤熔斷策略。
是否需要診斷定時程序:當(dāng)處于熔斷 Open狀態(tài)時,考慮是否需要來做個定時程序 測試三方服務(wù)是否恢復(fù)并轉(zhuǎn)換 到 Half-Open狀態(tài),更靈活的恢復(fù)服務(wù)。
管理熔斷的工具:由于異常是多樣的,某些情況下意外觸發(fā)了熔斷;此時管理員可以通過熔斷工具來恢復(fù)相關(guān)狀態(tài),應(yīng)對熔斷策略出現(xiàn)問題的情況。
注意三方服務(wù)耗時:有時候三方服務(wù)能夠正常返回但耗時很長,這樣可能會導(dǎo)致自身服務(wù)的超時;針對這種情況應(yīng)該進行相關(guān)超時熔斷處理,應(yīng)該關(guān)注這種隱蔽的超時異常。
限流(Rate Limit)
無論服務(wù)器的硬件多么強大,總歸也是有限的資源只能處理有限的請求;簡單理解限流(Rate Limit)的話,在有限時間內(nèi)請求數(shù)量超過服務(wù)的處理數(shù)量,自動丟棄新來的請求從而保障有限的請求高可用。
用日常例子來類比說明就很好理解,一個餐廳只有5張四人桌,理想坐滿的情況也也就是20個人;而如果涌進來50個人都點單,那么每個人都無法正常的用餐。因此,要限制進來的人數(shù)是保障正常用餐。
同樣的對于系統(tǒng)而言,一次性接受超出硬件承載的資源,就會導(dǎo)致資源的劇烈競爭從而 導(dǎo)致請求服務(wù)的延遲、異常等等,無法提供到高可用的服務(wù)。為此,對服務(wù)進行限流保護是提供高可用的重要策略了。
以下是常見的限流算法:
固定窗口計數(shù)限流算法(Fixed Window Counter):在固定的時間窗口內(nèi),限制請求的數(shù)量。例如,在1秒內(nèi)最多允許處理10個請求,當(dāng)窗口滿時,后續(xù)請求將被拒絕。
滑動窗口計數(shù)限流算法(Sliding Window Counter):設(shè)置一個滑動時間窗口,計算在該時間窗口內(nèi)的請求數(shù)量,并限制其在指定范圍內(nèi)。與固定窗口計數(shù)算法相比,滑動窗口算法允許更加靈活的流量控制。
令牌桶算法(Token Bucket):令牌桶算法通過將請求放入令牌桶中來控制流量。每個請求需要從令牌桶中獲取令牌,如果桶中沒有足夠的令牌,則請求被拒絕。令牌桶算法允許突發(fā)流量一定程度的處理,并平滑了請求的速率。
- 令牌桶是一個固定容量的桶,它以恒定的速率產(chǎn)生令牌(即令牌產(chǎn)生速率),并將其放入桶中。
- 桶中最大可以保存的令牌數(shù)量為桶的容量,當(dāng)桶滿時,多余的令牌會被丟棄。
- 每當(dāng)有請求到達時,如果令牌桶中有足夠的令牌,該請求會獲取一個令牌,并被處理。如果桶中沒有令牌可用,該請求將被延遲或丟棄。
- 令牌桶可以應(yīng)用于固定窗口計數(shù)限流算法和滑動窗口計數(shù)限流算法。在固定窗口計數(shù)限流中,令牌桶以固定速率產(chǎn)生令牌,而在滑動窗口計數(shù)限流中,令牌桶按照滑動時間窗口的速率產(chǎn)生令牌。
令牌桶算法的優(yōu)點在于,它可以平滑地處理突發(fā)流量,即使在短時間內(nèi)有大量請求到達,令牌桶算法仍然能夠保持相對穩(wěn)定的速率來處理這些請求。此外,令牌桶算法還可以允許一定程度的突發(fā)流量,因為桶中積累的令牌可以處理突發(fā)的請求。令牌桶算法的缺點是在某些情況下可能會導(dǎo)致請求的延遲。如果請求到達時桶中沒有足夠的令牌,該請求將被延遲等待令牌,可能會導(dǎo)致響應(yīng)時間增加。
漏桶算法(Leaky Bucket):漏桶算法將請求放入一個漏桶中,請求以恒定的速率從漏桶中流出。如果漏桶已滿,則多余的請求將被拒絕。漏桶算法可以用于平滑流量,防止突發(fā)請求造成的資源浪費。
- 漏桶是一個固定容量的桶,它有一個漏口。桶底的漏口以固定的速率(即令牌產(chǎn)生速率)漏水。
- 每個請求都會向漏桶中添加一個令牌。如果漏桶已滿(即桶內(nèi)令牌數(shù)量達到了最大容量),則新的令牌會被丟棄。
- 當(dāng)請求到達時,如果漏桶中有可用的令牌,則請求被處理,且漏桶中的令牌數(shù)量減少一個。如果漏桶中沒有足夠的令牌,則請求被丟棄或延遲處理。
漏桶算法的優(yōu)點在于,它能夠以固定的速率來處理請求,從而平滑流量,防止突發(fā)請求對系統(tǒng)造成過大的壓力。此外,漏桶算法還能夠控制流出速率,避免資源的浪費;然而,漏桶算法的缺點是對于突發(fā)流量的處理相對較差。如果漏桶中的令牌數(shù)量耗盡,那么突發(fā)流量的請求會被丟棄,可能會導(dǎo)致某些請求的延遲。
降級(Fallback)
不知道大家是否有經(jīng)歷,當(dāng)在樓下沙縣小店吃面時,如果小店人不多的情況下 店員會端上一碟小菜給到我們;而人很多的情況,如果想吃小菜可以自己去窗口附近用小蝶裝取。換個角度,這其實也可以稱得上服務(wù)降級。
服務(wù)降級往往指在面對系統(tǒng)過載、資源不足、有計劃的大型活動(雙十一),有意識地降低系統(tǒng)的部分功能或服務(wù)質(zhì)量,以保證系統(tǒng)的核心功能和關(guān)鍵服務(wù)仍能繼續(xù)正常運行。
舉個例子,電商系統(tǒng)中支持 商家對商品的價格調(diào)整 是一種非常常見的功能,但當(dāng) 雙十一零點的時刻 往往會和商家達成一致 不提供在零點后一段時間內(nèi)商品價格的調(diào)整服務(wù),以用來保障零點活動的高效執(zhí)行。
所以降級是一種非常規(guī)應(yīng)對措施,不應(yīng)該成為長期的解決方案。一旦面對情況有所改變就應(yīng)該恢復(fù)降級的服務(wù),確保系統(tǒng)能夠正常提供全部功能和服務(wù)。
降級本身的實現(xiàn)是根據(jù)具體業(yè)務(wù)規(guī)則來進行編碼,常見的設(shè)計有:
開關(guān)硬編碼: 用一個參數(shù)標(biāo)識是否進行降級,在服務(wù)中用 if 來判斷標(biāo)識 從而進行相關(guān)服務(wù)降級的業(yè)務(wù)邏輯。如果時間很短情況下要實現(xiàn)降級,可能是最直接最常見的選擇。
AOP攔截:通過 AOP切面面編程攔截服務(wù)請求,并更加服務(wù)降級的業(yè)務(wù)要求條件,調(diào)用降級服務(wù)請求。因為使用到了 AOP切面技術(shù),代碼侵入性小,但代碼可讀性差;如果沒有一些注釋說明,不熟悉相關(guān)業(yè)務(wù)的研發(fā)者忽略了降級攔截。
策略/工廠設(shè)計模式:在服務(wù)設(shè)計的時候采用工廠 或者 策略的設(shè)計模式,根據(jù)降級業(yè)務(wù)要求條件來進行策略/工廠的具體服務(wù)生成,從而實現(xiàn)服務(wù)降級邏輯。代碼邏輯實現(xiàn)上會復(fù)雜些,可能帶來更多類,可讀性上對于設(shè)計模式不熟悉的研發(fā)者造成疑惑。
三者的關(guān)系
行文至此,也許有部分讀者困惑比如:降級和熔斷是不是一回事?熔斷后執(zhí)行策略就相當(dāng)于降級?
糾結(jié)于這些問題的本身,還是要回到文章開頭三大策略提出所面對解決的高可用問題。熔斷是針對防止故障擴散所進行的策略設(shè)計,而 降級面對的是特殊場景的 服務(wù)功能/質(zhì)量的調(diào)整策略。
因此,可以看到 描述降級中提到的 雙十一零點前關(guān)閉商家價格調(diào)整的功能,顯然 并非為了防止故障擴散的措施而是保障其他業(yè)務(wù)關(guān)注功能性能(不是熔斷,主動改變);同樣的,也可以舉個例子當(dāng)調(diào)用某個服務(wù)失敗高時,切換調(diào)用到備用服務(wù)器來作為熔斷處理策略,此時提供的服務(wù)功能或許都沒有變化,只是啟動了熔斷一種技術(shù)處理策略(不屬于服務(wù)降級)。
兩者并非一回事。但如果考慮到 熔斷發(fā)生時,處理的方式是 調(diào)整某種產(chǎn)品功能服務(wù),那其實既可以算熔斷也可以算降級,所以有些文章中也有提到 熔斷降級 的概念。限流 與 降級呢? 熔斷 與 限流呢? 在此就不一一贅述了,簡而言之的話,三者都非一回事,但在某些場景下相互支撐。
熔斷、限流、降級這些概念,更多是指導(dǎo) 在分布式系統(tǒng) 高可用設(shè)計上 應(yīng)該考慮方面,其核心目的都是 達到系統(tǒng)的高可用。文章來源:http://www.zghlxwxcb.cn/news/detail-607536.html
轉(zhuǎn)載望能 保留,歡迎關(guān)注 Java研究者 公眾號文章來源地址http://www.zghlxwxcb.cn/news/detail-607536.html
參考文獻
- sentinel 限流熔斷神器詳細介紹 https://blog.csdn.net/a745233700/article/details/122733366
- Release It! Second Edition https://pragprog.com/titles/mnee2/release-it-second-edition/
- Rate Limiting pattern https://learn.microsoft.com/en-us/azure/architecture/patterns/rate-limiting-pattern
- Computer Network | Leaky bucket algorithm https://www.geeksforgeeks.org/leaky-bucket-algorithm/
- Fallback pattern https://badia-kharroubi.gitbooks.io/microservices-architecture/content/patterns/communication-patterns/fallback-pattern.html
到了這里,關(guān)于高可用三大利器 — 熔斷、限流和降級的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!