El rate limiting, o limitación de tasa, es una técnica para controlar el número de solicitudes que un usuario o IP puede hacer a un servidor en un período de tiempo específico. En Nginx, se puede implementar rate limiting con el uso de Redis o Memcached como backend de almacenamiento, lo que permite almacenar los contadores de solicitudes en estos sistemas de caché y mejorar el rendimiento en configuraciones distribuidas.
El rate limiting en Nginx es una configuración que restringe el acceso de usuarios mediante un límite de solicitudes en un intervalo de tiempo determinado. Al utilizar Redis o Memcached, los contadores de las solicitudes se almacenan en una base de datos en memoria, lo que es ideal para entornos distribuidos donde múltiples instancias de Nginx comparten el mismo límite de tasa para todos los usuarios.
Nginx puede trabajar con Redis para gestionar el rate limiting utilizando módulos adicionales, como el ngx_http_redis o lua-resty-redis de Lua, disponible con OpenResty.
1. Instalar OpenResty (distribución de Nginx que soporta Lua).
2. Configurar el rate limiting en Lua:
http {
lua_shared_dict limits 10m;
server {
location / {
access_by_lua_block {
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(1000) -- 1 segundo de timeout
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.log(ngx.ERR, "failed to connect to Redis: ", err)
return ngx.exit(500)
end
local key = "rate_limit:" .. ngx.var.remote_addr
local limit = 100 -- límite de 100 solicitudes
local expires_in = 60 -- en 60 segundos
local current, err = red:get(key)
if current == ngx.null then
red:set(key, 1)
red:expire(key, expires_in)
else
if tonumber(current) >= limit then
ngx.exit(429)
else
red:incr(key)
end
end
}
proxy_pass http://backend;
}
}
}
En este ejemplo:
127.0.0.1:6379
.
429 Too Many Requests
.
Aunque Memcached no es comúnmente utilizado para rate limiting en Nginx, se puede implementar mediante el uso de Lua y OpenResty.
http {
lua_shared_dict limits 10m;
server {
location / {
access_by_lua_block {
local memcached = require "resty.memcached"
local memc = memcached:new()
memc:set_timeout(1000) -- 1 segundo de timeout
local ok, err = memc:connect("127.0.0.1", 11211)
if not ok then
ngx.log(ngx.ERR, "failed to connect to Memcached: ", err)
return ngx.exit(500)
end
local key = "rate_limit:" .. ngx.var.remote_addr
local limit = 100 -- límite de 100 solicitudes
local expires_in = 60 -- en 60 segundos
local current, flags, err = memc:get(key)
if not current then
memc:set(key, 1, expires_in)
else
if tonumber(current) >= limit then
ngx.exit(429)
else
memc:incr(key, 1)
end
end
}
proxy_pass http://backend;
}
}
}
En este ejemplo:
127.0.0.1:11211
.
429 Too Many Requests
.
Parámetro | Descripción |
---|---|
key
|
Clave única para identificar al usuario o IP (ej. rate_limit:remote_addr ).
|
limit
|
Número máximo de solicitudes permitidas en el intervalo de tiempo especificado. |
expires_in
|
Tiempo en segundos que define el intervalo para la limitación de tasa. |
redis:connect()
|
Función de Lua para conectarse a Redis. |
memcached:connect()
|
Función de Lua para conectarse a Memcached. |
1. Límite de tasa por usuario autenticado:
local user_id = ngx.var.cookie_user_id or ngx.var.arg_user_id
local key = "rate_limit:" .. user_id
2. Aplicar un límite menos restrictivo (200 solicitudes):
local limit = 200
3. Límite de tasa con expiración de 120 segundos:
local expires_in = 120
Para más detalles sobre la configuración avanzada de rate limiting en Nginx con Redis o Memcached, consulta la documentación de OpenResty y la documentación oficial de Nginx.
Jorge García
Fullstack developer