主頁 > 軟體設計 > Nginx限流以及限速配置

Nginx限流以及限速配置

2021-04-08 07:51:02 軟體設計

序言

最近收到需求,需要在openresty上進行二次開發,對四層/七層負載進行限流以及限速,針對此,收集相關資料如下所示:

http限流模塊:

  • ngx_http_limit_conn_module;
  • ngx_http_limit_req_module;
  • lua-resty-limit-traffic;

stream限流模塊:

  • ngx_stream_limit_conn_module;

ngx_http_limit_conn_module

ngx_http_limit_conn_modul基于key($binary_remote_addr或者server_name),對網路總連接數進行限流,

不是所有的網路連接都會被計數器統計,只有被Nginx處理的并且已經讀取了整個請求頭的連接才會被技術器統計,

http{
    # 針對客戶端地址,進行連接數限制
    limit_conn_zone $binary_remote_addr zone=perip:10m;
    # 針對域名,進行連接數限制
    limit_conn_zone $server_name zone=perserver:10m;
    limit_conn_log_level error;
    limit_conn_status 503;

    server {
        # 每個IP僅允許發起10個連接
        limit_conn perip 10;
        # 每個域名僅允許發起100個連接
        limit_conn perserver 100;
    }
}

以上配置,節選自ngx_http_limit_conn_module官網,以下對關鍵配置項進行解釋:

  • limit_conn_zone: 用于配置限流key及存放限流key對應的共享記憶體大小;
  • limit_conn_log_level: 請求被限流后的日志級別,默認error級別;
  • limit_conn_status:請求被限流后回傳的http狀態碼,默認503;
  • limit_conn:配置存放key的共享記憶體區域名稱和指定key的最大連接數;

ngx_http_limit_req_module

ngx_http_limit_req_module基于key(基本上為客戶端IP地址)對請求進行限流(基于漏桶演算法),

http{
    # 固定請求速率為1個請求/每秒
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
    limit_req_log_level error;
    limit_req_status 503;

    server {
        location /search/ {
            # 漏桶容量為5
            limit_req zone=one burst=5 nodelay;
        }
    }  
}

以上配置,節選自ngx_http_limit_req_module官網,以下對關鍵配置項進行解釋:

  • limit_req_zone:配置限流key,存放key的共享記憶體區域大小,以及固定請求速率;
  • limit_req_log_level: 參照limit_conn_log_level;
  • limit_req_status:參照limit_conn_status;
  • limit_req: 配置限流區域,漏桶容量(突發容量,默認為0),是否采用延遲模式(默認延遲);

執行流程:

(1)請求進入后判斷最后一次請求時間相對于當前時間是否需要進行限流,若不需要,執行正常流程;否則,進入步驟2;
(2)如果未配置漏桶容量(默認0),按照固定速率處理請求,若此時請求被限流,則直接回傳503;否則,根據是否配置了延遲默認分別進入步驟3或步驟4;
(3)配置了漏桶容量以及延遲模式(未配置nodelay),若漏桶滿了,則新的請求將被限;如果漏桶沒有滿,則新的請求會以固定平均速率被處理(請求被延遲處理,基于sleep實作);
(4)配置了漏桶容量以及nodelay,新請求進入漏桶會即可處理(不進行休眠,以便處理固定數量的突發流量);若漏桶滿了,則請求被限流,直接回傳回應,

lua-resty-limit-traffic

使用場景比較固定的情況下,推薦使用自有模塊,
需求比較復雜時(產品要求動態化設定時),建議采用lua-resty-limit-traffic實作限流請求(較新的openresty已自動包含此庫,無需手動引入),

lua-resty-limit-traffic模塊主要由以下四個子模塊構成:

  • resty.limit.req:基于漏桶演算法對請求進行限流操作;
  • resty.limit.count:基于固定視窗實作流量控制;
  • resty.limit.conn:實作請求限流以及流量整形;
  • resty.limit.traffic:提供聚合器,以便整合resty.limit.req、resty.limit.count以及resty.limit.conn,
http {
    lua_shared_dict my_req_store 100m;
    lua_shared_dict my_conn_store 100m;

    server {
        location / {
            access_by_lua_block {
                local limit_conn = require "resty.limit.conn"
                local limit_req = require "resty.limit.req"
                local limit_traffic = require "resty.limit.traffic"

                -- 創建請求限流器,引數分別為共享記憶體名稱,執行速率(設定為300個請求/每秒),漏桶容量
                local lim1, err = limit_req.new("my_req_store", 300, 200)
                assert(lim1, err)
                -- 創建請求限流器
                local lim2, err = limit_req.new("my_req_store", 200, 100)
                assert(lim2, err)
                -- 創建連接限流器,引數分別為共享記憶體名稱,最大連接數(超過最大連接數,小于最大連接數+漏桶容量的連接將被延遲處理),漏桶容量,初始連接延遲時間
                local lim3, err = limit_conn.new("my_conn_store", 1000, 1000, 0.5)
                assert(lim3, err)

                local limiters = {lim1, lim2, lim3}

                local host = ngx.var.host
                local client = ngx.var.binary_remote_addr
                -- 傳入限流器所使用的key,lim1基于請求中的‘Host’,lim2基于客戶端地址,lim3基于客戶端地址
                local keys = {host, client, client}

                local states = {}

                -- 聚合限流器,完成復合功能
                local delay, err = limit_traffic.combine(limiters, keys, states)
                if not delay then
                    if err == "rejected" then
                        -- 請求被限流,回傳503
                        return ngx.exit(503)
                    end
                    -- 限流器內部執行存在錯誤,回傳500
                    ngx.log(ngx.ERR, "failed to limit traffic: ", err)
                    return ngx.exit(500)
                end

                if lim3:is_committed() then
                    -- 當前請求未被限流,且連接被記錄到共享記憶體中(可以不記錄,采用dry run方式)
                    local ctx = ngx.ctx
                    ctx.limit_conn = lim3
                    ctx.limit_conn_key = keys[3]
                end

                print("sleeping ", delay, " sec, states: ",
                      table.concat(states, ", "))

                if delay >= 0.001 then
                    -- 超過漏桶容量,未被限流的請求,需要休眠一段時間以保證請求勻速執行
                    ngx.sleep(delay)    
                end
            }

            log_by_lua_block {
                local ctx = ngx.ctx
                local lim = ctx.limit_conn
                if lim then
                    -- if you are using an upstream module in the content phase,
                    -- then you probably want to use $upstream_response_time
                    -- instead of $request_time below.
                    -- 記錄http請求的回應時間,如果有upstream module,那么建議使用$upstream_response_time代替$request_time
                    local latency = tonumber(ngx.var.request_time)
                    local key = ctx.limit_conn_key
                    assert(key)
                    -- 根據當前http請求的執行時間,更新請求的延遲時間 
                    local conn, err = lim:leaving(key, latency)
                    if not conn then
                        ngx.log(ngx.ERR,
                                "failed to record the connection leaving ",
                                "request: ", err)
                        return
                    end
                end
            }
        }
    }
}

以上配置,節選自lua-resty-limit-traffic代碼倉庫,因為配置項較多,因此部分配置,在配置項通過注釋進行解釋,

由以上配置可知,lua-resty-limit-traffic的配置可以進行組合,此外key的指定也比較靈活,此外lua-resty-limit-traffic模塊已經被正式包含在openresty發行版中(無需手動安裝),被大范圍使用,具有較高的穩定性,

ngx_stream_limit_conn_module

此模塊在TCP/UDP會話的Pre-access階段被處理,

stream {
    # 客戶端地址限流共享記憶體區域
    limit_conn_zone $binary_remote_addr zone=addr:10m;

    server {
        # 限制每個客戶端僅能發起一個連接 
        limit_conn           addr 1;
        # 限流記錄日志級別
        limit_conn_log_level error;
    }
}

Nginx對于stream模塊的支持度,現階段還不夠高,限流模塊,僅能針對客戶端地址進行連接限流(stream模塊中,無$server_name屬性),

限速配置

stream {
    upstream site {
        server your.upload-api.domain1:8080;
        server your.upload-api.domain1:8080;
    }

    server {
        listen    12345;
        proxy_pass site;

        # 19 MiB/min = ~332k/s,限制上行和下行的速率均為19MiB/min
        proxy_upload_rate 332k;
        proxy_download_rate 332k;
    }
}

http {

  server {
    location = /upload {
        
        # 關閉請求快取,請求直接代理至后端
        proxy_request_buffering off;    
        
        # It will pass to the stream
        # Then the stream passes to your.api.domain1:8080/upload?$args
        proxy_pass http://127.0.0.1:12345/upload?$args;
   
    }

    location /download {
        # 下載大檔案,需要調整超時時間/keepalive至較大數值
        keepalive_timeout  28800s;
        proxy_read_timeout 28800s;  
        proxy_buffering on;

        # 75MiB/min = ~1300kilobytes/s
        # 限制Nginx讀取后端回應速率(需要開啟代理快取才能生效)
        # proxy_limit_rate 1300k; 
        
        # 下載500k之后,進行限速(適用于小檔案下載)
        limit_rate_after 500k;
        # 限制下載速度為50k/每秒
        limit_rate       50k;

        proxy_pass your.api.domain1:8080;
    }
  }
}

限速配置,詳見注釋內容,

補充知識

max_conns:

upstream backend {
    server backend1.example.com weight=5 max_conns=5;
}

在upstream模塊中,可以針對server設定max_conns引數,
此引數的實際作用是,限制同一時間段內,連接到后端的最大連接數,以保證后端服務不被突發的連接沖垮,

request_time與upstream_response_time

  • request_time:Nginx接收客戶端請求,到發送完回應的時間段;
  • upstream_response_time:Nginx建立到后端的連接,到接收完代理后端回應的時間;

衡量系統回應時間,因為request_time受客戶端連接質量影響較大,應該使用upstream_response_time作為衡量標準,

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/273563.html

標籤:其他

上一篇:java 考試系統 在線學習 視頻直播 人臉識別 springboot框架 前后分離 PC和手機端

下一篇:java 考試系統 在線學習 視頻直播 人臉識別 springboot框架 前后分離 PC和手機端

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more