1. 程式人生 > >流量調整和限流技術

流量調整和限流技術

在早期的計算機領域,限流技術(time limiting)被用作控制網路介面收發通訊資料的速率。 可以用來優化效能,減少延遲和提高頻寬等。 現在在網際網路領域,也借鑑了這個概念, 用來為服務控制請求的速率, 如果雙十一的限流, 12306的搶票等。 即使在細粒度的軟體架構中,也有類似的概念。

兩種常用演算法

漏桶演算法

它的主要目的是控制資料注入到網路的速率,平滑網路上的突發流量。漏桶演算法提供了一種機制,通過它,突發流量可以被整形以便為網路提供一個穩定的流量。 漏桶可以看作是一個帶有常量服務時間的單伺服器佇列,如果漏桶(包快取)溢位,那麼資料包會被丟棄。 用說人話的講:

漏桶演算法思路很簡單,水(資料或者請求)先進入到漏桶裡,漏桶以一定的速度出水,當水流入速度過大會直接溢位,可以看出漏桶演算法能強行限制資料的傳輸速率。

在某些情況下,漏桶演算法不能夠有效地使用網路資源。因為漏桶的漏出速率是固定的引數,所以,即使網路中不存在資源衝突(沒有發生擁塞),漏桶演算法也不能使某一個單獨的流突發到埠速率。因此,漏桶演算法對於存在突發特性的流量來說缺乏效率。而令牌桶演算法則能夠滿足這些具有突發特性的流量。通常,漏桶演算法與令牌桶演算法可以結合起來為網路流量提供更大的控制。

令牌桶演算法

令牌桶演算法的原理是系統會以一個恆定的速度往桶裡放入令牌,而如果請求需要被處理,則需要先從桶裡獲取一個令牌,當桶裡沒有令牌可取時,則拒絕服務。 令牌桶的另外一個好處是可以方便的改變速度。 一旦需要提高速率,則按需提高放入桶中的令牌的速率。 一般會定時(比如100毫秒)往桶中增加一定數量的令牌, 有些變種演算法則實時的計算應該增加的令牌的數量, 比如華為的專利"採用令牌漏桶進行報文限流的方法

"(CN 1536815 A),提供了一種動態計算可用令牌數的方法, 相比其它定時增加令牌的方法, 它只在收到一個報文後,計算該報文與前一報文到來的時間間隔內向令牌漏桶內注入的令牌數, 並計算判斷桶內的令牌數是否滿足傳送該報文的要求。

從終端使用者訪問安全的角度看,設想有人想暴力碰撞網站的使用者密碼;或者有人攻擊某個很耗費資源的介面;或者有人想從某個介面大量抓取資料。大部分人都知道應該增加 Rate limiting,做請求頻率限制。從安全形度,這個可能也是大部分能想到,但不一定去做的薄弱環節。

從整個架構的穩定性角度看,一般 SOA 架構的每個介面的有限資源的情況下,所能提供的單位時間服務能力是有限的。假如超過服務能力,一般會造成整個介面服務停頓,或者應用 Crash,或者帶來連鎖反應,將延遲傳遞給服務呼叫方造成整個系統的服務能力喪失。有必要在服務能力超限的情況下 Fail Fast。

另外,根據排隊論,由於 API 介面服務具有延遲隨著請求量提升迅速提升的特點,為了保證 SLA 的低延遲,需要控制單位時間的請求量。這也是 Little’s law 所說的。

還有,公開 API 介面服務,Rate limiting 應該是一個必備的功能,否則公開的介面不知道哪一天就會被服務呼叫方有意無意的打垮。

所以,提供資源能夠支撐的服務,將過載請求快速拋棄對整個系統架構的穩定性非常重要。這就要求在應用層實現 Rate limiting 限制。

常見的 Rate limiting 的實現方式

Proxy 層的實現,針對部分 URL 或者 API 介面進行訪問頻率限制

Nginx 模組

limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

server {
    location /search/ {
        limit_req zone=one burst=5;
    }

Haproxy 提供的功能

RateLimiters是令牌桶和漏桶在.NET 中實現。這些策略可用於速率限制請求不同的網站中,後端或 API 呼叫等場景。

基於 Redis 功能的實現

這個在 Redis 官方文件有非常詳細的實現。一般適用於所有型別的應用,比如 PHP、Python 等等。Redis 的實現方式可以支援分散式服務的訪問頻率的集中控制。Redis 的頻率限制實現方式還適用於在應用中無法狀態儲存狀態的場景。

網上有眾多關於這方面的文章,這裡列出了本文參考的一些文件。


轉自:http://www.cnblogs.com/shanyou/p/4280546.html