Nginx R31 doc-13-Limiting Access to Proxied HTTP Resources 訪問限流

来源:https://www.cnblogs.com/houbbBlogs/p/18216554
-Advertisement-
Play Games

前言 大家好,我是老馬。很高興遇到你。 我們為 java 開發者實現了 java 版本的 nginx https://github.com/houbb/nginx4j 如果你想知道 servlet 如何處理的,可以參考我的另一個項目: 手寫從零實現簡易版 tomcat minicat 手寫 ngin ...


前言

大家好,我是老馬。很高興遇到你。

我們為 java 開發者實現了 java 版本的 nginx

https://github.com/houbb/nginx4j

如果你想知道 servlet 如何處理的,可以參考我的另一個項目:

手寫從零實現簡易版 tomcat minicat

手寫 nginx 系列

如果你對 netty 不是很熟悉,可以讀一下

從零手寫實現 nginx-01-為什麼不能有 java 版本的 nginx?

從零手寫實現 nginx-02-nginx 的核心能力

從零手寫實現 nginx-03-nginx 基於 Netty 實現

從零手寫實現 nginx-04-基於 netty http 出入參優化處理

從零手寫實現 nginx-05-MIME類型(Multipurpose Internet Mail Extensions,多用途互聯網郵件擴展類型)

從零手寫實現 nginx-06-文件夾自動索引

從零手寫實現 nginx-07-大文件下載

從零手寫實現 nginx-08-範圍查詢

從零手寫實現 nginx-09-文件壓縮

限制訪問代理的 HTTP 資源

通過限制連接、請求速率或帶寬,基於客戶端 IP 地址或其他變數,來保護您的上游 Web 和應用伺服器。

本文解釋瞭如何設置連接的最大請求數,或者從伺服器下載內容的最大速率。

簡介

使用 NGINX 和 NGINX Plus,可以限制:

  • 每個鍵值(例如,每個 IP 地址)的連接數
  • 每個鍵值(每秒或每分鐘允許處理的請求數)
  • 連接的下載速度

請註意,IP 地址可以在 NAT 設備後共用,因此應謹慎使用按 IP 地址限制。

限制連接數

要限制連接數:

  1. 使用 limit_conn_zone 指令定義鍵並設置共用記憶體區域的參數(工作進程將使用此區域來共用鍵值的計數器)。在

第一個參數中,指定為鍵計算的表達式。在第二個參數 zone 中,指定區域的名稱和大小:

limit_conn_zone $binary_remote_addr zone=addr:10m;
  1. 使用 limit_conn 指令在 location {}server {}http {} 上下文中應用限制。將共用記憶體區域的名稱作為第一個參數,並將每個鍵允許的連接數作為第二個參數:

    location /download/ {
         limit_conn addr 1;
    }
    

連接數基於 IP 地址進行限制,因為使用了 $binary_remote_addr 變數作為鍵。

另一種限制給定伺服器的連接數的方法是使用 $server_name 變數:

http {
    limit_conn_zone $server_name zone=servers:10m;

    server {
        limit_conn servers 1000;
    }
}

限制請求速率

速率限制可用於防止 DDoS 攻擊,或防止上游伺服器同時收到過多請求而被淹沒。該方法基於漏桶演算法:請求以不同的速率到達桶中,並以固定的速率離開桶。

在使用速率限制之前,您需要配置“漏桶”的全局參數:

  • 鍵(key):用於區分一個客戶端和另一個客戶端的參數,通常是一個變數。
  • 共用記憶體區域(shared memory zone):保存這些鍵的狀態(“漏桶”)的區域的名稱和大小。
  • 速率(rate):以每秒請求數(r/s)或每分鐘請求數(r/m)指定的請求速率限制(“漏桶排空”)。每分鐘請求用於指定少於每秒一個請求的速率。

這些參數是使用 limit_req_zone 指令設置的。該指令在 http {} 級別定義 - 這種方法允許將不同的區域和請求溢出參數應用於不同的上下文:

http {
    #...
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
}

通過這種配置,將創建一個名為 one、大小為 10 兆位元組的共用記憶體區域。該區域保存了使用 $binary_remote_addr 變數設置的客戶端 IP 地址的狀態。請註意,與 $remote_addr 相比,後者也保存客戶端的 IP 地址,而 $binary_remote_addr 保存的是 IP 地址的二進位表示,長度更短。

共用記憶體區域的最佳大小可以使用以下數據計算:IPv4 地址的 $binary_remote_addr 值大小為 4 位元組,在 64 位平臺上,存儲狀態占據 128 位元組。因此,大約 16,000 個 IP 地址的狀態信息占用 1 兆位元組的區域。

如果當 NGINX 需要添加新條目時存儲空間已經耗盡,則會刪除最舊的條目。如果釋放的空間仍然不足以容納新記錄,則 NGINX 返回狀態碼 503 Service Unavailable。您可以使用 limit_req_status 指令重新定義狀態碼。

設置了區域之後,您可以在 NGINX 配置的任何位置使用請求限制,使用 limit_reqserver {}location {}http {} 上下文中指定:

http {
    #...

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

    server {
        #...

        location /search/ {
            limit_req zone=one;
        }
    }
}

通過這種配置,NGINX 在 /search/ 位置內每秒最多處理 1 個請求。這些請求的處理會以這樣的方式延遲,以確保總速率不超過指定值。如果請求的數量超過指定的速率,NGINX 將延遲處理這些請求,直到“桶”(共用記憶體區域 one)已滿。

對於到達滿桶的請求,NGINX 將使用 503 Service Unavailable 錯誤進行響應(如果沒有使用 limit_req_status 重新定義)。

測試請求速率限制

在配置實際的請求速率限制之前,您可以嘗試“乾運行”模式,該模式不會限制請求處理速率。但是,這些過多的請求仍然會計入共用記憶體區域併進行記錄。您可以使用 limit_req_dry_run 指令啟用“乾運行”模式:

http {
    #...

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

    server {
        #...

        location /search/ {
            limit_req zone=one;
            limit_req_dry_run on;
        }
    }
}

每個超出定義的速率限制的請求都將帶有“乾運行”標記進行記錄:

2019/09/03 10:28:45 [error] 142#142: *13246 limiting requests, dry run, excess: 1.000 by zone "one", client: 172.19.0.1, server: www.example.com, request: "GET / HTTP/1.0", host: "www.example.com:80"

處理過多的請求 Handling Excessive Requests

請求被限制以符合 limit_req_zone 指令中定義的速率。

如果請求的數量超過了指定的速率,並且共用記憶體區域變滿,NGINX 將以錯誤響應。

由於流量往往是突發性的,返回錯誤以響應流量突發期間的客戶端請求並非最佳方案。

在 NGINX 中,這些過多的請求可以進行緩衝和處理。limit_req 指令的 burst 參數設置了等待以指定速率處理的過多請求的最大數量:

http {
    #...

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

    server {
        #...

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

通過這種配置,如果請求速率超過每秒 1 個請求,超出速率的請求將放入區域 one。當區域滿時,過多的請求將被排隊(burst),此隊列的大小為 5 個請求。隊列中的請求處理會延遲,以確保總速率不超過指定值。超出突發限制的請求將用 503 錯誤拒絕。

如果不希望在流量突發期間延遲請求,可以添加 nodelay 參數:

http {
    #...

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

    server {
        #...

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

通過這種配置,突發限制內的過多請求將立即服務,而不考慮指定的速率,超出突發限制的請求將用 503 錯誤拒絕。

延遲過多的請求 Delaying Excessive Requests

處理過多請求的另一種方法是在一定數量的請求中提供無延遲服務,然後在超出此數量後應用速率限制,直到拒絕過多的請求。

可以使用 delayburst 參數來實現這一點。delay 參數定義了超出請求被延遲以符合定義的速率限制的點:

http {
    #...

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

    server {
        #...

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

通過這種配置,前 3 個請求(delay)將無延遲通過,接下來的 2 個請求(burst - delay)將以延遲的方式進行處理,以確保總速率不超過指定的值,進一步過多的請求將被拒絕,因為已超出了總突發大小,後續請求將被延遲處理。

同步多個共用記憶體區域的內容 Synchronizing Contents of Many Shared Memory Zones

如果您有一個帶有多個 NGINX 實例的電腦集群,並且這些實例使用了 limit_req 方法,則可以在以下條件下同步它們的共用記憶體區域的內容:

  • 每個實例都配置了 zone_sync 功能
  • 每個實例的 limit_req_zone 指令設置的共用記憶體區域具有相同的名稱
  • 每個實例的 limit_req_zone 指令指定了 sync 參數:
http {
    #...
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s sync;
}

有關詳細信息,請參閱集群中的運行時狀態共用

限制帶寬

要限制每個連接的帶寬,可以使用 limit_rate 指令:

location /download/ {
    limit_rate 50k;
}

通過這個設置,客戶端將能夠通過單個連接以最大速度下載 50 千位元組/秒的內容。但是,客戶端可以打開多個連接。因此,如果目標是防止下載速度超過指定值,還應該限制連接的數量。例如,每個 IP 地址一個連接(如果使用上面指定的共用記憶體區域):

location /download/ {
    limit_conn addr 1;
    limit_rate 50k;
}

要在客戶端下載一定數量的數據後才施加限制,可以使用 limit_rate_after 指令。允許客戶端快速下載一定數量的數據(例如,文件頭 - 影片索引),然後限制下載其餘數據的速率可能是合理的(讓用戶觀看電影,而不是下載)。

limit_rate_after 500k;
limit_rate       20k;

下麵的示例展示了限制連接數和帶寬的組合配置。允許的最大連接數設置為每個客戶端地址 5 個連接,這適用於大多數常見情況,因為現代瀏覽器通常同時打開最多 3 個連接。同時,用於提供下載的位置只允許一個連接:

http {
    limit_conn_zone $binary_remote_address zone=addr:10m

    server {
        root /www/data;
        limit_conn addr 5;

        location / {
        }

        location /download/ {
            limit_conn       addr 1;
            limit_rate_after 1m;
            limit_rate       50k;
        }
    }
}

動態帶寬控制 Dynamic Bandwidth Control

limit_rate 值也可以指定為變數 - 這可以實現動態帶寬使用案例,例如,允許現代瀏覽器有更高的帶寬限制:

map $ssl_protocol $response_rate {
    "TLSv1.1" 10k;
    "TLSv1.2" 100k;
    "TLSv1.3" 1000k;
}

server {
    listen 443 ssl;
    ssl_protocols       TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_certificate     www.example.com.crt;
    ssl_certificate_key www.example.com.key;

    location / {
        limit_rate       $response_rate; # 根據 TLS 版本限制帶寬
        limit_rate_after 512;            # 發送頭部後應用限制
        proxy_pass       http://my_backend;
    }
}

參見

使用NGINX和NGINX Plus進行速率限制

參考資料

https://docs.nginx.com/nginx/admin-guide/security-controls/controlling-access-proxied-http/


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 文章關註JavaScript中async/await的異常處理,指出未捕獲異常的潛在風險。1)使用try-catch,雖全面但冗餘;2)藉助Promise的catch,減少冗餘; 3) 利用await-to-js庫簡化異常處理 ...
  • 大家看過黑客帝國的代碼雨嗎?本人自己寫了一個,效果還可以。演示效果請見https://www.lanbaoshi.site/coderain.htm 下麵上代碼: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http ...
  • title: Vue.js條件渲染與列表渲染指南 date: 2024/5/26 20:11:49 updated: 2024/5/26 20:11:49 categories: 前端開發 tags: VueJS 前端開發 數據綁定 列表渲染 狀態管理 路由配置 性能優化 第1章:Vue.js基礎與 ...
  • 從Vue開始較大範圍在前端應用開始,關於Vue一些基礎知識的討論和麵試問題就在開發圈子裡基本上就跟前幾年的股票和基金一樣,樓下擺攤賣醬香餅的阿姨都能說上幾句那種。找過前端開發工作或者正在找開發工作的前端都知道,面試官基本上都有那麼幾個常問的問題,而網上呢也有那麼一套可以用來背誦的“八股文”,自己懂多 ...
  • title: Vue 3指令與事件處理 date: 2024/5/25 18:53:37 updated: 2024/5/25 18:53:37 categories: 前端開發 tags: Vue3基礎 指令詳解 事件處理 高級事件 實戰案例 最佳實踐 性能優化 第1章 Vue 3基礎 1.1 V ...
  • Symbol 引用 iconfont icon圖標庫 Symbol 引用 這是一種全新的使用方式,應該說這才是未來的主流,也是平臺目前推薦的用法。相關介紹可以參考這篇文章 這種用法其實是做了一個 SVG 的集合,與另外兩種相比具有如下特點: 支持多色圖標了,不再受單色限制。 通過一些技巧,支持像字體 ...
  • 設計原則名稱 定義 使用頻率 單一職責原則 一個類只負責一個功能領域中的相應職責 四顆星 開閉原則 軟體實體應對擴展開發,而對修改關閉 五顆星 里氏代換原則 所有引用基類對象的地方能夠透明地使用其子類的對象 五顆星 依賴倒轉原則 抽象不應該依賴於細節,細節應該依賴於抽象 五顆星 介面隔離原則 使用多 ...
  • 中國程式員的特點 中國程式員的最大優點是非常勤奮。中國互聯網行業有句話叫:“they earn a lot of money but die early”(賺得多死得早)。由於工作強度大,經常有程式員突然去世的新聞報道。 996 工作制度:中國程式員通常實行“996”工作制度(即每天工作從早9點到晚 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...