La limitación de tasa (Rate Limiting) es una técnica utilizada para controlar la cantidad de solicitudes que un cliente puede hacer a un servidor en un período de tiempo determinado. Esto es crucial para proteger tu servidor GraphQL de abusos y garantizar un rendimiento estable y predecible.
¿Por qué es Importante la Limitación de Tasa?
- Protección contra Abuso: Evita que un solo cliente consuma todos los recursos del servidor.
- Estabilidad del Sistema: Mantiene el rendimiento del servidor bajo control, evitando sobrecargas.
- Equidad: Asegura que todos los clientes tengan acceso justo a los recursos del servidor.
- Seguridad: Puede ayudar a mitigar ataques de denegación de servicio (DoS).
Estrategias Comunes de Limitación de Tasa
- Límite Fijo (Fixed Window): Permite un número fijo de solicitudes en un período de tiempo determinado.
- Ventana Deslizante (Sliding Window): Permite un número fijo de solicitudes en un período de tiempo, pero la ventana se desliza con cada solicitud.
- Token Bucket: Utiliza un "cubo" de tokens que se llenan a una tasa constante. Cada solicitud consume un token.
- Leaky Bucket: Similar al Token Bucket, pero las solicitudes se procesan a una tasa constante, y el exceso se descarta.
Implementación de Limitación de Tasa en GraphQL
Ejemplo con Express.js y express-rate-limit
Vamos a implementar una limitación de tasa básica utilizando express-rate-limit en un servidor GraphQL configurado con Express.js.
-
Instalación de Dependencias
npm install express express-rate-limit express-graphql graphql -
Configuración del Servidor
const express = require('express'); const { graphqlHTTP } = require('express-graphql'); const { buildSchema } = require('graphql'); const rateLimit = require('express-rate-limit'); // Definir el esquema de GraphQL const schema = buildSchema(` type Query { hello: String } `); // Definir los resolvers const root = { hello: () => { return 'Hello, world!'; }, }; // Crear una instancia de Express const app = express(); // Configurar la limitación de tasa const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutos max: 100, // Limitar cada IP a 100 solicitudes por ventana message: 'Too many requests from this IP, please try again later.' }); // Aplicar la limitación de tasa a todas las rutas app.use(limiter); // Configurar el endpoint de GraphQL app.use('/graphql', graphqlHTTP({ schema: schema, rootValue: root, graphiql: true, })); // Iniciar el servidor app.listen(4000, () => { console.log('Running a GraphQL API server at http://localhost:4000/graphql'); });
Explicación del Código
- Dependencias: Importamos
express,express-rate-limit,express-graphqlygraphql. - Esquema y Resolvers: Definimos un esquema simple con una consulta
helloy su resolver correspondiente. - Express App: Creamos una instancia de Express.
- Rate Limiter: Configuramos
express-rate-limitpara permitir un máximo de 100 solicitudes por IP cada 15 minutos. - Middleware: Aplicamos el middleware de limitación de tasa a todas las rutas.
- GraphQL Endpoint: Configuramos el endpoint de GraphQL con
express-graphql. - Servidor: Iniciamos el servidor en el puerto 4000.
Ejercicio Práctico
Ejercicio
- Objetivo: Implementar una limitación de tasa en un servidor GraphQL que permita un máximo de 50 solicitudes por IP cada 10 minutos.
- Instrucciones:
- Modifica el código anterior para ajustar la ventana de tiempo y el número máximo de solicitudes.
- Prueba el servidor enviando más de 50 solicitudes en 10 minutos desde la misma IP y observa el mensaje de error.
Solución
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { buildSchema } = require('graphql');
const rateLimit = require('express-rate-limit');
// Definir el esquema de GraphQL
const schema = buildSchema(`
type Query {
hello: String
}
`);
// Definir los resolvers
const root = {
hello: () => {
return 'Hello, world!';
},
};
// Crear una instancia de Express
const app = express();
// Configurar la limitación de tasa
const limiter = rateLimit({
windowMs: 10 * 60 * 1000, // 10 minutos
max: 50, // Limitar cada IP a 50 solicitudes por ventana
message: 'Too many requests from this IP, please try again later.'
});
// Aplicar la limitación de tasa a todas las rutas
app.use(limiter);
// Configurar el endpoint de GraphQL
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
// Iniciar el servidor
app.listen(4000, () => {
console.log('Running a GraphQL API server at http://localhost:4000/graphql');
});Conclusión
La limitación de tasa es una técnica esencial para proteger tu servidor GraphQL de abusos y mantener un rendimiento estable. En este módulo, aprendimos sobre diferentes estrategias de limitación de tasa y cómo implementarlas en un servidor GraphQL utilizando express-rate-limit. Asegúrate de ajustar los parámetros de limitación de tasa según las necesidades específicas de tu aplicación para lograr un equilibrio entre seguridad y usabilidad.
En el próximo tema, exploraremos la Autenticación y Autorización en GraphQL, donde aprenderemos a proteger nuestras consultas y mutaciones con mecanismos de seguridad robustos.
Curso de GraphQL
Módulo 1: Introducción a GraphQL
- ¿Qué es GraphQL?
- GraphQL vs REST
- Configuración de un Servidor GraphQL
- Conceptos Básicos del Esquema de GraphQL
Módulo 2: Conceptos Fundamentales
Módulo 3: Diseño Avanzado de Esquemas
Módulo 4: Trabajando con Datos
Módulo 5: Rendimiento y Seguridad
Módulo 6: Herramientas y Ecosistema
Módulo 7: Pruebas y Despliegue
- Pruebas Unitarias de Resolvers
- Pruebas de Integración
- Integración Continua
- Despliegue de Servidores GraphQL
