若是「高併發」是爲了讓系統變得「有效率」,能夠抵抗大規模用戶訪問,那限流與熔斷就是爲了讓系統變得「更靠譜」。靠譜包括了高可用性、穩定性、可靠性,作一個「靠譜」的系統須要從不少方面着手,本文着重與你們探討「限流」與「熔斷」。html
本文選自《軟件架構設計:大型網站技術架構與業務架構融合之道》一書。前端
限流在平常生活中很常見,景點限流、遲早高峯限流等。對應到計算機中,好比要辦活動、秒殺等,一般會限流。限流能夠分爲技術層面的限流和業務層面的限流。技術層面的限流比較通用,各類業務場景均可以用到;業務層面的限流須要根據具體的業務場景作開發。算法
**(1)技術層面的限流。**一種是限制併發數,也就是根據系統的最大資源量進行限制,好比數據庫鏈接池、線程池、Nginx的limit_conn模塊;另外一種是限制速率(QPS),好比Guava的RateLimiter、Nginx的limit_req模塊。數據庫
限制速率的這種方式對於服務的接口調用很是有用。好比經過壓力測試能夠知道服務的QPS是2000,就能夠限流爲2000QPS。當調用方的併發量超過了這個數字,會直接拒絕提供服務。這樣一來,即便忽然有大量的請求進來,服務也不會被壓垮,雖然部分請求被拒絕了,但保證了其餘的服務能夠正常處理。通常成熟的RPC框架都有相應的配置,能夠對每一個接口進行限流,不須要業務人員本身開發。架構
**(2)業務層面的限流。**好比在秒殺系統中,一個商品的庫存只有100件,如今有2萬人搶購,沒有必要放2萬我的進來,只須要放前500我的進來,後面的人直接返回已售完便可。併發
針對這種業務場景,能夠作一個限流系統,或者叫售賣的資格系統(票據系統),票據系統裏面存放了500張票據,每來一我的,領一張票據。領到票據的人再進入後面的業務系統進行搶購;對於領不到票據的人,則返回已售完。框架
在具體實現上,有團隊使用Redis,也有團隊直接基於Nginx + Lua腳原本實現,二者的思路相似。高併發
**(3)限流算法。**限制併發數的計算原理很簡單,系統只須要維護正在使用的資源數或空閒數,好比數據庫的鏈接數、線程池的線程數。限制速率的算法稍微複雜,經常使用的有漏桶算法和令牌桶算法,下面詳細介紹。測試
▊ 漏桶算法網站
▊ 令牌桶算法
對比兩個算法會發現,兩者的原理恰好相反,一個是流出速率保持恆定,一個是流入速率保持恆定。兩者的用途有必定差異:令牌桶限制的是平均流入速率,而不是瞬時速率,由於可能出現一段時間沒有請求進來,令牌桶裏塞滿了令牌,而後短期內突發流量過來,一瞬間(能夠認爲是同時)從桶裏拿幾個令牌出來;漏桶有點相似消息隊列,起到了削峯的做用,平滑了突發流入速率。
當電路發生短路、溫度升高,可能燒燬整個電路的時候,保險絲會自動熔斷,切斷電路,從而保護整個電路系統。
在計算機系統中,也有相似設計保險絲的思路。熔斷有兩種策略:一種是根據請求失敗率,一種是根據請求響應時間。
**(1)根據請求失敗率作熔斷。**對於客戶端調用的某個服務,若是服務在短期內大量超時或拋錯,則客戶端直接開啓熔斷,也就是再也不調用此服務。而後過一段時間,再把熔斷打開,若是還不行,則繼續開啓熔斷。這也正是常常提到的「快速失敗(Fail Fast)」原則。
以Hystrix爲例,它有幾個參數來配置熔斷器的策略:
circuitBreaker.requestVolumeThreshold //滑動窗口的大小,默認爲20 circuitBreaker.sleepWindowInMilliseconds //過多長時間,熔斷器再次檢測是否開啓,默認爲5000,即5s circuitBreaker.errorThresholdPercentage //失敗率,默認爲50%
三個參數放在一塊兒,所表達的意思是:每20個請求中,有50%失敗時,熔斷器就會打開,此時再調用此服務,將會直接返回失敗,再也不調用遠程服務。直到5s以後,從新檢測該觸發條件,判斷是否把熔斷器關閉,或者繼續打開。
**(2)根據請求響應時間作熔斷。**除了根據請求失敗率作熔斷,阿里巴巴公司的Sentinel還提供了另一種思路:根據請求響應時間作熔斷。當資源的平均響應時間超過閾值後,資源進入準降級狀態。接下來若是持續進入5個請求,且它們的RT持續超過該閾值,那麼在接下來的時間窗口內,對這個方法的調用都會自動地返回。代碼樣例以下:
DegradeRule rule = new DegradeRule(); rule.setResource(「xxx」); rule.setCount(50); rule.setGrade(RuleConstant.DEGRADE_GRADE_RT); rule.setTimeWindow(5000);
樣例中的時間單位是ms,意思是當平均響應時間大於50ms,而且接下來持續5個請求的RT都超過50ms時,熔斷將開啓。5000ms以後,熔斷將再次關閉。
與限流進行對比會發現:限流是服務端,根據其能力上限設置一個過載保護;而熔斷是調用端對本身作的一個保護。
注意:能熔斷的服務確定不是核心鏈路上的必選服務。若是是的話,則服務若是超時或者宕機,前端就不能用了,而不是熔斷。因此,說熔斷其實也是降級的一種方式。
《軟件架構設計:大型網站技術架構與業務架構融合之道》
餘春龍 著
自成一派的架構設計方法論,教你體系化的架構設計思惟,點擊瞭解本書詳情。
系統的高可用性、穩定性與可靠性須要從不少方面着手,本文帶你瞭解如何經過「限流」與「熔斷」讓系統變得「更靠譜」。