Exploitez la puissance de la Fédération GraphQL avec le Schema Stitching. Apprenez à créer une API GraphQL unifiée à partir de plusieurs services, améliorant la scalabilité et la maintenabilité.
Fédération GraphQL : Schema Stitching - Un Guide Complet
Dans le paysage en constante évolution du développement d'applications modernes, le besoin d'architectures scalables et maintenables est devenu primordial. Les microservices, avec leur modularité inhérente et leur déployabilité indépendante, sont devenus une solution populaire. Cependant, la gestion de nombreux microservices peut introduire des complexités, notamment lorsqu'il s'agit d'exposer une API unifiée aux applications clientes. C'est là que la Fédération GraphQL, et plus spécifiquement le Schema Stitching, entre en jeu.
Qu'est-ce que la Fédération GraphQL ?
La Fédération GraphQL est une architecture puissante qui vous permet de construire une API GraphQL unique et unifiée à partir de plusieurs services GraphQL sous-jacents (représentant souvent des microservices). Elle permet aux développeurs d'interroger des données à travers différents services comme s'il s'agissait d'un seul graphe, simplifiant l'expérience client et réduisant le besoin d'une logique d'orchestration complexe côté client.
Il existe deux approches principales de la Fédération GraphQL :
- Schema Stitching : Cela consiste à combiner plusieurs schémas GraphQL en un seul schéma unifié au niveau de la passerelle. C'est une approche plus ancienne qui s'appuie sur des bibliothèques pour gérer la combinaison des schémas et la délégation des requêtes.
- Fédération Apollo : C'est une approche plus récente et robuste qui utilise un langage de schéma déclaratif et un planificateur de requêtes dédié pour gérer le processus de fédération. Elle offre des fonctionnalités avancées comme les extensions de type, les directives de clé et le traçage distribué.
Cet article se concentre sur le Schema Stitching, explorant ses concepts, ses avantages, ses limites et sa mise en œuvre pratique.
Comprendre le Schema Stitching
Le Schema Stitching est le processus de fusion de plusieurs schémas GraphQL en un seul schéma cohérent. Ce schéma unifié agit comme une façade, cachant la complexité des services sous-jacents au client. Lorsqu'un client fait une requête au schéma fusionné, la passerelle achemine intelligemment la requête vers le(s) service(s) sous-jacent(s) approprié(s), récupère les données et combine les résultats avant de les renvoyer au client.
Imaginez la chose suivante : vous avez plusieurs restaurants (services) spécialisés chacun dans des cuisines différentes. Le Schema Stitching est comme un menu universel qui combine tous les plats de chaque restaurant. Lorsqu'un client passe une commande à partir du menu universel, la commande est intelligemment acheminée vers les cuisines des restaurants appropriés, la nourriture est préparée, puis combinée en une seule livraison pour le client.
Concepts Clés du Schema Stitching
- Schémas Distants : Ce sont les schémas GraphQL individuels de chaque service sous-jacent. Chaque service expose son propre schéma, qui définit les données et les opérations qu'il fournit.
- Passerelle : La passerelle est le composant central chargé de fusionner les schémas distants et d'exposer le schéma unifié au client. Elle reçoit les requêtes des clients, les achemine vers les services appropriés et combine les résultats.
- Fusion de Schémas : C'est le processus de combinaison des schémas distants en un seul schéma. Cela implique souvent de renommer les types et les champs pour éviter les conflits et de définir des relations entre les types de différents schémas.
- Délégation de Requêtes : Lorsqu'un client fait une requête au schéma fusionné, la passerelle doit déléguer la requête au(x) service(s) sous-jacent(s) approprié(s) pour récupérer les données. Cela implique de traduire la requête du client en une requête compréhensible par le service distant.
- Agrégation des Résultats : Après que la passerelle a récupéré les données des services sous-jacents, elle doit combiner les résultats en une seule réponse qui peut être renvoyée au client. Cela implique souvent de transformer les données pour qu'elles correspondent à la structure du schéma fusionné.
Avantages du Schema Stitching
Le Schema Stitching offre plusieurs avantages convaincants pour les organisations qui adoptent une architecture de microservices :
- API Unifiée : Fournit une API unique et cohérente pour les clients, simplifiant l'accès aux données et réduisant le besoin pour les clients d'interagir directement avec plusieurs services. Cela se traduit par une expérience de développement plus propre et plus intuitive.
- Complexité Côté Client Réduite : Les clients n'ont besoin d'interagir qu'avec le schéma unifié, ce qui les protège des complexités de l'architecture de microservices sous-jacente. Cela simplifie le développement côté client et réduit la quantité de code requise sur le client.
- Scalabilité Accrue : Permet de faire évoluer les services individuels indépendamment en fonction de leurs besoins spécifiques. Cela améliore la scalabilité et la résilience globales du système. Par exemple, un service utilisateur subissant une charge élevée peut être mis à l'échelle sans affecter d'autres services comme le catalogue de produits.
- Maintenabilité Améliorée : Favorise la modularité et la séparation des préoccupations, ce qui facilite la maintenance et l'évolution des services individuels. Les modifications apportées à un service sont moins susceptibles d'avoir un impact sur d'autres services.
- Adoption Graduelle : Peut être mis en œuvre de manière incrémentielle, vous permettant de migrer progressivement d'une architecture monolithique à une architecture de microservices. Vous pouvez commencer par fusionner des API existantes, puis décomposer progressivement le monolithe en services plus petits.
Limites du Schema Stitching
Bien que le Schema Stitching offre de nombreux avantages, il est important d'être conscient de ses limites :
- Complexité : La mise en œuvre et la gestion du schema stitching peuvent être complexes, en particulier dans les systèmes vastes et complexes. Une planification et une conception minutieuses sont essentielles.
- Surcharge de Performance : La passerelle introduit une certaine surcharge de performance en raison de la couche d'indirection supplémentaire et de la nécessité de déléguer les requêtes et d'agréger les résultats. Une optimisation minutieuse est cruciale pour minimiser cette surcharge.
- Conflits de Schémas : Des conflits peuvent survenir lors de la fusion de schémas de différents services, surtout s'ils utilisent les mêmes noms de type ou de champ. Cela nécessite une conception de schéma soignée et potentiellement le renommage de types et de champs.
- Fonctionnalités Avancées Limitées : Comparé à la Fédération Apollo, le Schema Stitching manque de certaines fonctionnalités avancées comme les extensions de type et les directives de clé, ce qui peut rendre plus difficile la gestion des relations entre les types de différents schémas.
- Maturité de l'Outillage : L'outillage et l'écosystème autour du Schema Stitching ne sont pas aussi matures que ceux de la Fédération Apollo. Cela peut rendre le débogage et la résolution des problèmes plus difficiles.
Mise en Œuvre Pratique du Schema Stitching
Voyons un exemple simplifié de mise en œuvre du Schema Stitching en utilisant Node.js et la bibliothèque graphql-tools
(un choix populaire pour le schema stitching). Cet exemple implique deux microservices : un Service Utilisateur et un Service Produit.
1. Définir les Schémas Distants
D'abord, définissez les schémas GraphQL pour chacun des services distants.
Service Utilisateur (user-service.js
):
const { buildSchema } = require('graphql');
const userSchema = buildSchema(`
type User {
id: ID!
name: String
email: String
}
type Query {
user(id: ID!): User
}
`);
const users = [
{ id: '1', name: 'Alice Smith', email: 'alice@example.com' },
{ id: '2', name: 'Bob Johnson', email: 'bob@example.com' },
];
const userRoot = {
user: (args) => users.find(user => user.id === args.id),
};
module.exports = {
schema: userSchema,
rootValue: userRoot,
};
Service Produit (product-service.js
):
const { buildSchema } = require('graphql');
const productSchema = buildSchema(`
type Product {
id: ID!
name: String
price: Float
userId: ID! # Clé étrangère vers le Service Utilisateur
}
type Query {
product(id: ID!): Product
}
`);
const products = [
{ id: '101', name: 'Laptop', price: 1200, userId: '1' },
{ id: '102', name: 'Smartphone', price: 800, userId: '2' },
];
const productRoot = {
product: (args) => products.find(product => product.id === args.id),
};
module.exports = {
schema: productSchema,
rootValue: productRoot,
};
2. Créer le Service de Passerelle
Maintenant, créez le service de passerelle qui fusionnera les deux schémas.
Service de Passerelle (gateway.js
):
const { stitchSchemas } = require('@graphql-tools/stitch');
const { makeRemoteExecutableSchema } = require('@graphql-tools/wrap');
const { graphqlHTTP } = require('express-graphql');
const express = require('express');
const { introspectSchema } = require('@graphql-tools/wrap');
const { printSchema } = require('graphql');
const fetch = require('node-fetch');
async function createRemoteSchema(uri) {
const fetcher = async (params) => {
const response = await fetch(uri, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(params),
});
return response.json();
};
const schema = await introspectSchema(fetcher);
return makeRemoteExecutableSchema({
schema,
fetcher,
});
}
async function main() {
const userSchema = await createRemoteSchema('http://localhost:4001/graphql');
const productSchema = await createRemoteSchema('http://localhost:4002/graphql');
const stitchedSchema = stitchSchemas({
subschemas: [
{ schema: userSchema },
{ schema: productSchema },
],
typeDefs: `
extend type Product {
user: User
}
`,
resolvers: {
Product: {
user: {
selectionSet: `{ userId }`,
resolve(product, args, context, info) {
return info.mergeInfo.delegateToSchema({
schema: userSchema,
operation: 'query',
fieldName: 'user',
args: {
id: product.userId,
},
context,
info,
});
},
},
},
},
});
const app = express();
app.use('/graphql', graphqlHTTP({
schema: stitchedSchema,
graphiql: true,
}));
app.listen(4000, () => console.log('Serveur de passerelle en cours d'exécution sur http://localhost:4000/graphql'));
}
main().catch(console.error);
3. Exécuter les Services
Vous devrez exécuter le Service Utilisateur et le Service Produit sur des ports différents. Par exemple :
Service Utilisateur (port 4001):
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { schema, rootValue } = require('./user-service');
const app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: rootValue,
graphiql: true,
}));
app.listen(4001, () => console.log('Service utilisateur en cours d'exécution sur http://localhost:4001/graphql'));
Service Produit (port 4002):
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { schema, rootValue } = require('./product-service');
const app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: rootValue,
graphiql: true,
}));
app.listen(4002, () => console.log('Service produit en cours d'exécution sur http://localhost:4002/graphql'));
4. Interroger le Schéma Fusionné
Vous pouvez maintenant interroger le schéma fusionné via la passerelle (exécutée sur le port 4000). Vous pouvez exécuter une requête comme celle-ci :
query {
product(id: "101") {
id
name
price
user {
id
name
email
}
}
}
Cette requête récupère le produit avec l'ID "101" et récupère également l'utilisateur associé du Service Utilisateur, démontrant comment le Schema Stitching vous permet d'interroger des données sur plusieurs services en une seule requête.
Techniques Avancées de Schema Stitching
Au-delà de l'exemple de base, voici quelques techniques avancées qui peuvent être utilisées pour améliorer votre implémentation de Schema Stitching :
- Délégation de Schéma : Cela vous permet de déléguer des parties d'une requête à différents services en fonction des données demandées. Par exemple, vous pouvez déléguer la résolution d'un type `User` au Service Utilisateur et la résolution d'un type `Product` au Service Produit.
- Transformation de Schéma : Cela consiste à modifier le schéma d'un service distant avant qu'il ne soit fusionné dans le schéma unifié. Cela peut être utile pour renommer des types et des champs, ajouter de nouveaux champs ou supprimer des champs existants.
- Résolveurs Personnalisés : Vous pouvez définir des résolveurs personnalisés dans la passerelle pour gérer des transformations de données complexes ou pour récupérer des données de plusieurs services et les combiner en un seul résultat.
- Partage de Contexte : Il est souvent nécessaire de partager des informations de contexte entre la passerelle et les services distants, comme des jetons d'authentification ou des ID utilisateur. Ceci peut être réalisé en passant les informations de contexte dans le cadre du processus de délégation de requête.
- Gestion des Erreurs : Mettez en œuvre une gestion robuste des erreurs pour traiter gracieusement les erreurs qui se produisent dans les services distants. Cela peut impliquer la journalisation des erreurs, le renvoi de messages d'erreur conviviaux ou la relance des requêtes échouées.
Choisir entre le Schema Stitching et la Fédération Apollo
Bien que le Schema Stitching soit une option viable pour la Fédération GraphQL, la Fédération Apollo est devenue le choix le plus populaire en raison de ses fonctionnalités avancées et de son expérience de développement améliorée. Voici une comparaison des deux approches :
Fonctionnalité | Schema Stitching | Fédération Apollo |
---|---|---|
Définition du Schéma | Utilise le langage de schéma GraphQL existant | Utilise un langage de schéma déclaratif avec des directives |
Planification des Requêtes | Nécessite une délégation de requête manuelle | Planification automatique des requêtes par la passerelle Apollo |
Extensions de Type | Support limité | Support intégré pour les extensions de type |
Directives de Clé | Non supporté | Utilise la directive @key pour identifier les entités |
Traçage Distribué | Nécessite une implémentation manuelle | Support intégré pour le traçage distribué |
Outillage et Écosystème | Outillage moins mature | Outillage plus mature et une grande communauté |
Complexité | Peut être complexe à gérer dans de grands systèmes | Conçu pour les systèmes vastes et complexes |
Quand choisir le Schema Stitching :
- Vous avez des services GraphQL existants et souhaitez les combiner rapidement.
- Vous avez besoin d'une solution de fédération simple et ne nécessitez pas de fonctionnalités avancées.
- Vous avez des ressources limitées et voulez éviter la surcharge liée à la mise en place de la Fédération Apollo.
Quand choisir la Fédération Apollo :
- Vous construisez un système vaste et complexe avec plusieurs équipes et services.
- Vous avez besoin de fonctionnalités avancées comme les extensions de type, les directives de clé et le traçage distribué.
- Vous voulez une solution de fédération plus robuste et scalable.
- Vous préférez une approche de la fédération plus déclarative et automatisée.
Exemples Concrets et Cas d'Usage
Voici quelques exemples concrets de la manière dont la Fédération GraphQL, y compris le Schema Stitching, peut être utilisée :
- Plateforme E-commerce : Une plateforme e-commerce pourrait utiliser la Fédération GraphQL pour combiner des données de plusieurs services, tels qu'un service de catalogue de produits, un service utilisateur, un service de commandes et un service de paiement. Cela permet aux clients de récupérer facilement toutes les informations dont ils ont besoin pour afficher les détails des produits, les profils utilisateur, l'historique des commandes et les informations de paiement.
- Plateforme de Médias Sociaux : Une plateforme de médias sociaux pourrait utiliser la Fédération GraphQL pour combiner des données de services qui gèrent les profils utilisateur, les publications, les commentaires et les "j'aime". Cela permet aux clients de récupérer efficacement toutes les informations nécessaires pour afficher le profil d'un utilisateur, ses publications, ainsi que les commentaires et les "j'aime" associés à ces publications.
- Application de Services Financiers : Une application de services financiers pourrait utiliser la Fédération GraphQL pour combiner des données de services qui gèrent les comptes, les transactions et les investissements. Cela permet aux clients de récupérer facilement toutes les informations dont ils ont besoin pour afficher les soldes des comptes, l'historique des transactions et les portefeuilles d'investissement.
- Système de Gestion de Contenu (CMS) : Un CMS peut tirer parti de la Fédération GraphQL pour intégrer des données de diverses sources comme des articles, des images, des vidéos et du contenu généré par les utilisateurs. Cela permet une API unifiée pour récupérer tout le contenu lié à un sujet ou un auteur spécifique.
- Application de Santé : Intégrer les données des patients de différents systèmes comme les dossiers de santé électroniques (DSE), les résultats de laboratoire et la planification de rendez-vous. Cela offre aux médecins un point d'accès unique à des informations complètes sur les patients.
Meilleures Pratiques pour le Schema Stitching
Pour garantir une implémentation réussie du Schema Stitching, suivez ces meilleures pratiques :
- Planifiez votre schéma avec soin : Avant de commencer à fusionner des schémas, planifiez soigneusement la structure du schéma unifié. Cela inclut la définition des relations entre les types de différents schémas, le renommage des types et des champs pour éviter les conflits, et la prise en compte des modèles d'accès aux données globaux.
- Utilisez des conventions de nommage cohérentes : Adoptez des conventions de nommage cohérentes pour les types, les champs et les opérations dans tous les services. Cela aidera à éviter les conflits et facilitera la compréhension du schéma unifié.
- Documentez votre schéma : Documentez minutieusement le schéma unifié, y compris les descriptions des types, des champs et des opérations. Cela facilitera la compréhension et l'utilisation du schéma par les développeurs.
- Surveillez les performances : Surveillez les performances de la passerelle et des services distants pour identifier et résoudre les goulots d'étranglement de performance. Utilisez des outils comme le traçage distribué pour suivre les requêtes à travers plusieurs services.
- Mettez en œuvre la sécurité : Mettez en œuvre des mesures de sécurité appropriées pour protéger la passerelle et les services distants contre les accès non autorisés. Cela peut impliquer l'utilisation de mécanismes d'authentification et d'autorisation, ainsi que la validation des entrées et l'encodage des sorties.
- Versionnez votre schéma : Au fur et à mesure que vous faites évoluer vos schémas, versionnez-les de manière appropriée pour garantir que les clients puissent continuer à utiliser les anciennes versions du schéma sans interruption. Cela aidera à éviter les changements cassants et à assurer la rétrocompatibilité.
- Automatisez le déploiement : Automatisez le déploiement de la passerelle et des services distants pour garantir que les modifications peuvent être déployées rapidement et de manière fiable. Cela aidera à réduire le risque d'erreurs et à améliorer l'agilité globale du système.
Conclusion
La Fédération GraphQL avec le Schema Stitching offre une approche puissante pour construire des API unifiées à partir de plusieurs services dans une architecture de microservices. En comprenant ses concepts fondamentaux, ses avantages, ses limites et ses techniques de mise en œuvre, vous pouvez tirer parti du Schema Stitching pour simplifier l'accès aux données, améliorer la scalabilité et renforcer la maintenabilité. Bien que la Fédération Apollo soit apparue comme une solution plus avancée, le Schema Stitching reste une option viable pour des scénarios plus simples ou lors de l'intégration de services GraphQL existants. Examinez attentivement vos besoins et exigences spécifiques pour choisir la meilleure approche pour votre organisation.