架構必備:Rate limiting 的作用和常見方式

jopen 9年前發布 | 43K 次閱讀 架構

 

Rate limiting 在 Web 架構中非常重要,是互聯網架構可靠性保證重要的一個方面。

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

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

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

架構必備:Rate limiting 的作用和常見方式

還有,公開 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;
    }

詳細參見: ngx_http_limit_req_module

Haproxy 提供的功能

詳細參見: Haproxy Rate limit 模塊

Java、Scala JVM 系應用層實現

Google Guava 提供了一個 RateLimiter 實現。使用方式簡單明了,在自己的應用中簡單封裝即可,放到 HTTP 服務或者其他邏輯接口調用的前端。

final RateLimiter rateLimiter = RateLimiter.create(2.0); // rate is "2 permits per second"
  void submitTasks(List<Runnable> tasks, Executor executor) {
    for (Runnable task : tasks) {
      rateLimiter.acquire(); // may wait
      executor.execute(task);
    }
  }

詳細參見: Google Guava RateLimiter

基于 Redis 功能的實現

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

參見: Redis INCR rate limiter

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!