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-graphql
ygraphql
. - Esquema y Resolvers: Definimos un esquema simple con una consulta
hello
y su resolver correspondiente. - Express App: Creamos una instancia de Express.
- Rate Limiter: Configuramos
express-rate-limit
para 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