限流場景
-
保護系統資源:限流可用於保護系統資源,防止系統被過度請求而導致資源耗盡或系統崩潰。例如,限制對資料庫、快取、訊息佇列等關鍵資源的訪問速率,以確保系統的穩定性和可用性。
-
防止惡意攻擊:限流可用於防止惡意攻擊和惡意請求,如暴力破解、DDoS 攻擊等。透過限制來自單個 IP 地址或單個使用者的請求速率,可以有效地減輕攻擊的影響,並保護系統的安全。
-
流量控制:限流可用於控制系統的流量,防止流量突增而導致系統負載過高。例如,限制某個 API 介面或服務的請求速率,以確保系統能夠處理流量峰值,避免系統效能下降或服務不可用。
-
平滑流量:限流可用於平滑流量,防止突發流量對系統造成衝擊。透過限制請求速率,可以平滑流量的到達時間,減少系統負載的波動,提高系統的穩定性和可靠性。
-
保護第三方服務:限流可用於保護對第三方服務的呼叫,防止對第三方服務造成過度壓力。例如,限制對外部 API 的請求速率,以確保系統能夠遵守第三方服務的使用規範,避免被封禁或受到懲罰。
常用限流方案
-
令牌桶演算法:
- 基於令牌桶實現的限流演算法。
- 每秒生成一定數量的令牌,請求需要獲取令牌才能被處理。
- 令牌桶演算法可以應對突發流量。
-
漏桶演算法:
- 將訪問請求的資料包放入“漏桶”中。
- 以恆定速率處理請求,保證穩定性。
令牌桶演算法的理解
系統以恆定速率向桶中放入令牌。如果請求(request)需要處理,必須先從桶中獲取一個令牌。當桶中沒有令牌時,拒絕請求(request)。
漏桶演算法的理解
所有的請求(request)緩衝至桶內,系統以恆定的速率處理請求(request),當請求(request)的量累積至溢位桶外,拒絕請求(request)。
需要更平滑的流量控制,令牌桶演算法可能更適合;如果你需要嚴格的速率控制,漏桶演算法可能更合適。
由於令牌桶允許突發流量在閾值範圍內激增,因此個人認為它的適用性更為廣泛。
限流常用類庫
- Guava RateLimiter: Guava 提供的限流類庫,簡單易用,支援多種限流模式。
- Java 9 java.util.concurrent.RateLimiter: Java 9 提供的限流類庫,與 Guava RateLimiter 類似,但效能更高。(要求JDK版本必須9以上)
- Redis: Redis 可以使用 Lua 指令碼實現令牌桶限流,支援分散式限流。
- Alibaba的Sentinel元件自帶限流功能,基於滑動視窗演算法實現,支援多種策略。
值得注意的是:將限流措施寫在介面處時,流量已經抵達了系統內,才會進行限流判斷。這種做法有時候可能會導致系統過載或不穩定性,尤其是在高流量或突發流量的情況下。
為了更有效地保護系統的穩定性,通常建議在流量的入口處或者在系統的邊緣進行限流,例如在外部的反向代理層(比如 Nginx)或者 API 閘道器(比如 Zuul、Kong 等)上實施限流措施。
+--------------+
| 客戶端 |
+--------------+
|
v
+--------------+
| 反向代理層 |
+--------------+
|
v
+--------------+
| 閘道器層 |
+--------------+
|
+------------- v -------------+
| |
| |
+--------------+ +--------------+
| 服務例項1 | | 服務例項2 |
+--------------+ +--------------+