高並發系統中限流技術的應用場景

在開發具有較高併發訪問的系統時,大家知道的有哪些手段可以保護後端應用不被請求擊垮?比如我們可以分析出有哪些服務的訪問量較大,採用緩衝的方式提供數據。另外,目前分佈式服務框架,例如Dubbo、以及Spring Cloud都提供了服務的治理功能,採用服務降級策略,可以提供Mock值的方式保護服務。當然,上面的辦法明顯時犧牲了用戶體驗,保全應用的做法,對有些場景的服務,使用這種做法是可行的。但是對於某些對服務資源要求非常嚴格的系統中,例如搶票、秒殺、下單購買等場景下,需要給用戶明確的反饋才是最重要的,要麼成功,要麼失敗。

今天我們主要介紹下限流算法:

  • 令牌桶

  • 漏桶

  • 滑動窗口

  • 計數器

令牌桶

令牌桶算法有一個容量固定的令牌桶,該桶可以按照固定的速度生產Token。根據限流的方式不同,消耗令牌的方式也不同。

例1:我們對API進行限流,防止爬蟲或者異常刷接口,我們限的是對API的調用,因此一次API調用,消耗一個token。

例2:我們還可以根據請求的數據包進行限流,通過保護服務的帶寬保護服務的安全。我們可以認為一個字節的請求數據包對應一個token。

高併發系統中限流技術的應用場景

令牌桶

令牌桶算法具有如下特性:

  • 算法可以設置生產速率,例如2r/s,這樣500ms就會有一個token產生。

  • 桶具有上限,滿了之後,新生成的token被丟棄。

  • 消耗token時,token不足無法消耗。

  • 容易有洪峰(令牌滿的時候)。

代碼示例:

RateLimiter limiter = RateLimiter.create(10.0); // 每秒不超過10個任務被提交

for (int i = 0; i < 10; i++) {

limiter.acquire(); // 請求RateLimiter, 超過permits會被阻塞

System.out.println("call execute.." + i);

}

漏桶

漏桶和沙漏似的,一個計量工具,具有固定的速率控制。

  • 漏桶具有固定流速。

  • 可空,不流出。

  • 漏桶進入速度隨意。

  • 容量固定,滿則溢。

令牌桶是按照固定速率向桶裡面添加令牌,請求是否被處理要看桶中是否有足夠的令牌。流通是按照固定的流速漏出請求流量。令牌桶允許突發請求,漏桶則平滑請求。

高併發系統中限流技術的應用場景

漏桶

滑動窗口

在TCP通信中,使用了滑動窗口做擁塞控制。需要雙方參與:發送方和接收方。簡單來說,就是接收方要告訴發送方,你不要發的太快,多了我接收不了。發送方為了把數據安全送達,當然要聽接收方的建議。這種限流需要有對應的算法支持。

計數器

有時候我們可以使用簡單的計數器實現限流。我們可以限制一定時間內的訪問併發數,這樣簡單粗暴。例如我們設定一定時間內的連接數不能高於100,數據庫連接數、線程創建數等。這種方式不夠平滑,但可以應對簡單的服務限流場景,實際上我們可以結合滑動時間主動失效並轉移計數的起點,用可以實現。

總結

限流只是保護系統安全的方式一種手段而已,可以嵌套在應用中,也可以在代理上做入口限流。nginx使用Lua腳本做。後續慢慢說明,這些比較簡單。

實際上我們在應用中,用的比較多的還是令牌桶和漏桶兩種算法,在Google的Guava庫中有對應的實現。



分享到:


相關文章: