La limitació de velocitat (rate limiting) és una tècnica essencial per protegir les API de GraphQL contra l'ús excessiu i els atacs de denegació de servei (DoS). Aquesta tècnica ajuda a controlar el nombre de sol·licituds que un client pot fer en un període de temps determinat, assegurant que els recursos del servidor es distribueixin de manera equitativa i que el sistema es mantingui estable i segur.
Objectius de la limitació de velocitat
- Protecció contra abusos: Evitar que un sol client consumeixi una quantitat desproporcionada de recursos.
- Estabilitat del sistema: Mantenir el rendiment del servidor sota control, especialment durant pics de trànsit.
- Seguretat: Prevenir atacs de denegació de servei (DoS) i altres formes d'abús.
Estratègies de limitació de velocitat
- Token Bucket
El mètode del "cubell de tokens" és una de les tècniques més comunes per implementar la limitació de velocitat. Funciona de la següent manera:
- Cada client té un "cubell" que conté un nombre limitat de tokens.
- Cada sol·licitud consumeix un token del cubell.
- Els tokens es regeneren a una taxa fixa amb el temps.
- Si el cubell es queda sense tokens, les sol·licituds addicionals es rebutgen fins que es regenerin més tokens.
- Fixed Window
En aquest mètode, es defineix una finestra de temps fixa (per exemple, 1 minut) durant la qual es permet un nombre determinat de sol·licituds. Si un client supera aquest límit dins de la finestra de temps, les sol·licituds addicionals es rebutgen fins que comenci la següent finestra.
- Sliding Window
Aquesta tècnica és una variació del mètode de finestra fixa, però amb una finestra de temps que es mou contínuament. Això proporciona una limitació de velocitat més suau i precisa.
- Leaky Bucket
Similar al "Token Bucket", però en lloc de regenerar tokens, les sol·licituds es processen a una taxa constant. Si les sol·licituds arriben més ràpidament del que es poden processar, es posen en cua i es processen més tard.
Implementació de la limitació de velocitat en GraphQL
Exemple pràctic amb Express.js i Apollo Server
A continuació, es mostra un exemple de com implementar la limitació de velocitat en un servidor GraphQL utilitzant Express.js i Apollo Server.
Instal·lació de dependències
Primer, instal·lem les dependències necessàries:
Configuració del servidor
Després, configurem el servidor amb la limitació de velocitat:
const express = require('express'); const { ApolloServer, gql } = require('apollo-server-express'); const { RateLimiterMemory } = require('rate-limiter-flexible'); // Definició de l'esquema de GraphQL const typeDefs = gql` type Query { hello: String } `; // Definició dels resolvers const resolvers = { Query: { hello: () => 'Hola, món!', }, }; // Configuració de la limitació de velocitat const rateLimiter = new RateLimiterMemory({ points: 5, // 5 sol·licituds duration: 1, // per segon }); const app = express(); // Middleware de limitació de velocitat app.use((req, res, next) => { rateLimiter.consume(req.ip) .then(() => { next(); }) .catch(() => { res.status(429).send('Massa sol·licituds - si us plau, espera un moment i torna-ho a intentar.'); }); }); // Configuració d'Apollo Server const server = new ApolloServer({ typeDefs, resolvers }); server.applyMiddleware({ app }); // Inici del servidor app.listen({ port: 4000 }, () => console.log(`Servidor de GraphQL en http://localhost:4000${server.graphqlPath}`) );
Explicació del codi
- Definició de l'esquema i resolvers: Es defineix un esquema simple amb una única consulta
hello
que retorna un missatge de benvinguda. - Configuració de la limitació de velocitat: S'utilitza la biblioteca
rate-limiter-flexible
per configurar la limitació de velocitat. En aquest exemple, es permeten 5 sol·licituds per segon per cada adreça IP. - Middleware de limitació de velocitat: Es crea un middleware d'Express que consumeix un token per cada sol·licitud. Si no hi ha tokens disponibles, es retorna un error 429 (Too Many Requests).
- Configuració d'Apollo Server: Es configura Apollo Server amb l'esquema i els resolvers definits anteriorment, i s'aplica el middleware d'Express.
Exercici pràctic
Exercici
Implementa una limitació de velocitat en un servidor GraphQL que permeti un màxim de 10 sol·licituds per minut per cada adreça IP. Utilitza la biblioteca rate-limiter-flexible
i Express.js.
Solució
const express = require('express'); const { ApolloServer, gql } = require('apollo-server-express'); const { RateLimiterMemory } = require('rate-limiter-flexible'); // Definició de l'esquema de GraphQL const typeDefs = gql` type Query { hello: String } `; // Definició dels resolvers const resolvers = { Query: { hello: () => 'Hola, món!', }, }; // Configuració de la limitació de velocitat const rateLimiter = new RateLimiterMemory({ points: 10, // 10 sol·licituds duration: 60, // per minut }); const app = express(); // Middleware de limitació de velocitat app.use((req, res, next) => { rateLimiter.consume(req.ip) .then(() => { next(); }) .catch(() => { res.status(429).send('Massa sol·licituds - si us plau, espera un moment i torna-ho a intentar.'); }); }); // Configuració d'Apollo Server const server = new ApolloServer({ typeDefs, resolvers }); server.applyMiddleware({ app }); // Inici del servidor app.listen({ port: 4000 }, () => console.log(`Servidor de GraphQL en http://localhost:4000${server.graphqlPath}`) );
Conclusió
La limitació de velocitat és una tècnica crucial per mantenir la seguretat i l'estabilitat dels servidors GraphQL. Implementar-la correctament pot ajudar a prevenir abusos i assegurar que els recursos del servidor es distribueixin de manera equitativa entre tots els usuaris. En aquest mòdul, hem explorat diverses estratègies de limitació de velocitat i hem vist com implementar una solució pràctica utilitzant Express.js i Apollo Server.
Curs de GraphQL
Mòdul 1: Introducció a GraphQL
- Què és GraphQL?
- GraphQL vs REST
- Configuració d'un servidor GraphQL
- Conceptes bàsics de l'esquema de GraphQL
Mòdul 2: Conceptes bàsics
Mòdul 3: Disseny avançat d'esquemes
Mòdul 4: Treballant amb dades
- Connexió a una base de dades
- Estratègies de recuperació de dades
- Agrupació i emmagatzematge en memòria cau
- Gestió d'errors
Mòdul 5: Rendiment i seguretat
Mòdul 6: Eines i ecosistema
Mòdul 7: Proves i desplegament
- Proves unitàries de resolvers
- Proves d'integració
- Integració contínua
- Desplegament de servidors GraphQL