限流-最佳實踐
對比基於時間視窗的限流演演算法,令牌桶和漏桶演演算法對流量整形效果比時間視窗演演算法要好很多,但是並不是整形效果越好就越合適,對於沒有提前預熱的令牌桶,如果做否決式限流,會導致誤殺很多請求。上述演演算法中當 n 比較小時,比如 50,間隔 20ms 才會向桶中放入一個令牌,而介面的訪問在 1s 內可能隨機性很強,這就會出現:儘管從曲線上看對最大訪問頻率的限制很有效,流量在細時間粒度上面都很平滑,但是誤殺了很多本不應該拒絕的介面請求。
所以令牌桶和漏桶演演算法比較適合阻塞式限流,比如一些後臺 job 類的限流,超過了最大訪問頻率之後,請求並不會被拒絕,而是會被阻塞到有令牌後再繼續執行。對於像微服務介面這種對響應時間比較敏感的限流場景,會比較適合選擇基於時間視窗的否決式
以上是各種優劣的對比。
上面說的,拒絕,就是放棄請求。阻塞,就是等待,稍後再處理請求,而不會丟棄請求。
最佳實踐
拒絕演演算法。即時間演演算法。
拒絕
因為阻塞演演算法只適合每個請求都必須要處理的場景。而拒絕演演算法,適合限流,而且實現簡單。
當然,阻塞演演算法也可以放棄請求,即拒絕請求。只不過,適合的應用場景有區別。因為漏桶演演算法是按固定速度來處理請求,而時間演演算法是按固定時間來處理請求。
即,一個是1ms處理一個請求,一個是1s處理1000個請求。
這兩個有什麼區別呢?就是我們的需求,應該是1ms可以處理10個請求,而不是1個請求。而如果是採用時間演演算法,那麼1s內的任何1ms,都可以處理10個請求。但是,如果是漏桶演演算法,那麼就只能處理1個請求,其他9個請求處理不了,就只能丟棄請求了。
本質的區別是,兩個維度。當然,如果硬要去解決的話,漏桶演演算法也可以做到1ms處理10個請求,當然歸根結底,還是適用的應用場景有一些區別的,不是說一種演演算法就只能解決一種演演算法的問題,而解決不了另外一種演演算法的問題,關鍵是適合。
阻塞
阻塞其實也是限流,本質上是控制流量。
阻塞,就是必須要消費這些資料。比如,支付系統裡的實名認證介面,每一個請求都是必須要處理的。但是你的執行緒池裡的阻塞佇列是1000,超過了就只能先阻塞,等佇列資料被消費了,再入佇列。