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

  1. 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.

  1. 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.

  1. 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.

  1. 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:

npm install express apollo-server-express graphql rate-limiter-flexible

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

  1. Definició de l'esquema i resolvers: Es defineix un esquema simple amb una única consulta hello que retorna un missatge de benvinguda.
  2. 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.
  3. 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).
  4. 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.

© Copyright 2024. Tots els drets reservats