Frigör kraften i GraphQL Federation med Schema Stitching. Lär dig bygga ett enhetligt GraphQL API från flera tjänster, vilket förbättrar skalbarhet och underhåll.
GraphQL Federation: Schema Stitching - En Omfattande Guide
I det ständigt föränderliga landskapet för modern applikationsutveckling har behovet av skalbara och underhållbara arkitekturer blivit avgörande. Mikrotjänster, med sin inneboende modularitet och oberoende driftsättningsbarhet, har framträtt som en populär lösning. Att hantera ett stort antal mikrotjänster kan dock introducera komplexitet, särskilt när det gäller att exponera ett enhetligt API för klientapplikationer. Det är här GraphQL Federation, och specifikt Schema Stitching, kommer in i bilden.
Vad är GraphQL Federation?
GraphQL Federation är en kraftfull arkitektur som låter dig bygga ett enda, enhetligt GraphQL API från flera underliggande GraphQL-tjänster (som ofta representerar mikrotjänster). Det gör det möjligt för utvecklare att hämta data över olika tjänster som om det vore en enda graf, vilket förenklar klientupplevelsen och minskar behovet av komplex orkestreringslogik på klientsidan.
Det finns två huvudsakliga tillvägagångssätt för GraphQL Federation:
- Schema Stitching: Detta innebär att man kombinerar flera GraphQL-scheman till ett enda, enhetligt schema i gateway-lagret. Det är ett tidigare tillvägagångssätt och förlitar sig på bibliotek för att hantera schemakombinationen och delegering av förfrågningar.
- Apollo Federation: Detta är ett nyare och mer robust tillvägagångssätt som använder ett deklarativt schemaspråk och en dedikerad frågeplanerare för att hantera federationsprocessen. Det erbjuder avancerade funktioner som typ-utökningar, nyckeldirektiv och distribuerad spårning.
Denna artikel fokuserar på Schema Stitching och utforskar dess koncept, fördelar, begränsningar och praktiska implementering.
Förståelse för Schema Stitching
Schema Stitching är processen att slå samman flera GraphQL-scheman till ett enda, sammanhängande schema. Detta enhetliga schema fungerar som en fasad och döljer komplexiteten hos de underliggande tjänsterna från klienten. När en klient gör en förfrågan till det sammansatta schemat, dirigerar gatewayen intelligent förfrågan till den eller de lämpliga underliggande tjänsterna, hämtar datan och kombinerar resultaten innan de returneras till klienten.
Tänk på det så här: Du har flera restauranger (tjänster) som var och en specialiserar sig på olika kök. Schema Stitching är som en universell meny som kombinerar alla rätter från varje restaurang. När en kund (klient) beställer från den universella menyn, dirigeras beställningen intelligent till rätt restaurangkök, maten förbereds och kombineras sedan till en enda leverans för kunden.
Nyckelkoncept inom Schema Stitching
- Fjärrscheman (Remote Schemas): Dessa är de individuella GraphQL-schemana för varje underliggande tjänst. Varje tjänst exponerar sitt eget schema, som definierar den data och de operationer den tillhandahåller.
- Gateway: Gatewayen är den centrala komponenten som ansvarar för att sy ihop fjärrschemana och exponera det enhetliga schemat för klienten. Den tar emot klientförfrågningar, dirigerar dem till lämpliga tjänster och kombinerar resultaten.
- Schemakoppling (Schema Merging): Detta är processen att kombinera fjärrscheman till ett enda schema. Detta innebär ofta att man döper om typer och fält för att undvika konflikter och definierar relationer mellan typer över olika scheman.
- Delegering av förfrågningar (Query Delegation): När en klient gör en förfrågan till det sammansatta schemat måste gatewayen delegera förfrågan till lämplig underliggande tjänst(er) för att hämta datan. Detta innebär att klientens förfrågan översätts till en förfrågan som den fjärranslutna tjänsten kan förstå.
- Resultataggregering (Result Aggregation): Efter att gatewayen har hämtat data från de underliggande tjänsterna måste den kombinera resultaten till ett enda svar som kan returneras till klienten. Detta innebär ofta att datan omvandlas för att matcha strukturen i det sammansatta schemat.
Fördelar med Schema Stitching
Schema Stitching erbjuder flera övertygande fördelar för organisationer som antar en mikrotjänstarkitektur:
- Enhetligt API: Ger ett enda, konsekvent API för klienter, vilket förenklar dataåtkomst och minskar behovet för klienter att interagera med flera tjänster direkt. Detta resulterar i en renare och mer intuitiv utvecklarupplevelse.
- Minskad klientkomplexitet: Klienter behöver bara interagera med det enhetliga schemat, vilket skyddar dem från komplexiteten i den underliggande mikrotjänstarkitekturen. Detta förenklar utvecklingen på klientsidan och minskar mängden kod som krävs på klienten.
- Ökad skalbarhet: Låter dig skala enskilda tjänster oberoende av varandra baserat på deras specifika behov. Detta förbättrar systemets övergripande skalbarhet och motståndskraft. Till exempel kan en användartjänst som upplever hög belastning skalas utan att påverka andra tjänster som produktkatalogen.
- Förbättrad underhållbarhet: Främjar modularitet och separation av ansvarsområden, vilket gör det lättare att underhålla och utveckla enskilda tjänster. Ändringar i en tjänst är mindre benägna att påverka andra tjänster.
- Gradvis adoption: Kan implementeras stegvis, vilket gör att du gradvis kan migrera från en monolitisk arkitektur till en mikrotjänstarkitektur. Du kan börja med att sy ihop befintliga API:er och sedan gradvis bryta ner monoliten i mindre tjänster.
Begränsningar med Schema Stitching
Även om Schema Stitching erbjuder många fördelar är det viktigt att vara medveten om dess begränsningar:
- Komplexitet: Att implementera och hantera schema stitching kan vara komplicerat, särskilt i stora och komplexa system. Noggrann planering och design är avgörande.
- Prestanda-overhead: Gatewayen introducerar en viss prestanda-overhead på grund av det extra lagret av indirektion och behovet av att delegera förfrågningar och aggregera resultat. Noggrann optimering är avgörande för att minimera denna overhead.
- Schemakonflikter: Konflikter kan uppstå när man slår samman scheman från olika tjänster, särskilt om de använder samma typ- eller fältnamn. Detta kräver noggrann schemadesign och eventuellt omdöpning av typer och fält.
- Begränsade avancerade funktioner: Jämfört med Apollo Federation saknar Schema Stitching vissa avancerade funktioner som typ-utökningar och nyckeldirektiv, vilket kan göra det mer utmanande att hantera relationer mellan typer över olika scheman.
- Verktygsmognad: Verktygen och ekosystemet kring Schema Stitching är inte lika mogna som de kring Apollo Federation. Detta kan göra det mer utmanande att felsöka och lösa problem.
Praktisk implementering av Schema Stitching
Låt oss gå igenom ett förenklat exempel på hur man implementerar Schema Stitching med Node.js och biblioteket graphql-tools
(ett populärt val för schema stitching). Detta exempel involverar två mikrotjänster: en Användartjänst och en Produkttjänst.
1. Definiera fjärrschemana
Först definierar du GraphQL-schemana för var och en av fjärrtjänsterna.
Användartjänst (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,
};
Produkttjänst (product-service.js
):
const { buildSchema } = require('graphql');
const productSchema = buildSchema(`
type Product {
id: ID!
name: String
price: Float
userId: ID! # Främmande nyckel till Användartjänsten
}
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. Skapa Gateway-tjänsten
Skapa nu gateway-tjänsten som kommer att sy ihop de två schemana.
Gateway-tjänst (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('Gateway server running on http://localhost:4000/graphql'));
}
main().catch(console.error);
3. Kör tjänsterna
Du måste köra Användartjänsten och Produkttjänsten på olika portar. Till exempel:
Användartjänst (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('User service running on http://localhost:4001/graphql'));
Produkttjänst (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('Product service running on http://localhost:4002/graphql'));
4. Fråga det sammansatta schemat
Nu kan du fråga det sammansatta schemat via gatewayen (som körs på port 4000). Du kan köra en fråga som denna:
query {
product(id: "101") {
id
name
price
user {
id
name
email
}
}
}
Denna fråga hämtar produkten med ID "101" och hämtar även den associerade användaren från Användartjänsten, vilket demonstrerar hur Schema Stitching låter dig hämta data över flera tjänster i en enda förfrågan.
Avancerade tekniker för Schema Stitching
Utöver det grundläggande exemplet finns här några avancerade tekniker som kan användas för att förbättra din implementering av Schema Stitching:
- Schemadelegering: Detta gör att du kan delegera delar av en fråga till olika tjänster baserat på den data som efterfrågas. Till exempel kan du delegera upplösningen av en `User`-typ till Användartjänsten och upplösningen av en `Product`-typ till Produkttjänsten.
- Schematransformering: Detta innebär att man modifierar schemat för en fjärrtjänst innan det sys ihop i det enhetliga schemat. Detta kan vara användbart för att döpa om typer och fält, lägga till nya fält eller ta bort befintliga fält.
- Anpassade resolvers: Du kan definiera anpassade resolvers i gatewayen för att hantera komplexa datatransformationer eller för att hämta data från flera tjänster och kombinera den till ett enda resultat.
- Kontextdelning: Det är ofta nödvändigt att dela kontextinformation mellan gatewayen och fjärrtjänsterna, såsom autentiseringstokens eller användar-ID. Detta kan uppnås genom att skicka kontextinformation som en del av frågedelegeringsprocessen.
- Felhantering: Implementera robust felhantering för att elegant hantera fel som uppstår i fjärrtjänsterna. Detta kan innebära att logga fel, returnera användarvänliga felmeddelanden eller försöka misslyckade förfrågningar igen.
Välja mellan Schema Stitching och Apollo Federation
Även om Schema Stitching är ett gångbart alternativ för GraphQL Federation, har Apollo Federation blivit det mer populära valet på grund av sina avancerade funktioner och förbättrade utvecklarupplevelse. Här är en jämförelse av de två tillvägagångssätten:
Funktion | Schema Stitching | Apollo Federation |
---|---|---|
Schemadefinition | Använder befintligt GraphQL-schemaspråk | Använder ett deklarativt schemaspråk med direktiv |
Frågeplanering | Kräver manuell delegering av förfrågningar | Automatisk frågeplanering av Apollo Gateway |
Typ-utökningar | Begränsat stöd | Inbyggt stöd för typ-utökningar |
Nyckeldirektiv | Stöds inte | Använder @key -direktivet för att identifiera entiteter |
Distribuerad spårning | Kräver manuell implementering | Inbyggt stöd för distribuerad spårning |
Verktyg och ekosystem | Mindre mogna verktyg | Mognare verktyg och en stor community |
Komplexitet | Kan vara komplext att hantera i stora system | Designat för stora och komplexa system |
När du ska välja Schema Stitching:
- Du har befintliga GraphQL-tjänster och vill snabbt kombinera dem.
- Du behöver en enkel federationslösning och kräver inte avancerade funktioner.
- Du har begränsade resurser och vill undvika overheaden med att sätta upp Apollo Federation.
När du ska välja Apollo Federation:
- Du bygger ett stort och komplext system med flera team och tjänster.
- Du behöver avancerade funktioner som typ-utökningar, nyckeldirektiv och distribuerad spårning.
- Du vill ha en mer robust och skalbar federationslösning.
- Du föredrar ett mer deklarativt och automatiserat tillvägagångssätt för federation.
Verkliga exempel och användningsfall
Här är några verkliga exempel på hur GraphQL Federation, inklusive Schema Stitching, kan användas:
- E-handelsplattform: En e-handelsplattform kan använda GraphQL Federation för att kombinera data från flera tjänster, såsom en produktkatalogtjänst, en användartjänst, en ordertjänst och en betalningstjänst. Detta gör det möjligt för klienter att enkelt hämta all information de behöver för att visa produktdetaljer, användarprofiler, orderhistorik och betalningsinformation.
- Sociala medier-plattform: En sociala medier-plattform skulle kunna använda GraphQL Federation för att kombinera data från tjänster som hanterar användarprofiler, inlägg, kommentarer och gillamarkeringar. Detta gör det möjligt för klienter att effektivt hämta all information som krävs för att visa en användares profil, deras inlägg och de kommentarer och gillamarkeringar som är associerade med dessa inlägg.
- Applikation för finansiella tjänster: En applikation för finansiella tjänster kan använda GraphQL Federation för att kombinera data från tjänster som hanterar konton, transaktioner och investeringar. Detta gör det möjligt för klienter att enkelt hämta all information de behöver för att visa kontosaldon, transaktionshistorik och investeringsportföljer.
- Innehållshanteringssystem (CMS): Ett CMS kan utnyttja GraphQL Federation för att integrera data från olika källor som artiklar, bilder, videor och användargenererat innehåll. Detta möjliggör ett enhetligt API för att hämta allt innehåll relaterat till ett specifikt ämne eller en författare.
- Sjukvårdsapplikation: Integrera patientdata från olika system som elektroniska patientjournaler (EHR), labbresultat och tidsbokning. Detta erbjuder läkare en enda åtkomstpunkt till omfattande patientinformation.
Bästa praxis för Schema Stitching
För att säkerställa en framgångsrik implementering av Schema Stitching, följ dessa bästa praxis:
- Planera ditt schema noggrant: Innan du börjar sy ihop scheman, planera noggrant strukturen för det enhetliga schemat. Detta inkluderar att definiera relationerna mellan typer över olika scheman, döpa om typer och fält för att undvika konflikter och överväga de övergripande dataåtkomstmönstren.
- Använd konsekventa namnkonventioner: Anta konsekventa namnkonventioner för typer, fält och operationer över alla tjänster. Detta hjälper till att undvika konflikter och gör det lättare att förstå det enhetliga schemat.
- Dokumentera ditt schema: Dokumentera det enhetliga schemat noggrant, inklusive beskrivningar av typer, fält och operationer. Detta gör det lättare för utvecklare att förstå och använda schemat.
- Övervaka prestanda: Övervaka prestandan för gatewayen och fjärrtjänsterna för att identifiera och åtgärda eventuella prestandaflaskhalsar. Använd verktyg som distribuerad spårning för att följa förfrågningar över flera tjänster.
- Implementera säkerhet: Implementera lämpliga säkerhetsåtgärder för att skydda gatewayen och fjärrtjänsterna från obehörig åtkomst. Detta kan innebära att använda autentiserings- och auktoriseringsmekanismer, samt indatavalidering och utdatakodning.
- Versionera ditt schema: När du utvecklar dina scheman, versionera dem på lämpligt sätt för att säkerställa att klienter kan fortsätta använda äldre versioner av schemat utan att det går sönder. Detta hjälper till att undvika brytande ändringar och säkerställa bakåtkompatibilitet.
- Automatisera driftsättning: Automatisera driftsättningen av gatewayen och fjärrtjänsterna för att säkerställa att ändringar kan driftsättas snabbt och tillförlitligt. Detta hjälper till att minska risken för fel och förbättra systemets övergripande smidighet.
Slutsats
GraphQL Federation med Schema Stitching erbjuder ett kraftfullt tillvägagångssätt för att bygga enhetliga API:er från flera tjänster i en mikrotjänstarkitektur. Genom att förstå dess kärnkoncept, fördelar, begränsningar och implementeringstekniker kan du utnyttja Schema Stitching för att förenkla dataåtkomst, förbättra skalbarhet och öka underhållbarheten. Även om Apollo Federation har framstått som en mer avancerad lösning, förblir Schema Stitching ett gångbart alternativ för enklare scenarier eller vid integrering av befintliga GraphQL-tjänster. Överväg noggrant dina specifika behov och krav för att välja det bästa tillvägagångssättet för din organisation.