在早期的計算機領域,限流技術(time limiting)被用做控制網絡接口收發通訊數據的速率。 能夠用來優化性能,減小延遲和提升帶寬等。 如今在互聯網領域,也借鑑了這個概念, 用來爲服務控制請求的速率, 若是雙十一的限流, 12306的搶票等。 即便在細粒度的軟件架構中,也有相似的概念。 html
兩種經常使用算法nginx
令牌桶(Token Bucket)和漏桶(leaky bucket)是 最經常使用的兩種限流的算法。 git
漏桶算法github
它的主要目的是控制數據注入到網絡的速率,平滑網絡上的突發流量。漏桶算法提供了一種機制,經過它,突發流量能夠被整形以便爲網絡提供一個穩定的流量。 漏桶能夠看做是一個帶有常量服務時間的單服務器隊列,若是漏桶(包緩存)溢出,那麼數據包會被丟棄。 用說人話的講: redis
漏桶算法思路很簡單,水(數據或者請求)先進入到漏桶裏,漏桶以必定的速度出水,當水流入速度過大會直接溢出,能夠看出漏桶算法能強行限制數據的傳輸速率。算法
在某些狀況下,漏桶算法不可以有效地使用網絡資源。由於漏桶的漏出速率是固定的參數,因此,即便網絡中不存在資源衝突(沒有發生擁塞),漏桶算法也不能使某一個單獨的流突發到端口速率。所以,漏桶算法對於存在突發特性的流量來講缺少效率。而令牌桶算法則可以知足這些具備突發特性的流量。一般,漏桶算法與令牌桶算法能夠結合起來爲網絡流量提供更大的控制。 後端
令牌桶算法緩存
令牌桶算法的原理是系統會以一個恆定的速度往桶裏放入令牌,而若是請求須要被處理,則須要先從桶裏獲取一個令牌,當桶裏沒有令牌可取時,則拒絕服務。 令牌桶的另一個好處是能夠方便的改變速度。 一旦須要提升速率,則按需提升放入桶中的令牌的速率。 通常會定時(好比100毫秒)往桶中增長必定數量的令牌, 有些變種算法則實時的計算應該增長的令牌的數量, 好比華爲的專利"採用令牌漏桶進行報文限流的方法"(CN 1536815 A),提供了一種動態計算可用令牌數的方法, 相比其它定時增長令牌的方法, 它只在收到一個報文後,計算該報文與前一報文到來的時間間隔內向令牌漏桶內注入的令牌數, 並計算判斷桶內的令牌數是否知足傳送該報文的要求。 安全
從最終用戶訪問安全的角度看,設想有人想暴力碰撞網站的用戶密碼;或者有人攻擊某個很耗費資源的接口;或者有人想從某個接口大量抓取數據。大部分人都知道應該增長 Rate limiting,作請求頻率限制。從安全角度,這個可能也是大部分能想到,但不必定去作的薄弱環節。服務器
從整個架構的穩定性角度看,通常 SOA 架構的每一個接口的有限資源的狀況下,所能提供的單位時間服務能力是有限的。假如超過服務能力,通常會形成整個接口服務停頓,或者應用 Crash,或者帶來連鎖反應,將延遲傳遞給服務調用方形成整個系統的服務能力喪失。有必要在服務能力超限的狀況下 Fail Fast。
另外,根據排隊論,因爲 API 接口服務具備延遲隨着請求量提高迅速提高的特色,爲了保證 SLA 的低延遲,須要控制單位時間的請求量。這也是 Little’s law 所說的。
還有,公開 API 接口服務,Rate limiting 應該是一個必備的功能,不然公開的接口不知道哪一天就會被服務調用方有意無心的打垮。
因此,提供資源可以支撐的服務,將過載請求快速拋棄對整個系統架構的穩定性很是重要。這就要求在應用層實現 Rate limiting 限制。
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; server { location /search/ { limit_req zone=one burst=5; }
詳細參見: ngx_http_limit_req_module
詳細參見: Haproxy Rate limit 模塊
RateLimiters是令牌桶和漏桶在.NET 中實現。這些策略可用於速率限制請求不一樣的網站中,後端或 API 調用等場景。
ASP.NET Web API rate limiter for IIS and Owin hosting
這個在 Redis 官方文檔有很是詳細的實現。通常適用於全部類型的應用,好比 PHP、Python 等等。Redis 的實現方式能夠支持分佈式服務的訪問頻率的集中控制。Redis 的頻率限制實現方式還適用於在應用中沒法狀態保存狀態的場景。
網上有衆多關於這方面的文章,這裏列出了本文參考的一些文檔。