Български

Отключете силата на GraphQL федерацията със слепване на схеми. Научете как да изградите унифициран GraphQL API от множество услуги, подобрявайки мащабируемостта и поддръжката.

GraphQL федерация: Слепване на схеми (Schema Stitching) - изчерпателно ръководство

В постоянно развиващия се свят на модерната разработка на приложения, нуждата от мащабируеми и лесни за поддръжка архитектури стана от първостепенно значение. Микроуслугите, с тяхната присъща модулност и независима възможност за внедряване, се превърнаха в популярно решение. Управлението на множество микроуслуги обаче може да доведе до усложнения, особено когато става въпрос за предоставяне на унифициран API към клиентските приложения. Точно тук се намесва GraphQL федерацията и по-конкретно слепването на схеми (Schema Stitching).

Какво е GraphQL федерация?

GraphQL федерацията е мощна архитектура, която ви позволява да изградите единен, унифициран GraphQL API от множество базови GraphQL услуги (често представляващи микроуслуги). Тя дава възможност на разработчиците да изпращат заявки за данни от различни услуги, сякаш те са част от единен граф, което опростява клиентското изживяване и намалява нуждата от сложна логика за оркестрация от страна на клиента.

Съществуват два основни подхода към GraphQL федерацията:

Тази статия се фокусира върху слепването на схеми (Schema Stitching), като изследва неговите концепции, предимства, ограничения и практическо приложение.

Разбиране на слепването на схеми (Schema Stitching)

Слепването на схеми е процес на обединяване на множество GraphQL схеми в една единна, съгласувана схема. Тази унифицирана схема действа като фасада, скривайки сложността на базовите услуги от клиента. Когато клиент направи заявка към слепената схема, шлюзът интелигентно насочва заявката към съответната базова услуга(и), извлича данните и комбинира резултатите, преди да ги върне на клиента.

Представете си го така: имате няколко ресторанта (услуги), всеки от които е специализиран в различни кухни. Слепването на схеми е като универсално меню, което комбинира всички ястия от всеки ресторант. Когато клиент (client) поръча от универсалното меню, поръчката се насочва интелигентно към кухните на съответните ресторанти, храната се приготвя и след това се комбинира в една доставка за клиента.

Ключови концепции в слепването на схеми

Предимства на слепването на схеми

Слепването на схеми предлага няколко убедителни предимства за организации, които възприемат архитектура на микроуслуги:

Ограничения на слепването на схеми

Въпреки че слепването на схеми предлага многобройни предимства, е важно да сте наясно с неговите ограничения:

Практическо внедряване на слепване на схеми

Нека разгледаме опростен пример за това как да внедрим слепване на схеми с помощта на Node.js и библиотеката graphql-tools (популярен избор за слепване на схеми). Този пример включва две микроуслуги: услуга за потребители (User Service) и услуга за продукти (Product Service).

1. Дефиниране на отдалечените схеми

Първо, дефинирайте GraphQL схемите за всяка от отдалечените услуги.

Услуга за потребители (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,
};

Услуга за продукти (product-service.js):


const { buildSchema } = require('graphql');

const productSchema = buildSchema(`
  type Product {
    id: ID!
    name: String
    price: Float
    userId: ID!  # Foreign key to User Service
  }

  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. Създаване на услугата-шлюз (Gateway Service)

Сега създайте услугата-шлюз, която ще слепи двете схеми заедно.

Услуга-шлюз (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. Стартиране на услугите

Ще трябва да стартирате услугата за потребители и услугата за продукти на различни портове. Например:

Услуга за потребители (порт 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'));

Услуга за продукти (порт 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. Изпращане на заявка към слепената схема

Сега можете да изпратите заявка към слепената схема през шлюза (работещ на порт 4000). Можете да изпълните заявка като тази:


query {
  product(id: "101") {
    id
    name
    price
    user {
      id
      name
      email
    }
  }
}

Тази заявка извлича продукта с ID "101" и също така извлича свързания потребител от услугата за потребители, демонстрирайки как слепването на схеми ви позволява да изисквате данни от множество услуги в една единствена заявка.

Разширени техники за слепване на схеми

Освен основния пример, ето някои разширени техники, които могат да се използват за подобряване на вашата имплементация на слепване на схеми:

Избор между слепване на схеми и Apollo Federation

Въпреки че слепването на схеми е жизнеспособен вариант за GraphQL федерация, Apollo Federation се превърна в по-популярния избор поради своите разширени функции и подобрено изживяване за разработчиците. Ето сравнение на двата подхода:

Функция Слепване на схеми (Schema Stitching) Apollo Federation
Дефиниция на схема Използва съществуващия език за GraphQL схеми Използва декларативен език за схеми с директиви
Планиране на заявки Изисква ръчно делегиране на заявки Автоматично планиране на заявки от Apollo Gateway
Разширения на типове Ограничена поддръжка Вградена поддръжка за разширения на типове
Ключови директиви Не се поддържа Използва директива @key за идентифициране на същности
Разпределено проследяване Изисква ръчно внедряване Вградена поддръжка за разпределено проследяване
Инструменти и екосистема По-малко зрели инструменти По-зрели инструменти и голяма общност
Сложност Може да бъде сложно за управление в големи системи Проектиран за големи и сложни системи

Кога да изберем слепване на схеми:

Кога да изберем Apollo Federation:

Примери от реалния свят и случаи на употреба

Ето някои примери от реалния свят за това как може да се използва GraphQL федерацията, включително слепването на схеми:

Най-добри практики за слепване на схеми

За да осигурите успешно внедряване на слепване на схеми, следвайте тези най-добри практики:

Заключение

GraphQL федерацията със слепване на схеми предлага мощен подход за изграждане на унифицирани API-та от множество услуги в архитектура на микроуслуги. Като разбирате основните му концепции, предимства, ограничения и техники за внедряване, можете да използвате слепването на схеми, за да опростите достъпа до данни, да подобрите мащабируемостта и да улесните поддръжката. Въпреки че Apollo Federation се очерта като по-напреднало решение, слепването на схеми остава жизнеспособен вариант за по-прости сценарии или при интегриране на съществуващи GraphQL услуги. Внимателно обмислете вашите специфични нужди и изисквания, за да изберете най-добрия подход за вашата организация.