Zum Inhalt

limit-traffic: Lua-Bibliothek zur Begrenzung und Kontrolle des Verkehrs im nginx-module-lua

Installation

Wenn Sie noch kein RPM-Repository-Abonnement eingerichtet haben, melden Sie sich an. Danach können Sie mit den folgenden Schritten fortfahren.

CentOS/RHEL 7 oder Amazon Linux 2

yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-limit-traffic

CentOS/RHEL 8+, Fedora Linux, Amazon Linux 2023

dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-limit-traffic

Um diese Lua-Bibliothek mit NGINX zu verwenden, stellen Sie sicher, dass nginx-module-lua installiert ist.

Dieses Dokument beschreibt lua-resty-limit-traffic v0.9, das am 08. August 2023 veröffentlicht wurde.


## demonstrieren der Verwendung des resty.limit.req Moduls (allein!)
http {
    lua_shared_dict my_limit_req_store 100m;

    server {
        location / {
            access_by_lua_block {
                -- nun, wir könnten die require() und new() Aufrufe in unsere eigenen Lua
                -- Module setzen, um Overhead zu sparen. Hier setzen wir sie nur zur
                -- Bequemlichkeit darunter.

                local limit_req = require "resty.limit.req"

                -- die Anfragen unter 200 req/sec mit einem Burst von 100 req/sec begrenzen,
                -- das heißt, wir verzögern Anfragen unter 300 req/sec und über 200
                -- req/sec und lehnen alle Anfragen ab, die 300 req/sec überschreiten.
                local lim, err = limit_req.new("my_limit_req_store", 200, 100)
                if not lim then
                    ngx.log(ngx.ERR,
                            "Fehler beim Instanziieren eines resty.limit.req Objekts: ", err)
                    return ngx.exit(500)
                end

                -- der folgende Aufruf muss pro Anfrage erfolgen.
                -- hier verwenden wir die Remote (IP) Adresse als das begrenzende Schlüssel
                local key = ngx.var.binary_remote_addr
                local delay, err = lim:incoming(key, true)
                if not delay then
                    if err == "rejected" then
                        return ngx.exit(503)
                    end
                    ngx.log(ngx.ERR, "Fehler beim Begrenzen der Anfragen: ", err)
                    return ngx.exit(500)
                end

                if delay >= 0.001 then
                    -- der 2. Rückgabewert enthält die Anzahl der überschüssigen Anfragen
                    -- pro Sekunde für den angegebenen Schlüssel. Zum Beispiel bedeutet die Zahl 31
                    -- dass die aktuelle Anfragequote bei 231 req/sec für den
                    -- angegebenen Schlüssel liegt.
                    local excess = err

                    -- die Anfrage überschreitet die 200 req/sec, liegt aber unter 300 req/sec,
                    -- daher verzögern wir sie hier absichtlich ein wenig, um der
                    -- Rate von 200 req/sec zu entsprechen.
                    ngx.sleep(delay)
                end
            }

            # Inhaltshandler kommt hierhin. Wenn es content_by_lua ist, können Sie
            # den oben stehenden Lua-Code in access_by_lua in den Lua-Handler Ihres
            # content_by_lua integrieren, um ein wenig CPU-Zeit zu sparen.
        }
    }
}
## demonstrieren der Verwendung des resty.limit.conn Moduls (allein!)
http {
    lua_shared_dict my_limit_conn_store 100m;

    server {
        location / {
            access_by_lua_block {
                -- nun, wir könnten die require() und new() Aufrufe in unsere eigenen Lua
                -- Module setzen, um Overhead zu sparen. Hier setzen wir sie nur zur
                -- Bequemlichkeit darunter.

                local limit_conn = require "resty.limit.conn"

                -- die Anfragen unter 200 gleichzeitigen Anfragen (normalerweise nur
                -- eingehende Verbindungen, es sei denn, Protokolle wie SPDY werden verwendet) mit
                -- einem Burst von 100 zusätzlichen gleichzeitigen Anfragen begrenzen, das heißt, wir verzögern
                -- Anfragen unter 300 gleichzeitigen Verbindungen und über 200
                -- Verbindungen und lehnen alle neuen Anfragen ab, die 300
                -- Verbindungen überschreiten.
                -- außerdem gehen wir von einer standardmäßigen Anfragezeit von 0,5 Sek. aus, die durch
                -- den leaving() Aufruf in log_by_lua unten dynamisch angepasst werden kann.
                local lim, err = limit_conn.new("my_limit_conn_store", 200, 100, 0.5)
                if not lim then
                    ngx.log(ngx.ERR,
                            "Fehler beim Instanziieren eines resty.limit.conn Objekts: ", err)
                    return ngx.exit(500)
                end

                -- der folgende Aufruf muss pro Anfrage erfolgen.
                -- hier verwenden wir die Remote (IP) Adresse als das begrenzende Schlüssel
                local key = ngx.var.binary_remote_addr
                local delay, err = lim:incoming(key, true)
                if not delay then
                    if err == "rejected" then
                        return ngx.exit(503)
                    end
                    ngx.log(ngx.ERR, "Fehler beim Begrenzen der Anfragen: ", err)
                    return ngx.exit(500)
                end

                if lim:is_committed() then
                    local ctx = ngx.ctx
                    ctx.limit_conn = lim
                    ctx.limit_conn_key = key
                    ctx.limit_conn_delay = delay
                end

                -- der 2. Rückgabewert enthält das aktuelle Niveau der Gleichzeitigkeit
                -- für den angegebenen Schlüssel.
                local conn = err

                if delay >= 0.001 then
                    -- die Anfrage überschreitet das Verhältnis von 200 Verbindungen, liegt aber unter
                    -- 300 Verbindungen, daher
                    -- verzögern wir sie hier absichtlich ein wenig, um der
                    -- Begrenzung von 200 Verbindungen zu entsprechen.
                    -- ngx.log(ngx.WARN, "verzögere")
                    ngx.sleep(delay)
                end
            }

            # Inhaltshandler kommt hierhin. Wenn es content_by_lua ist, können Sie
            # den oben stehenden Lua-Code in access_by_lua in Ihren
            # content_by_lua Lua-Handler integrieren, um ein wenig CPU-Zeit zu sparen.

            log_by_lua_block {
                local ctx = ngx.ctx
                local lim = ctx.limit_conn
                if lim then
                    -- wenn Sie ein Upstream-Modul in der Inhaltsphase verwenden,
                    -- möchten Sie wahrscheinlich $upstream_response_time
                    -- anstelle von ($request_time - ctx.limit_conn_delay) unten verwenden.
                    local latency = tonumber(ngx.var.request_time) - ctx.limit_conn_delay
                    local key = ctx.limit_conn_key
                    assert(key)
                    local conn, err = lim:leaving(key, latency)
                    if not conn then
                        ngx.log(ngx.ERR,
                                "Fehler beim Aufzeichnen der Verbindung, die die ",
                                "Anfrage verlässt: ", err)
                        return
                    end
                end
            }
        }
    }
}
## demonstrieren der Verwendung des resty.limit.traffic Moduls
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"

                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
                local keys = {host, client, client}

                local states = {}

                local delay, err = limit_traffic.combine(limiters, keys, states)
                if not delay then
                    if err == "rejected" then
                        return ngx.exit(503)
                    end
                    ngx.log(ngx.ERR, "Fehler beim Begrenzen des Verkehrs: ", err)
                    return ngx.exit(500)
                end

                if lim3:is_committed() then
                    local ctx = ngx.ctx
                    ctx.limit_conn = lim3
                    ctx.limit_conn_key = keys[3]
                end

                print("schlafe ", delay, " sec, zustände: ",
                      table.concat(states, ", "))

                if delay >= 0.001 then
                    ngx.sleep(delay)
                end
            }

            # Inhaltshandler kommt hierhin. Wenn es content_by_lua ist, können Sie
            # den oben stehenden Lua-Code in access_by_lua in Ihren
            # content_by_lua Lua-Handler integrieren, um ein wenig CPU-Zeit zu sparen.

            log_by_lua_block {
                local ctx = ngx.ctx
                local lim = ctx.limit_conn
                if lim then
                    -- wenn Sie ein Upstream-Modul in der Inhaltsphase verwenden,
                    -- möchten Sie wahrscheinlich $upstream_response_time
                    -- anstelle von $request_time unten verwenden.
                    local latency = tonumber(ngx.var.request_time)
                    local key = ctx.limit_conn_key
                    assert(key)
                    local conn, err = lim:leaving(key, latency)
                    if not conn then
                        ngx.log(ngx.ERR,
                                "Fehler beim Aufzeichnen der Verbindung, die die ",
                                "Anfrage verlässt: ", err)
                        return
                    end
                end
            }
        }
    }
}

Beschreibung

Diese Bibliothek bietet mehrere Lua-Module, um OpenResty/ngx_lua-Benutzern zu helfen, den Verkehr zu kontrollieren und zu begrenzen, entweder die Anfragequote oder die Anfragegleichzeitigkeit (oder beides).

Bitte sehen Sie sich die eigene Dokumentation dieser Lua-Module für weitere Details an.

Diese Bibliothek bietet flexiblere Alternativen zu den Standardmodulen von NGINX ngx_limit_req und ngx_limit_conn. Zum Beispiel können die von dieser Bibliothek bereitgestellten Lua-basierten Begrenzungen in jedem Kontext verwendet werden, wie direkt vor dem SSL-Handschlagverfahren (wie bei ssl_certificate_by_lua) oder direkt vor der Ausgabe von Backend-Anfragen.

nginx.conf

http { ... }

und laden Sie dann eines der von dieser Bibliothek bereitgestellten Module in Lua. Zum Beispiel,

```lua
local limit_req = require "resty.limit.req"

Siehe auch

GitHub

Sie finden möglicherweise zusätzliche Konfigurationstipps und Dokumentationen für dieses Modul im GitHub-Repository für nginx-module-limit-traffic.