Українська

Розкрийте потенціал Федерації GraphQL за допомогою зшивання схем. Дізнайтеся, як створити єдиний GraphQL API з кількох сервісів, покращуючи масштабованість та підтримку.

Федерація GraphQL: Зшивання схем - вичерпний посібник

У світі розробки сучасних додатків, що постійно розвивається, потреба в масштабованих архітектурах, які легко підтримувати, стала першочерговою. Мікросервіси, з їхньою притаманною модульністю та незалежним розгортанням, стали популярним рішенням. Однак управління численними мікросервісами може створювати складнощі, особливо коли йдеться про надання єдиного API для клієнтських додатків. Саме тут на допомогу приходить Федерація GraphQL, а зокрема — зшивання схем (Schema Stitching).

Що таке Федерація GraphQL?

Федерація GraphQL — це потужна архітектура, яка дозволяє створювати єдиний, уніфікований GraphQL API з кількох базових сервісів GraphQL (які часто представляють мікросервіси). Вона дає змогу розробникам запитувати дані з різних сервісів так, ніби це єдиний граф, що спрощує роботу клієнта та зменшує потребу в складній логіці оркестрації на стороні клієнта.

Існує два основних підходи до Федерації GraphQL:

Ця стаття зосереджена на зшиванні схем, досліджуючи його концепції, переваги, обмеження та практичну реалізацію.

Розуміння зшивання схем

Зшивання схем — це процес об'єднання кількох схем GraphQL в одну, цілісну схему. Ця уніфікована схема діє як фасад, приховуючи складність базових сервісів від клієнта. Коли клієнт робить запит до зшитої схеми, шлюз розумно маршрутизує запит до відповідного сервісу(-ів), отримує дані та поєднує результати перед тим, як повернути їх клієнту.

Уявіть собі це так: у вас є кілька ресторанів (сервісів), кожен з яких спеціалізується на різних кухнях. Зшивання схем — це як універсальне меню, що поєднує всі страви з кожного ресторану. Коли клієнт (замовник) робить замовлення з універсального меню, замовлення розумно направляється на кухні відповідних ресторанів, їжа готується, а потім об'єднується в одну доставку для клієнта.

Ключові концепції зшивання схем

Переваги зшивання схем

Зшивання схем пропонує кілька значних переваг для організацій, що використовують мікросервісну архітектуру:

Обмеження зшивання схем

Хоча зшивання схем пропонує численні переваги, важливо знати про його обмеження:

Практична реалізація зшивання схем

Розгляньмо спрощений приклад того, як реалізувати зшивання схем за допомогою Node.js та бібліотеки graphql-tools (популярний вибір для зшивання схем). Цей приклад включає два мікросервіси: сервіс користувачів та сервіс продуктів.

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!  # Зовнішній ключ до сервісу користувачів
  }

  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.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('Сервер шлюзу запущено на 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('Сервіс користувачів запущено на 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('Сервіс продуктів запущено на http://localhost:4002/graphql'));

4. Запитайте зшиту схему

Тепер ви можете надсилати запити до зшитої схеми через шлюз (який працює на порту 4000). Ви можете виконати такий запит:


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

Цей запит отримує продукт з ID "101", а також отримує пов'язаного з ним користувача з сервісу користувачів, демонструючи, як зшивання схем дозволяє запитувати дані з кількох сервісів в одному запиті.

Просунуті техніки зшивання схем

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

Вибір між зшиванням схем та Apollo Federation

Хоча зшивання схем є життєздатним варіантом для Федерації GraphQL, Apollo Federation стала популярнішим вибором завдяки своїм розширеним функціям та покращеному досвіду розробників. Ось порівняння двох підходів:

Функція Зшивання схем Apollo Federation
Визначення схеми Використовує існуючу мову схем GraphQL Використовує декларативну мову схем з директивами
Планування запитів Вимагає ручного делегування запитів Автоматичне планування запитів шлюзом Apollo
Розширення типів Обмежена підтримка Вбудована підтримка розширень типів
Ключові директиви Не підтримується Використовує директиву @key для ідентифікації сутностей
Розподілене трасування Вимагає ручної реалізації Вбудована підтримка розподіленого трасування
Інструменти та екосистема Менш зрілі інструменти Більш зрілі інструменти та велика спільнота
Складність Може бути складним в управлінні у великих системах Розроблено для великих і складних систем

Коли обирати зшивання схем:

Коли обирати Apollo Federation:

Реальні приклади та випадки використання

Ось кілька реальних прикладів того, як можна використовувати Федерацію GraphQL, включаючи зшивання схем:

Найкращі практики для зшивання схем

Щоб забезпечити успішну реалізацію зшивання схем, дотримуйтесь цих найкращих практик:

Висновок

Федерація GraphQL зі зшиванням схем пропонує потужний підхід до створення уніфікованих API з кількох сервісів у мікросервісній архітектурі. Розуміючи її основні концепції, переваги, обмеження та техніки реалізації, ви можете використовувати зшивання схем для спрощення доступу до даних, покращення масштабованості та підвищення зручності підтримки. Хоча Apollo Federation стала більш просунутим рішенням, зшивання схем залишається життєздатним варіантом для простіших сценаріїв або при інтеграції існуючих сервісів GraphQL. Ретельно зважте ваші конкретні потреби та вимоги, щоб вибрати найкращий підхід для вашої організації.