您好,登錄后才能下訂單哦!
這篇文章主要介紹“如何理解微服務中的限流邏輯與算法”,在日常操作中,相信很多人在如何理解微服務中的限流邏輯與算法問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”如何理解微服務中的限流邏輯與算法”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
限流的概念
先介紹下什么是限流?其實日常生活中的限流場景隨處可見,例如北京地鐵早高峰,每天都是人山人海,如果大家一起蜂擁進站,將很容易造成站內擁堵,所以地鐵站一般都會進站口設置像迷宮一樣的柵欄,大家轉圈圈分批進站,這就是一種典型的限流場景。
那么在微服務中的限流具體是指什么呢?從字面上看,限流限的是流量,在不同場景下流量的定義是不同的,可以是QPS(每秒請求數)、TPS(每秒事務處理數),也可以指純粹的網絡流量(如網卡通過的字節數)等。
但我們通常所說的限流,是指限制達到系統的并發請求數,使得系統能夠在自身能力允許的情況下正常處理部分用戶的請求,而對超出自身處理能力的用戶請求則予以拒絕,從而保證系統的穩定運行。
限流不可避免的會造成用戶請求失敗或變慢的情況,從而在一定程度上影響用戶體驗,所以限流策略的制定需要以系統壓測的結果為參考,并在用戶體驗與系統穩定性之間進行平衡取舍。
限流的必要性?
前面我們提到限流的主要目的是為了保證系統的穩定性。在日常的業務中,如果遇到像雙十一之類的促銷活動,或者遇到爬蟲等不正常的流量等情況,用戶流量突增,但后端服務的處理能力是有限的,如果不能有效處理突發流量,那么后端服務就很容易被打垮。
可以設想這樣一個場景:"某服務單節點可以承受的QPS是1000,該服務共有5個節點,日常情況下服務的QPS為3000"。那么正常情況下該服務毫無壓力,根據負載均衡配置3000/5=600,每個節點的日常QPS才600左右。
直到某一天,老板突然搞了一波促銷,系統的整體QPS達到了8000。此時每個節點的平均承載QPS為1600,節點A率先扛不住直接掛了,此時集群中還剩下4個節點,每個節點的平均承載QPS將達到2000,于是,剩下的4個節點也一臺接一臺掛了,整個服務就此雪崩。
而如果我們的系統有限流機制,那么情況將會如何發展呢?
系統整體QPS達到8000,但由于集群整體限流了5000,所以超出集群承受力的那3000個請求將被拒絕,系統則會正常處理5000個用戶請求,這是對集群整體限流的情況。而對于各個節點來說,由于我的承受力只是1000QPS,那么超出1000的部分也將被拒絕。這樣雖然損失了部分用戶請求,但保證了整個系統的穩定性,也給開發運維留下了系統擴容時間。
由此可見,限流對于系統的自我保護是非常重要的存在。那么限流具體怎么做呢?接下來我們總結下常見的限流算法。
常見的限流算法
常見的限流算法主要有:計數器、固定窗口,滑動窗口、漏桶、令牌桶。接下來我們分別介紹下這幾種限流算法。
<計數器限流>
計數器限流是最簡單粗暴的一種限流算法,例如系統能同時處理100個請求,那么可以在保存一個計數器,處理一個請求,計數器加一,一個請求處理完畢后計數器減一。每次請求進來的時候,先看一眼計數器的值,如果超過閥值則直接拒絕。
在具體實現時,如果該計數器是存在單機內存中,那么就實現了單機限流;而如果存在例如Redis中,集群中的所有節點依次為限流依據,那么就算實現了集群限流算法。
優點:實現簡單,單機例如諸如Java的Atomic等原子類就能實現,集群則通過Redis的incr操作就能快速實現。
缺點:計數器限流無法應對突發的流量增長。例如我們允許的閥值是1W,此時計數器的值是0,那么當1W個請求瞬間全部打進來的時候,很可能服務就頂不住了。這是因為流量的緩緩增加和一下子涌入,對系統所產生的壓力是不一樣的。
況且一般限流都是限制在指定時間間隔內的訪問量,而不是全時段服務的總體處理能力,所以計數器限流不太適合高并發場景下的限流實現。
<固定窗口限流>
相對于計數器來說,固定窗口限流是以一段時間窗口內的訪問量作為限流的依據,計數器每過一個時間窗口就自動重置。其規則如下:
請求次數小于閥值,允許訪問,計數器加1;
請求次數大于閥值,拒絕訪問;
本時間窗口過了之后,計數器自動清零;
固定窗口限流雖然看起來挺完美,但是它有固定窗口臨界的問題。例如系統每秒允許1000個請求,假如第一個時間窗口的間隔是0~1秒,但在第0.55秒處一下子涌入了1000個請求,過了1秒后計數清零,此時在1.05秒的時候又一下子涌入了1000個請求。
此時雖然在固定時間窗口內的計數沒有超過閥值,但在全局看來0.55秒~1.05秒這0.5秒內一下子卻涌入了2000個請求,而這對于閥值為1000/s的系統來說是不可承受的。如下圖所示:
而為了解決這個問題,衍生出了滑動窗口限流的算法!
<滑動窗口限流>
滑動窗口限流解決了固定窗口臨界值的問題,可以保證任意時間窗口內都不會超過限流閥值。相對于固定窗口,滑動窗口除了需要引入計數器外,還需要額外記錄時間窗口內每個請求到達的時間點。
以時間窗口為1秒為例,規則如下:
記錄每次請求的時間;
統計每次請求的時間向前推1秒這個時間窗口內的請求數,且1秒前的數據可以刪除;
統計的請求數小于閥值則記錄該請求的時間,并允許通過,反之則拒絕該請求;
雖然看起來很OK,但是滑動窗口也無法解決短時間之內集中流量的沖擊。例如每秒限制1000個請求,但是有可能存在前5毫秒的時候,閥值就被打滿的情況,理想情況下每10毫秒來100個請求,那么系統對流量的處理就會更加平滑。
但在真實場景中是很難控制請求的頻率的。所以為了解決時間窗口類算法的痛點,又出現了漏桶算法。
<漏桶限流>
漏桶算法的基本思想是,流量持續進入漏桶中,底部則定速處理請求,如果流量進入的速率高于底部請求被處理的速率,且當桶中的流量超過桶的大小時,流量就會被溢出。具體如下圖所示:
漏桶算法的特點是寬進嚴出,無論請求的速率有多大,底部的處理速度都勻速進行。這種算法的特點有點類似于消息隊列的處理機制,一般來說漏桶算法也是由隊列來實現的。
但漏桶算法的這種特點,實際上即是它的優點也是缺點。有時候面對突發流量,我們往往會希望在保持系統穩定的同時,能更快地處理用戶請求以提升用戶體驗,而不是按部就班的佛系工作。在這種情況下又出現了令牌桶這樣的限流算法,它在應對突發流量時,可以比漏桶算法更加激進。
<令牌桶限流>
令牌桶與漏桶的原理類似,只是漏桶是底部勻速處理,而令牌桶則是定速的向桶里塞入令牌,然后請求只有拿到了令牌才會被服務器處理。具體規則如下:
定速的向桶中放入令牌;
令牌數量超過桶的限制,則丟棄;
請求來了先向桶中索取令牌,索取成功則通過被處理,否則拒絕;
可以看出令牌桶在應對突發流量時,不會想漏桶那樣勻速的處理,而是在短時間內請求可以同時取走桶中的令牌,并及時的被服務器處理。所以在應對突發流量的場景下,令牌桶表現更強。
限流算法總結
經過上述的描述,好像漏桶、令牌桶比時間窗口類算法好多了,那么時間窗口類算法是不是就沒啥用了呢?
其實并不是,雖然漏桶、令牌桶對比時間窗口類算法對流量的整形效果更好,但是它們也有各自的缺點,例如令牌桶,假如系統上線時沒有預熱,那么可能會出現由于此時桶中還沒有令牌,而導致請求被誤殺的情況;而漏桶中由于請求是暫存在桶中的,所以請求什么時候能被處理,則是有延時的,這并不符合互聯網業務低延時的要求。
所以令牌桶、漏桶算法更適合阻塞式限流的場景,即后臺任務類的限流。而基于時間窗口的限流則更適合互聯網實施業務限流的場景,即能處理快速處理,不能處理及時響應調用方,避免請求出現過長的等待時間。
微服務限流組件
如果你有興趣實際上也是可以自己實現一個限流組件的,只不過這種輪子已經早有人造好了。目前市面上比較流行的限流組件主要有:Google Guava提供的限流工具類“RateLimiter”、阿里開源的Sentinel。
其中Google Guava提供的限流工具類“RateLimiter”,是基于令牌桶實現的,并且擴展了算法,支持了預熱功能。
到此,關于“如何理解微服務中的限流邏輯與算法”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。