博客 / 詳情

返回

流量洪峯下的交通指揮家:詳解負載均衡與限流實戰

負載均衡:聰明的交通指揮家
如果説水平擴容是為系統增加了更多的“工作車道”,那麼負載均衡就是站在車道入口處的交通指揮家。它的存在,是為了回答一個根本性問題:當成千上萬的請求同時涌來時,如何將它們高效、公平且智能地引導至後端的服務集羣,從而避免任何一條“車道”因擁堵而癱瘓?
負載均衡的本質,是將單一的、巨大的訪問壓力,分解為多個可管理的、微小的壓力。負載均衡不僅需要在用户請求和Web服務器之間進行,而且在系統的每個階段都必須進行。一箇中等規模的系統可能在以下三個層面實現負載均衡。
1)用户請求到Web服務器;
2)Web服務器到內部平台層;
3)內部平台層到數據存儲層。
負載均衡可以通過硬件或軟件來實現。硬件負載均衡器,如F5 BIG-IP等專用硬件設備,通常被用於處理高流量的網站和網絡,但其價格通常較高。相比之下,軟件負載均衡器,如LVS(Linux Virtual Server)和Nginx,不僅價格更為低廉,而且提供了更高的靈活性,可以根據具體需求進行定製和調整,以滿足各種不同的業務場景。對於大多數系統,建議從軟件負載均衡器開始,只有在明確需要的情況下,才考慮轉向硬件負載均衡器。
image

負載均衡算法
負載均衡器在將請求轉發到後端服務器之前會考慮兩個因素。首先,它會確保所選擇的服務器能夠適當地響應請求,然後使用預先配置的算法從一組正常的服務器中選擇一個。
負載均衡器應該只將流量轉發到“正常”的服務節點。為了監視服務器的運行狀況,負載均衡器會定期進行運行狀況檢查(Health Check),嘗試連接到服務器,以確保服務節點正在正常運行。如果某個服務節點未通過運行狀況檢查,它將自動從服務器池中刪除,並且在它再次通過運行狀況檢查之前,負載均衡器不會將流量轉發給它。
在負載均衡中,有各種各樣的方法和算法,這些算法可以根據服務器的性能、負載情況、會話保持需求等因素來進行選擇。以下是一些常見的負載均衡算法。
1)輪詢(Round Robin):這是最簡單也最經典的策略。它像發牌一樣,按順序將請求逐一分發給每台服務器。這種方式純粹、公平,但略顯“天真”——它假設所有服務器的處理能力完全相同,且每個請求的耗時也一樣,這在現實世界中幾乎不可能。
2)最少連接(Least Connections): 這是最常用的動態算法。它會把新請求發送給當前連接數最少的服務器。這好比在超市結賬時,總會下意識地選擇排隊人數最少的那個收銀台,因為它大概率最快。
3)加權算法(Weighted Algorithms):當服務器配置高低不一時,加權算法便派上用場。可以為性能更強的服務器分配更高的“權重”,讓它承擔更多的流量,實現“能者多勞”,最大化利用硬件投資。
4)會話保持(Session Persistence / Sticky Sessions):在某些場景下(如網上銀行、購物車),需要用户的連續請求始終由同一台服務器處理,以維持會話狀態。此時,負載均衡器會根據用户的IP地址或Cookie等信息,實現“粘性會話”,確保用户的請求“粘”在固定的服務器上。

限流:給流量裝上調節閥
無論系統多麼強大,短時間內的流量突增總是令人頭疼的問題,因此,對於併發系統來説,一個必不可少的模塊就是限流(Rate Limiter)。
限流是一種通過控制請求的頻率或數量來保護系統免受過載的技術,確保系統能夠在可接受的範圍內處理請求,避免過多的請求導致系統資源耗盡、性能下降或崩潰。
常見的限流算法包括固定窗口、滑動窗口、漏桶、令牌桶。
image

固定窗口
固定窗口(Fixed Window)算法是最簡單的限流算法。其原理是在一個固定的時間窗口內(每個時間單位)限制請求的數量。
固定窗口的缺點是無法平滑地處理突發流量。例如,如果閾值為5個請求,時間窗口的時間單位為1秒,在0.8秒到1秒和1秒到1.2秒分別有5個併發請求,儘管它們都沒有超過閾值,但當計算0.8秒到1.2秒內的請求時,併發數高達10,已經超過了每個時間單位不超過5個請求的定義。
image

滑動窗口
因此,可以引入滑動窗口(Sliding Window)算法來解決關鍵時間窗口轉換的問題。滑動窗口是將一個較大的時間窗口分割成幾個粒度更細的子窗口。每個子窗口獨立計數,並基於子窗口的時間滑動進行限流控制。當滑動窗口具有更多的網格週期時,滑動窗口的滾動將更加平滑,限流統計將更加準確。
image

假設每單位時間仍然是1秒,滑動窗口算法將其劃分為5個小週期,即滑動窗口(每單位時間)被劃分為5個小格子。每個格子代表0.2秒。在每個0.2秒內,時間窗口會向右滑動一個格子。然後,每個小週期都有其獨立的計數器。如果請求在0.83秒到達,那麼在0.8秒到1.0秒格子內的對應計數器將增加1。
假設在1秒內的閾值仍然是5個請求,0.8秒到1.0秒內到達5個請求(例如0.9秒),它們將落入黃色的格子。
在1.0秒的格子之後,又有5個請求到達並落入紫色的格子。如果是固定窗口算法,它將不會被限制。然而,如果是滑動窗口算法,每次經過一個小週期,它就會向右滑動一個格子。在1.0秒的格子之後,它會向右滑動一個格子。當前的每單位時間週期是0.2秒到1.2秒。在這個區域內的請求已經超過了5個的閾值,當前的限流已經被觸發。實際上,紫色格子內的所有請求都已被拒絕。

漏桶
漏桶(Leaky Bucket)算法是一種基於輸出流速進行流量控制的方法。這個算法的名字來源於它的工作原理,就像一個漏水的桶一樣。
在漏桶算法中,可以將數據想象成水滴,而漏桶就是一個有固定容量的桶。請求(水滴)以任何速率進入桶中,而桶(漏桶)以固定的速率將請求(水)釋放出去。如果進入的請求(水滴)過多,超過了桶的容量,那麼多餘的請求(水)就會被丟棄。
漏桶算法適用於需要強制執行固定速率處理的場景,如網絡流量控制、API請求限制等。即使輸入數據的速率有波動,漏桶算法也可以通過丟棄多餘的數據來防止系統過載。
然而,面對突發流量時,漏桶算法仍然以規律的方式處理請求,這並不是希望看到的。當流量突然增加時,希望系統能儘快處理請求,以提高用户體驗。
image

令牌桶
令牌桶(Token Bucket)算法是一種基於輸入流量速率進行流量控制的方法。該算法維護一個具有固定容量的令牌桶,並且每秒向令牌桶中放入一定數量的令牌。當請求到來時,如果令牌桶中的令牌數量足夠,那麼請求將被允許通過,並從令牌桶中消耗一個令牌。否則,請求將被拒絕。
令牌桶算法通常用於保護系統,通過限制調用者的請求速率來防止系統面臨突發流量的壓力。如果系統的實際處理能力大於配置的流量限制,那麼可能會允許一定程度的流量突發,使得實際處理速率高於配置的速率,從而充分利用系統資源。
image

使用場景
固定窗口:在一個電商網站中,為了防止惡意刷單,希望對每個用户每分鐘的下單次數進行限制。通過使用固定窗口算法,例如設置每分鐘只能下單5次,以確保訂單減少的合理性。
滑動窗口:在一個API服務中,希望平滑地控制請求的頻率。通過滑動窗口算法,例如限制每秒最多處理10個請求,且每個請求必須均勻分佈在連續的1秒窗口內。
漏桶:在一個消息推送服務中,希望消息的發送速度是恆定的。通過使用漏桶算法,可以控制消息的發送速率,確保發送速度是恆定的,不會超過系統的處理能力。
令牌桶:在一個視頻網站中,希望限制用户的平均下載速度,同時又希望能夠應對突發的下載需求。通過使用令牌桶算法,可以設置每個用户的下載速度上限,並在令牌桶中存儲一定數量的令牌。用户每下載一個視頻,需要消耗一個令牌,當令牌桶中的令牌不足時,用户需要等待令牌生成或下載速度受限。

未完待續

很高興與你相遇!如果你喜歡本文內容,記得關注哦!!!

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.