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 toujoursrejected, 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'objetRedis 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 :
- Si la requête ne dépasse pas la valeur
ratespécifiée dans la méthode new, alors cette méthode retourne0comme délai et le nombre (zéro) de requêtes excessives par seconde au moment actuel. - Si la requête dépasse la limite
ratespécifiée dans la méthode new mais pas la valeurrate+burst, alors cette méthode retourne un délai approprié (en secondes) pour la requête actuelle afin qu'elle soit toujours conforme au seuilratecomme 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). - Si la requête dépasse la limite
rate+burst, alors cette méthode retournenilet la chaîne d'erreur"rejected". - Si une erreur se produit, alors cette méthode retourne
nilet 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
- Limitation de Taux avec NGINX : https://www.nginx.com/blog/rate-limiting-nginx/
- le module ngx_lua : https://github.com/openresty/lua-nginx-module
- OpenResty : https://openresty.org/
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.