面試被問高併發流量控制,我臉都綠了。。。

點擊上方“芋道源碼”,選擇“設爲星標

管她前浪,還是後浪?

能浪的浪,纔是好浪!

每天 8:55 更新文章,每天掉億點點頭髮...

源碼精品專欄

 

來源:jianshu.com/p/d9504fc0af4d

  • 前言

  • 應對大流量的一些思路

  • 限流的常用方式

  • 限流神器:Guava RateLimiter

  • 分佈式場景下的限流


前言

在實際項目中,曾經遭遇過線上5W+QPS的峯值,也在壓測狀態下經歷過10W+QPS的大流量請求,本篇博客的話題主要就是自己對高併發流量控制的一點思考。

應對大流量的一些思路

首先,我們來說一下什麼是大流量?

大流量,我們很可能會冒出:TPS(每秒事務量),QPS(每秒請求量),1W+,5W+,10W+,100W+...。其實並沒有一個絕對的數字,如果這個量造成了系統的壓力,影響了系統的性能,那麼這個量就可以稱之爲大流量了。

其次,應對大流量的一些常見手段是什麼?

緩存:說白了,就是讓數據儘早進入緩存,離程序近一點,不要大量頻繁的訪問DB。

降級:如果不是核心鏈路,那麼就把這個服務降級掉。打個比喻,現在的APP都講究千人千面,拿到數據後,做個性化排序展示,如果在大流量下,這個排序就可以降級掉!

限流:大家都知道,北京地鐵早高峯,地鐵站都會做一件事情,就是限流了!想法很直接,就是想在一定時間內把請求限制在一定範圍內,保證系統不被沖垮,同時儘可能提升系統的吞吐量。

注意到,有些時候,緩存和降級是解決不了問題的,比如,電商的雙十一,用戶的購買,下單等行爲,是涉及到大量寫操作,而且是核心鏈路,無法降級的,這個時候,限流就比較重要了。

那麼接下來,我們重點說一下,限流。

限流的常用方式

限流的常用處理手段有:計數器、滑動窗口、漏桶、令牌。

計數器

計數器是一種比較簡單的限流算法,用途比較廣泛,在接口層面,很多地方使用這種方式限流。在一段時間內,進行計數,與閥值進行比較,到了時間臨界點,將計數器清0。

計數器思想

代碼實例

計數器代碼實現

這裏需要注意的是,存在一個時間臨界點的問題。舉個栗子,在12:01:00到12:01:58這段時間內沒有用戶請求,然後在12:01:59這一瞬時發出100個請求,OK,然後在12:02:00這一瞬時又發出了100個請求。這裏你應該能感受到,在這個臨界點可能會承受惡意用戶的大量請求,甚至超出系統預期的承受。

滑動窗口

**由於計數器存在臨界點缺陷,後來出現了滑動窗口算法來解決。

**

滑動窗口原理圖

滑動窗口的意思是說把固定時間片,進行劃分,並且隨着時間的流逝,進行移動,這樣就巧妙的避開了計數器的臨界點問題。也就是說這些固定數量的可以移動的格子,將會進行計數判斷閥值,因此格子的數量影響着滑動窗口算法的精度。

漏桶

雖然滑動窗口有效避免了時間臨界點的問題,但是依然有時間片的概念,而漏桶算法在這方面比滑動窗口而言,更加先進。

有一個固定的桶,進水的速率是不確定的,但是出水的速率是恆定的,當水滿的時候是會溢出的。

漏桶算法思想

代碼實現

漏桶代碼實現

令牌桶

注意到,漏桶的出水速度是恆定的,那麼意味着如果瞬時大流量的話,將有大部分請求被丟棄掉(也就是所謂的溢出)。爲了解決這個問題,令牌桶進行了算法改進。

令牌桶原理

生成令牌的速度是恆定的,而請求去拿令牌是沒有速度限制的。這意味,面對瞬時大流量,該算法可以在短時間內請求拿到大量令牌,而且拿令牌的過程並不是消耗很大的事情。(有一點生產令牌,消費令牌的意味)

不論是對於令牌桶拿不到令牌被拒絕,還是漏桶的水滿了溢出,都是爲了保證大部分流量的正常使用,而犧牲掉了少部分流量,這是合理的,如果因爲極少部分流量需要保證的話,那麼就可能導致系統達到極限而掛掉,得不償失。

代碼實現

令牌桶代碼實現

限流神器:Guava RateLimiter

Guava不僅僅在集合、緩存、異步回調等方面功能強大(可以參考博主的《使用Google Guava快樂編程》),而且還給我們封裝好了限流的API!

Guava RateLimiter基於令牌桶算法,我們只需要告訴RateLimiter系統限制的QPS是多少,那麼RateLimiter將以這個速度往桶裏面放入令牌,然後請求的時候,通過tryAcquire()方法向RateLimiter獲取許可(令牌)。

代碼示例

RateLimiter

分佈式場景下的限流

上面所說的限流的一些方式,都是針對單機而言的,其實大部分的場景,單機的限流已經足夠了。分佈式下限流的手段常常需要多種技術相結合,比如Nginx+Lua,Redis+Lua等去做。本文主要討論的是單機的限流,這裏就不在詳細介紹分佈式場景下的限流了。

一句話,讓系統的流量,先到隊列中排隊、限流,不要讓流量直接打到系統上。

好了,到這裏,本文就結束了!

早安!

美好的一天開始了,上班咯!



歡迎加入我的知識星球,一起探討架構,交流源碼。加入方式,長按下方二維碼噢

已在知識星球更新源碼解析如下:

最近更新《芋道 SpringBoot 2.X 入門》系列,已經 20 餘篇,覆蓋了 MyBatis、Redis、MongoDB、ES、分庫分表、讀寫分離、SpringMVC、Webflux、權限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能測試等等內容。

提供近 3W 行代碼的 SpringBoot 示例,以及超 4W 行代碼的電商微服務項目。

獲取方式:點“在看”,關注公衆號並回復 666 領取,更多內容陸續奉上。

兄弟,一口,點個????

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章