En aquest tema, explorarem dues tècniques essencials per millorar el rendiment de les aplicacions GraphQL: l'agrupació (batching) i l'emmagatzematge en memòria cau (caching). Aquestes tècniques ajuden a reduir la latència i a optimitzar l'ús dels recursos del servidor.
Agrupació (Batching)
Què és l'agrupació?
L'agrupació és una tècnica que permet combinar múltiples sol·licituds en una sola operació per reduir el nombre de crides a la base de dades o a altres serveis externs. Això és especialment útil en GraphQL, on una sola consulta pot desencadenar múltiples resolucions de dades.
Exemple pràctic d'agrupació
Suposem que tenim una consulta que necessita obtenir informació de diversos usuaris:
Sense agrupació, cada resolució de posts
per a cada usuari podria resultar en una crida separada a la base de dades. Amb l'agrupació, podem combinar aquestes crides en una sola operació.
Implementació amb DataLoader
Una eina popular per implementar l'agrupació en GraphQL és DataLoader. A continuació, es mostra com utilitzar DataLoader per agrupar crides a la base de dades:
const DataLoader = require('dataloader'); // Funció per carregar múltiples usuaris per ID const batchUsers = async (userIds) => { const users = await User.find({ _id: { $in: userIds } }); return userIds.map(id => users.find(user => user.id === id)); }; // Crear una instància de DataLoader const userLoader = new DataLoader(batchUsers); // Resolver per a la consulta d'usuaris const resolvers = { Query: { users: () => userLoader.loadMany([1, 2, 3]), // Exemple d'IDs d'usuaris }, User: { posts: (user) => Post.find({ userId: user.id }), }, };
Beneficis de l'agrupació
- Reducció de crides a la base de dades: Menys crides significa menys latència i menys càrrega al servidor.
- Millora del rendiment: Les operacions agrupades són més eficients i poden processar-se més ràpidament.
Emmagatzematge en memòria cau (Caching)
Què és l'emmagatzematge en memòria cau?
L'emmagatzematge en memòria cau és una tècnica per guardar dades recentment sol·licitades en una ubicació temporal (memòria cau) per accelerar futures sol·licituds de les mateixes dades. Això redueix la necessitat de recalcular o tornar a obtenir dades des de la font original.
Tipus de memòria cau
- Memòria cau del client: Emmagatzematge de dades al costat del client per evitar sol·licituds repetides al servidor.
- Memòria cau del servidor: Emmagatzematge de dades al costat del servidor per evitar recalculs o crides repetides a la base de dades.
Implementació de la memòria cau
Memòria cau del client amb Apollo Client
Apollo Client ofereix una solució integrada per a la memòria cau del client:
import { ApolloClient, InMemoryCache } from '@apollo/client'; const client = new ApolloClient({ uri: 'http://localhost:4000/graphql', cache: new InMemoryCache(), });
Memòria cau del servidor amb Redis
Redis és una eina popular per a la memòria cau del servidor. A continuació, es mostra com utilitzar Redis per emmagatzemar dades en memòria cau:
const redis = require('redis'); const client = redis.createClient(); // Funció per obtenir dades amb memòria cau const getUser = async (id) => { const cacheKey = `user:${id}`; const cachedUser = await client.get(cacheKey); if (cachedUser) { return JSON.parse(cachedUser); } const user = await User.findById(id); await client.set(cacheKey, JSON.stringify(user), 'EX', 3600); // Emmagatzema durant 1 hora return user; }; // Resolver per a la consulta d'usuari const resolvers = { Query: { user: (_, { id }) => getUser(id), }, };
Beneficis de la memòria cau
- Reducció de la latència: Les dades emmagatzemades en memòria cau es poden recuperar més ràpidament que les dades obtingudes des de la font original.
- Reducció de la càrrega del servidor: Menys crides a la base de dades o a altres serveis externs.
Exercici pràctic
Exercici
Implementa una solució d'agrupació i memòria cau per a una consulta que obtingui informació de productes i les seves categories.
Pas 1: Crear un DataLoader per agrupar les crides a la base de dades de categories.
const batchCategories = async (categoryIds) => { const categories = await Category.find({ _id: { $in: categoryIds } }); return categoryIds.map(id => categories.find(category => category.id === id)); }; const categoryLoader = new DataLoader(batchCategories);
Pas 2: Implementar la memòria cau del servidor amb Redis per a les dades de productes.
const getProduct = async (id) => { const cacheKey = `product:${id}`; const cachedProduct = await client.get(cacheKey); if (cachedProduct) { return JSON.parse(cachedProduct); } const product = await Product.findById(id); await client.set(cacheKey, JSON.stringify(product), 'EX', 3600); // Emmagatzema durant 1 hora return product; };
Pas 3: Integrar les solucions d'agrupació i memòria cau en els resolvers.
const resolvers = { Query: { product: (_, { id }) => getProduct(id), products: () => Product.find(), }, Product: { category: (product) => categoryLoader.load(product.categoryId), }, };
Solució
const DataLoader = require('dataloader'); const redis = require('redis'); const client = redis.createClient(); // Funció per agrupar categories const batchCategories = async (categoryIds) => { const categories = await Category.find({ _id: { $in: categoryIds } }); return categoryIds.map(id => categories.find(category => category.id === id)); }; const categoryLoader = new DataLoader(batchCategories); // Funció per obtenir productes amb memòria cau const getProduct = async (id) => { const cacheKey = `product:${id}`; const cachedProduct = await client.get(cacheKey); if (cachedProduct) { return JSON.parse(cachedProduct); } const product = await Product.findById(id); await client.set(cacheKey, JSON.stringify(product), 'EX', 3600); // Emmagatzema durant 1 hora return product; }; // Resolvers const resolvers = { Query: { product: (_, { id }) => getProduct(id), products: () => Product.find(), }, Product: { category: (product) => categoryLoader.load(product.categoryId), }, };
Conclusió
L'agrupació i l'emmagatzematge en memòria cau són tècniques poderoses per millorar el rendiment de les aplicacions GraphQL. L'agrupació redueix el nombre de crides a la base de dades, mentre que l'emmagatzematge en memòria cau accelera la recuperació de dades. Implementar aquestes tècniques pot significar una gran diferència en l'eficiència i la velocitat de la teva aplicació.
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