redis-ratelimit: Limite a taxa de processamento de requisições entre várias instâncias do NGINX suportadas pelo Redis
Instalação
Se você ainda não configurou a assinatura do repositório RPM, inscreva-se. Depois, você pode prosseguir com os seguintes passos.
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
Para usar esta biblioteca Lua com o NGINX, certifique-se de que o nginx-module-lua esteja instalado.
Este documento descreve lua-resty-redis-ratelimit v0.3 lançado em 03 de outubro de 2019.
Esta biblioteca lua é um módulo de limite de taxa de processamento de requisições para ngx_lua:
http://wiki.nginx.org/HttpLuaModule
Ela é usada para limitar a taxa de processamento de requisições por uma chave definida entre várias instâncias do NGINX. A limitação é feita usando o método "leaky bucket".

Este módulo usa Redis (>= 2.6.0) como armazenamento backend, então você também precisa da biblioteca lua-resty-redis para trabalhar com ela.
AVISO: Se você não usar o recurso duration e o tráfego de entrada estiver distribuído uniformemente, é recomendável usar o módulo resty.limit.req para evitar atrasos de rede desnecessários.
Sinopse
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,
"falha ao instanciar um objeto resty.redis.ratelimit: ", err)
return ngx.exit(500)
end
-- AVISO: a chamada a seguir deve ser por requisição.
-- 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, "falha ao conectar ao 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, "falha ao limitar req: ", err)
return ngx.exit(500)
end
if delay >= 0.001 then
-- o 2º valor de retorno contém o número de requisições excessivas
-- por segundo para a chave especificada.
local excess = err
ngx.sleep(delay)
end
'}
echo Logged in;
}
}
Métodos
new
sintaxe: obj, err = class.new(zone, rate, burst, duration)
Instancia um objeto desta classe. O valor da classe é retornado pela chamada require resty.redis.ratelimit.
Este método aceita os seguintes argumentos:
zone: Define o namespace, em particular, usamos a string<zone>:<key>como um identificador de estado único dentro do Redis.rate: A taxa é especificada em requisições por segundo (r/s). Se uma taxa de menos de uma requisição por segundo for desejada, ela é especificada em requisições por minuto (r/m). Por exemplo, meia requisição por segundo é 30r/m.burst: Define quantas requisições podem ser feitas em excesso da taxa especificada pela zona, padrão 0.duration: O atraso de tempo (em segundos) antes de voltar ao estado normal, durante este período, a requisição é semprerejected, padrão 0.
Em caso de falha, este método retorna nil e uma string descrevendo o erro.
incoming
sintaxe: delay, err = obj:incoming(key, redis)
Dispara um novo evento de requisição de entrada e calcula o atraso necessário (se houver) para a requisição atual com base na chave especificada ou se o usuário deve rejeitá-la imediatamente.
Este método aceita os seguintes argumentos:
key: A chave é qualquer valor não vazio da variável especificada.redis: Define a configuração do Redis,host,port,timeoute assim por diante (veja abaixo); Em vez da configuração específica do Redis, você também pode definir oobjectdo Redis conectado diretamente.
- redis.host: Padrão 127.0.0.1.
- redis.port: Padrão 80.
- redis.timeout: Padrão 1s.
- redis.pass: Solicitação de autenticação em um servidor Redis protegido por senha.
- redis.dbid: Seleciona o banco de dados lógico do Redis.
Os valores de retorno dependem dos seguintes casos:
- Se a requisição não exceder o valor
rateespecificado no método new, então este método retorna0como o atraso e o número (zero) de requisições excessivas por segundo no momento atual. - Se a requisição exceder o limite
rateespecificado no método new, mas não o valorrate+burst, então este método retorna um atraso apropriado (em segundos) para a requisição atual, de modo que ainda se conforme ao limiterate, como se tivesse chegado um pouco mais tarde do que agora. O 2º valor de retorno indica o número de requisições excessivas por segundo neste ponto (incluindo a requisição atual). - Se a requisição exceder o limite
rate+burst, então este método retornanile a string de erro"rejected". - Se um erro ocorrer, então este método retorna
nile uma string descrevendo o erro. Como"falha ao criar redis - conexão recusada".
Este método nunca dorme por si só. Ele simplesmente retorna um atraso se necessário e requer que o chamador invoque posteriormente o método ngx.sleep para dormir.
set_burst
sintaxe: obj:set_burst(burst)
Sobrescreve o limite burst conforme especificado no método new.
Veja Também
- Limitação de Taxa com NGINX: https://www.nginx.com/blog/rate-limiting-nginx/
- o módulo ngx_lua: https://github.com/openresty/lua-nginx-module
- OpenResty: https://openresty.org/
GitHub
Você pode encontrar dicas adicionais de configuração e documentação para este módulo no repositório do GitHub para nginx-module-redis-ratelimit.