限流的作用:
應對
1.熱點業(yè)務帶來的突發(fā)請求
2.調(diào)用方 bug 導致的突發(fā)請求
3.惡意攻擊的請求
常見的限流算法有
1)固定窗口計數(shù)器:將時間劃分為多個窗口;在每個窗口內(nèi)每有一次請求就講計數(shù)器+1;如果計數(shù)器超過了限制的數(shù)量活尊,則本窗口內(nèi)所有的請求都被丟棄,當時間到達下一個窗口時脖旱,計數(shù)器重置。
算法問題:會讓通過請求量是允許量的兩倍。
2)滑動窗口計數(shù)器:將時間劃分為多個區(qū)間搔课;在每個區(qū)間沒有一次請求就將計數(shù)器+1維持一個時間窗口,占據(jù)多個區(qū)間截亦;每經(jīng)過一個區(qū)間時間爬泥,則拋棄最老的一個區(qū)間柬讨,并納入最新的一個區(qū)間;如果當前窗口內(nèi)區(qū)間的請求技術總和超過了限制的數(shù)量袍啡,則本窗口內(nèi)所有的請求都被丟棄踩官。
問題:滑動窗口計數(shù)器是通過將窗口再細分,并且按照時間"滑動"境输,這種算法避免了固定窗口計數(shù)器帶來的雙倍突發(fā)請求蔗牡,但時間區(qū)間的精度越高,算法需要的空間容量越大嗅剖。
3)漏桶算法:將每個請求看做'水滴'放入'漏桶' 進行存儲辩越;'漏桶'以固定的速率向外'漏'出請求來執(zhí)行,如果'漏桶'空了則停止'漏水'窗悯;如果'漏桶'滿了則多余的'水滴'會被直接丟棄区匣;
漏桶算法多使用消息隊列實現(xiàn)偷拔,服務的請求會存到隊列中蒋院,服務的提供方按照固定的速度從隊列中去除請求并執(zhí)行,過多的請求則放在隊列中排隊或者直接拒絕莲绰。
漏桶算的缺點是欺旧,當短時間內(nèi)有大量的突發(fā)請求時,即便此時服務器沒有任何負載蛤签,每個請求也得再隊列中等待一段時間才能被響應辞友。
4)令牌桶:令牌以固定的速率生成;生成的令牌放入令牌桶中存放震肮,如果令牌桶滿了則多余的令牌會被直接丟棄称龙,當請求到達時,會嘗試從令牌桶中取令牌戳晌,取到了令牌的請求可以執(zhí)行鲫尊;如果桶空了,那么嘗試取令牌的請求 會被直接丟棄沦偎。
令牌桶算法就能夠?qū)⑺?的請求平均分不到時間區(qū)間內(nèi)疫向,又能接受服務器能夠承受范圍內(nèi)的突發(fā)請求,一次是目前使用廣泛的一種限流算法豪嚎。
開源的限流項目:
Google 的開源項目 guava 提供了 RateLimiter 類搔驼,實現(xiàn)了單點的令牌桶限流。
限流策略:多維防護+縱身防御
常見的三種:限制請求數(shù)侈询,限制并發(fā)連接數(shù) (請求頻率)舌涨,限制傳輸速度(請求體積)
各層級限流:
全局統(tǒng)一接入:
google 叫 GFE,baidu 是BFE扔字,jd 叫 GFE泼菌,這類產(chǎn)品會將公司所有對外流量進行統(tǒng)計的接入呵呵調(diào)度谍肤,同時具備較強的通用防護能力,比如抗 D,WAF等哗伯。
熔斷:
熔斷的本質(zhì)是一個過載保護機制荒揣。互聯(lián)網(wǎng)系統(tǒng)中通常是:當下游服務因為訪問壓力過大而響應變慢或者失敗焊刹,上游服務為了保護自己以及系統(tǒng)整體的可用性系任,可以暫時切斷對下游服務的調(diào)用。
熔斷的思路:
中心思想:量力而行虐块。沒有奇跡會發(fā)生俩滥,什么樣的性能撐多少流量是固定的。
四個步驟:
1.定一個識別是否處于"不可用"狀態(tài)的策略贺奠;
2.切斷聯(lián)系
3.定義一個識別是否處于'可用'狀態(tài)的策略霜旧,并嘗試探測;
4.重新恢復正常
如何識別是否處于不正常的策略:
1.是不是能調(diào)通
2.如果能夠調(diào)通儡率,耗時是不是超過預期的長
由于網(wǎng)絡并不是100%的可靠挂据,所以不能將瞬時異常等同于系統(tǒng)不可用。
如何解決這個問題呢:時間窗口儿普,在某個時間段內(nèi) 的情況
比如:
閾值:在10s 內(nèi)出現(xiàn)100次無法連接或者出現(xiàn)大于100次大于5s 的請求
百分比:在10s 內(nèi)有30%的請求無法連接或者30%的請求大 于5s崎逃。
切斷聯(lián)系:
切斷聯(lián)系要盡可能的果斷,既然已經(jīng)認定了對方不可用眉孩,那么索性默認失敗个绍,避免作無用功,也可以緩解對方的壓力浪汪。
定義一個識別是否處于可用的狀態(tài)的策略巴柿,并嘗試探測
切斷聯(lián)系后,功能的完整性必然會受到影響死遭,所以還是要盡快恢復回來广恢,以提供完整的服務能力。如何自動的識別依賴系統(tǒng)是否可用呢殃姓≡ǎ可以考慮的策略如下:
一般來說 這個策略與識別不可用的策略類似,是個反向指標:
?閾值蜗侈。比如篷牌,在 10 秒內(nèi)出現(xiàn) 100 次“調(diào)用成功”并且耗時都小于 1 秒。
百分比踏幻。比如枷颊,在 10 秒內(nèi)有 95% 請求“調(diào)用成功”并且 98% 的請求小于 1 秒。
但是驗證可用是個復雜的過程:
1.按照一定的比例流量去驗證;
2.如果在整個通信框架都是統(tǒng)一的情況下夭苗,可以統(tǒng)一給每個系統(tǒng)增加一個專門用于驗證程序健康狀態(tài)的檢測的獨立接口信卡。這個接口額外可以多返回一些系統(tǒng)負載信息用于判斷健康狀態(tài),如 CPU题造、I/O 的情況等傍菇。
重新恢復正常
一旦通過了衡量可否可用的驗證,整個系統(tǒng)就恢復了正常的狀態(tài)界赔。重新開啟不可用策略丢习。這樣整體就是一個循環(huán)。
做熔斷的最佳實踐
什么場景最適合做熔斷
一個事物在不同的場景里會發(fā)揮出不同的效果淮悼。以下是我能想到最適合熔斷發(fā)揮更大優(yōu)勢的幾個場景:
? 所依賴的系統(tǒng)本身是一個共享系統(tǒng)咐低,當前客戶端只是其中的一個客戶端。這是因為袜腥,如果其它客戶端進行胡亂調(diào)用也會影響到你的調(diào)用见擦。
? 所以依賴的系統(tǒng)被部署在一個共享環(huán)境中(資源未做隔離),并不獨占使用羹令。比如鲤屡,和某個高負荷的數(shù)據(jù)庫在同一臺服務器上。
? 所依賴的系統(tǒng)是一個經(jīng)常會迭代更新的服務特恬。這點也意味著执俩,越“敏捷”的系統(tǒng)越需要“熔斷”徐钠。
? 當前所在的系統(tǒng)流量大小是不確定的癌刽。比如,一個電商網(wǎng)站的流量波動會很大尝丐,你能抗住突增的流量不代表所依賴的后端系統(tǒng)也能抗住显拜。這點也反映出了我們在軟件設計中帶著“面向懷疑”的心態(tài)的重要性。
需要注意的地方:
1.依賴系統(tǒng)的個別節(jié)點異常不等于所有的節(jié)點異常
2.熔斷是最后的選擇爹袁,優(yōu)先使用降級或者限流的方案远荠。因為'部分勝于無',雖然無法提供完整的服務失息,但盡可能的降低影響譬淳。比如,拋棄非核心業(yè)務盹兢,友好提示等邻梆;