Aller au contenu

redis-ratelimit: Limiter le taux de traitement des requêtes entre plusieurs instances NGINX soutenues par Redis

Installation

Si vous n'avez pas configuré l'abonnement au dépôt RPM, inscrivez-vous. Ensuite, vous pouvez procéder avec les étapes suivantes.

CentOS/RHEL 7 ou 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-redis-ratelimit

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

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

Pour utiliser cette bibliothèque Lua avec NGINX, assurez-vous que le nginx-module-lua est installé.

Ce document décrit lua-resty-redis-ratelimit v0.3 publié le 03 octobre 2019.


Cette bibliothèque lua est un module de limitation du taux de traitement des requêtes pour ngx_lua :

http://wiki.nginx.org/HttpLuaModule

Elle est utilisée pour limiter le taux de traitement des requêtes par une clé définie entre plusieurs instances NGINX. La limitation est effectuée en utilisant la méthode "leaky bucket".

Ce module utilise Redis (>= 2.6.0) comme stockage backend, donc vous avez également besoin de la bibliothèque lua-resty-redis pour travailler avec.

AVIS : Si vous n'utilisez pas la fonctionnalité duration et que le trafic entrant est uniformément réparti, il est recommandé d'utiliser le module resty.limit.req pour éviter des retards réseau inutiles.

Synopsis

server {

    listen 9090;

    location /t {
        access_by_lua_block {
            local ratelimit = require "resty.redis.ratelimit"

            local lim, err = ratelimit.new("one", "2r/s", 0, 2)
            if not lim then
                ngx.log(ngx.ERR,
                        "échec de l'instanciation d'un objet resty.redis.ratelimit : ", err)
                return ngx.exit(500)
            end

            -- AVIS : l'appel suivant doit être par requête.

            -- local redis = require "resty.redis"
            -- local red = redis:new()

            -- red:set_timeout(1000)

            -- local ok, err = red:connect("127.0.0.1", 6379)
            -- if not ok then
            --     ngx.log(ngx.ERR, "échec de la connexion à redis : ", err)
            --     return ngx.exit(500)
            -- end

            local red = { host = "127.0.0.1", port = 6379, timeout = 1 }

            local key = ngx.var.binary_remote_addr
            local delay, err = lim:incoming(key, red)
            if not delay then
                if err == "rejected" then
                    return ngx.exit(503)
                end
                ngx.log(ngx.ERR, "échec de la limitation de la requête : ", err)
                return ngx.exit(500)
            end

            if delay >= 0.001 then
                -- la 2ème valeur de retour contient le nombre de requêtes excessives
                -- par seconde pour la clé spécifiée.
                local excess = err

                ngx.sleep(delay)
            end
        '}

        echo Connecté;
    }

}

Méthodes

new

syntax: obj, err = class.new(zone, rate, burst, duration)

Instancie un objet de cette classe. La valeur de la classe est retournée par l'appel require resty.redis.ratelimit.

Cette méthode prend les arguments suivants :

  • zone : Définit l'espace de noms, en particulier, nous utilisons la chaîne <zone>:<key> comme identifiant d'état unique à l'intérieur de Redis.
  • rate : Le taux est spécifié en requêtes par seconde (r/s). Si un taux de moins d'une requête par seconde est souhaité, il est spécifié en requêtes par minute (r/m). Par exemple, une demi-requête par seconde est 30r/m.
  • burst : Définit combien de requêtes peuvent être effectuées en excès du taux spécifié par la zone, par défaut 0.
  • duration : Le délai (en secondes) avant de revenir à l'état normal, pendant cette période, la requête est toujours rejected, par défaut 0.

En cas d'échec, cette méthode retourne nil et une chaîne décrivant l'erreur.

incoming

syntax: delay, err = obj:incoming(key, redis)

Déclenche un nouvel événement de requête entrante et calcule le délai nécessaire (le cas échéant) pour la requête actuelle sur la clé spécifiée ou détermine si l'utilisateur doit la rejeter immédiatement.

Cette méthode accepte les arguments suivants :

  • key : La clé est toute valeur non vide de la variable spécifiée.
  • redis : Définit la configuration Redis, host, port, timeout, etc. (voir ci-dessous) ; Au lieu de la configuration Redis spécifique, vous pouvez également définir directement l'objet Redis connecté.
- redis.host : Par défaut 127.0.0.1.
- redis.port : Par défaut 80.
- redis.timeout : Par défaut 1s.
- redis.pass : Demande d'authentification dans un serveur Redis protégé par mot de passe.
- redis.dbid : Sélectionne la base de données logique Redis.

Les valeurs de retour dépendent des cas suivants :

  1. Si la requête ne dépasse pas la valeur rate spécifiée dans la méthode new, alors cette méthode retourne 0 comme délai et le nombre (zéro) de requêtes excessives par seconde au moment actuel.
  2. Si la requête dépasse la limite rate spécifiée dans la méthode new mais pas la valeur rate + burst, alors cette méthode retourne un délai approprié (en secondes) pour la requête actuelle afin qu'elle soit toujours conforme au seuil rate comme si elle arrivait un peu plus tard plutôt qu'à présent. La 2ème valeur de retour indique le nombre de requêtes excessives par seconde à ce moment-là (y compris la requête actuelle).
  3. Si la requête dépasse la limite rate + burst, alors cette méthode retourne nil et la chaîne d'erreur "rejected".
  4. Si une erreur se produit, alors cette méthode retourne nil et une chaîne décrivant l'erreur. Par exemple, "échec de la création de redis - connexion refusée".

Cette méthode ne dort jamais elle-même. Elle retourne simplement un délai si nécessaire et exige que l'appelant invoque plus tard la méthode ngx.sleep pour dormir.

set_burst

syntax: obj:set_burst(burst)

Écrase le seuil burst tel que spécifié dans la méthode new.

Voir Aussi

GitHub

Vous pouvez trouver des conseils de configuration supplémentaires et de la documentation pour ce module dans le dépôt GitHub pour nginx-module-redis-ratelimit.