說說限流那些事

說說限流那些事

限流就是限制流量。原來是物理名詞。限流是通過限流電阻使得電路中的某一段電流不超過一個上限。


後面限流使用到多個場景,道路限流、接口限流、景區限流等。直觀理解,就是控制流量,那麼其它流量如何處理呢?常見的處理方式就是拒絕請求。比如道路限流,超過限流值的車輛就不允許上路;接口限流,超過限流值的請求就直接丟棄返回失敗;景區限流,超過限流值的人就阻擋在景區外。


一般來說,限流更爲關注如何限制流量,至於超過限流的處理方式一般不在限流範圍內討論。基本上可以根據具體業務選擇丟棄或者降級處理。


一個雪崩的問題產生

一個生產推送系統,除了正向的推送外,超過一定員工數量的組織變無法全員推達,涉及到一個寫擴散的問題,即一次無法推達所有用戶,此時需要有另外的策略來實現數據推送。


寫擴散,即通過寫入的方式將數據存儲到用戶的存儲空間中,不再依賴服務提供方的數據。比如郵箱就是一種寫擴散的模式,公司老闆給全員寫了一封郵件,全員每個人的收件箱都會收到一封信,無論老闆或者其他員工對信件如何處理,不影響用戶自己的信件數據。


那麼問題來了,寫擴散對於任何系統來說都有一個上限,如果一封郵件同時發給100萬的員工,相信哪個系統也頂不住。對於郵箱來說,可以做一些異步的優化。但是對於實際推送系統來說,往往還依賴很多的系統,比如100萬的用戶名就不大可能能查出來。


那麼這裏可以使用一個非常常見也經典的模式,就是推拉結合。那就是利用用戶客戶端上線等時機來調用服務端數據增量計算,然後下發到客戶端。


開始跑的正常,但是突然某一天業務量暴漲,系統就崩潰了,正向推送成功率極具下跌

屏幕快照 2020-02-17 10.28.23.png


問題排查

開始排查成功率爲什麼會抖動如此嚴重,從表象上來看,是推送依賴的取數據接口大量限流或者超時。和底層系統同學溝通,流量無法繼續擴大,否則會影響其他正常核心調用。

那麼根本問題再哪裏,是因爲總體流量上漲,導致超過取數依賴的接口嗎?至少表象看起來是這樣的。流量也確實翻倍了,但是真正的根源是哪裏呢?


屏幕快照 2020-02-17 10.34.17.png


正向接口確實也翻倍了。但是這個是引起對取數流量劇增的原因嗎? 想知道到底爲何,就必須對下游取數的接口做分析,分析每個場景對取數調用接口的比例,經過打點觀察,驚人的發現,客戶端上線的調用量居然佔用了60%以上的取數接口,也就是說,而且當時客戶端上線上漲了N倍。N倍的調用量佔據了取數接口的主要調用,進而引起取數接口限流,進而導致正向流量受影響,正向受影響後又依賴客戶端上線來恢復數據,形成了一個惡性循環。


問題解決

正常情況下,不需要依賴客戶端上線來恢復數據,只有員工數超大的情況下需要,因此需要對客戶端上線取數做校驗,普通的員工數不做任何處理,另外增加限流邏輯,嚴控客戶端上線的請求量,防止高峯和毛刺壓垮數據源。上線後,發現實際效果良好,正向推送接口成功率基本100%。



限流問題思考

限流是對無法承受外部壓力的自我保護最簡單的一個措施。限流也是有技巧的,是否需要限流、限流值多少、對誰限流等是幾個非常重要的TOPIC。


毛主席說過,革命的首要問題,就是識別誰是敵人,誰是朋友。


限流三要素


對於系統來說,也是一樣,要識別關鍵調用方,一般來說一個接口80%的能力是被20%的業務調用了,只要識別出這個20%,並對20%的業務方做限流處理,即可達到系統自我保護。限流了一個調用量1%的接口,哪怕限流到0了,依然避免不了系統風險。


因此,識別核心調用接口,是設置限流的首要問題


僅僅是限流嗎?不是的,強行限流,系統是保護了,那對業務的影響是什麼,是否導致核心用戶不可用了?因此需要對限流造成的影響做評估。評估限流會導致何種問題,是導致用戶側失敗,還是導致異步接口處理延時,是否需要被調用方降級處理?


因此,評估限流影響,是設置限流的第二個問題


影響也評估了,那麼剩下了唯一一個問題,就是限流值該如何設置的問題了。設置低了,天天限流告警無法提供正常服務;限流高了,還沒命中限流值,系統已經崩潰了。那麼如何設置最佳的限流值?答案是:經驗水位+壓測。

經驗水位是指按照往常的調用的最高峯,設置閾值,防止突然的流量突增導致系統過載。另外要結合的就是壓測,壓測系統的最佳水位值。根據經驗水位+壓測報告,可以得出限流值。


因此,經驗水位+壓測,是設置限流值的最佳實踐


限流方法

常用的限流有計數法和桶法。”計數”又有:固定計數法、滑動窗口計數法,“桶”:漏桶算法、令牌桶算法。這裏簡單介紹一下每個限流方法的原理。

固定計數法

統計1秒內的請求數,超過了指定閾值則丟棄請求,1s後清零處理。這種方法缺點很明顯,就是秒級統計單位,毫秒級別如果超過限流值了,則1秒內都是拒絕請求的,存在極大的資源浪費。


屏幕快照 2020-02-17 11.11.09.png


滑動窗口計數法

相對固定計數法來說,滑動窗口把1秒分成了若干小分段,比如200毫秒一段,統計某個時間點的限流值是把當前1秒內的小窗流量全部相加。


屏幕快照 2020-02-17 11.17.17.png

漏痛算法

漏桶算法思路很簡單,水(請求)先進入到漏桶裏,漏桶以一定的速度出水,當水流入速度過大會直接溢出,可以看出漏桶算法能強行限制數據的傳輸速率。


屏幕快照 2020-02-17 11.20.42.png


漏桶算法具體實現見文章:https://www.ctolib.com/topics-134605.html


關於漏桶算法做個解釋,漏桶算法的一個缺點,就是出水速度是被強行限制的,也就是說,外部流量被桶的容量限制,放行流量是均勻的,比如漏水速度控制在10qps,那麼不管底層系統提供的能力是多少,調用值會限定在10qps。


令牌桶算法

令牌桶算法的原理是系統會以一個恆定的速度往桶裏放入令牌,而如果請求需要被處理,則需要先從桶裏獲取一個令牌,當桶裏沒有令牌可取時,則拒絕服務。


屏幕快照 2020-02-17 11.56.15.png


Google開源工具包Guava提供了限流工具類RateLimiter,該類基於令牌桶算法來完成限流,非常易於使用。RateLimiter類的接口描述請參考:RateLimiter接口描述,具體使用請參考:RateLimiter使用實踐。具體教程參考:https://www.baeldung.com/guava-rate-limiter


屏幕快照 2020-02-17 12.22.18.png


相對漏桶算法來說,是在桶容量前提下,保持固定的調用速率,而令牌桶則允許在桶容量前提下,可以任意的調用速率。因此令牌桶的實際適用更好一些。


總結


限流是保護系統的一個非常直接的辦法。阿里開源的setinel是一個非常好的限流項目,項目地址:https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D

sentinel的具體限流核心算法,我們將在另外一篇文章進行分析,讀讀阿里巴巴優雅的代碼設計。

發佈了344 篇原創文章 · 獲贊 25 · 訪問量 52萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章