Български

Научете мащабируеми модели за дизайн на GraphQL схеми за изграждане на стабилни и лесни за поддръжка API-та, които обслужват разнообразна глобална аудитория. Овладейте schema stitching, federation и modularization.

Дизайн на GraphQL схема: Мащабируеми модели за глобални API-та

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

Значението на мащабируемия дизайн на схемата

Добре проектираната GraphQL схема е основата на успешното API. Тя диктува как клиентите могат да взаимодействат с вашите данни и услуги. Лошият дизайн на схемата може да доведе до редица проблеми, включително:

При глобалните приложения тези проблеми се засилват. Различните региони може да имат различни изисквания за данни, регулаторни ограничения и очаквания за производителност. Мащабируемият дизайн на схемата ви позволява да се справите ефективно с тези предизвикателства.

Ключови принципи на мащабируемия дизайн на схемата

Преди да се потопим в конкретни модели, нека очертаем някои ключови принципи, които трябва да ръководят дизайна на вашата схема:

Мащабируеми модели за дизайн на схеми

Ето няколко мащабируеми модела за дизайн на схеми, които можете да използвате за изграждане на стабилни GraphQL API-та:

1. Schema Stitching

Schema stitching ви позволява да комбинирате няколко GraphQL API-та в една единна, унифицирана схема. Това е особено полезно, когато имате различни екипи или услуги, отговорни за различни части от вашите данни. Това е като да имате няколко мини-API-та и да ги свържете в едно цяло чрез "gateway" API.

Как работи:

  1. Всеки екип или услуга предоставя собствено GraphQL API със собствена схема.
  2. Централна gateway услуга използва инструменти за schema stitching (като Apollo Federation или GraphQL Mesh) за сливане на тези схеми в една единна, унифицирана схема.
  3. Клиентите взаимодействат с gateway услугата, която пренасочва заявките към съответните базови API-та.

Пример:

Представете си платформа за електронна търговия с отделни API-та за продукти, потребители и поръчки. Всяко API има своя собствена схема:

  
    # API за продукти
    type Product {
      id: ID!
      name: String!
      price: Float!
    }

    type Query {
      product(id: ID!): Product
    }

    # API за потребители
    type User {
      id: ID!
      name: String!
      email: String!
    }

    type Query {
      user(id: ID!): User
    }

    # API за поръчки
    type Order {
      id: ID!
      userId: ID!
      productId: ID!
      quantity: Int!
    }

    type Query {
      order(id: ID!): Order
    }
  

Gateway услугата може да свърже тези схеми, за да създаде унифицирана схема:

  
    type Product {
      id: ID!
      name: String!
      price: Float!
    }

    type User {
      id: ID!
      name: String!
      email: String!
    }

    type Order {
      id: ID!
      user: User! @relation(field: "userId")
      product: Product! @relation(field: "productId")
      quantity: Int!
    }

    type Query {
      product(id: ID!): Product
      user(id: ID!): User
      order(id: ID!): Order
    }
  

Забележете как типът Order сега включва препратки към User и Product, въпреки че тези типове са дефинирани в отделни API-та. Това се постига чрез директиви за свързване на схеми (като @relation в този пример).

Предимства:

Съображения:

2. Schema Federation

Schema federation е еволюция на schema stitching, създадена да отговори на някои от нейните ограничения. Тя предоставя по-декларативен и стандартизиран подход за композиране на GraphQL схеми.

Как работи:

  1. Всяка услуга предоставя GraphQL API и анотира своята схема с federation директиви (напр. @key, @extends, @external).
  2. Централна gateway услуга (използваща Apollo Federation) използва тези директиви, за да изгради supergraph – представяне на цялата федеративна схема.
  3. Gateway услугата използва supergraph-а, за да пренасочва заявките към съответните базови услуги и да разрешава зависимости.

Пример:

Използвайки същия пример с електронна търговия, федеративните схеми може да изглеждат така:

  
    # API за продукти
    type Product @key(fields: "id") {
      id: ID!
      name: String!
      price: Float!
    }

    type Query {
      product(id: ID!): Product
    }

    # API за потребители
    type User @key(fields: "id") {
      id: ID!
      name: String!
      email: String!
    }

    type Query {
      user(id: ID!): User
    }

    # API за поръчки
    type Order {
      id: ID!
      userId: ID!
      productId: ID!
      quantity: Int!
      user: User! @requires(fields: "userId")
      product: Product! @requires(fields: "productId")
    }

    extend type Query {
      order(id: ID!): Order
    }
  

Забележете използването на federation директиви:

Предимства:

Съображения:

3. Модулен дизайн на схемата

Модулният дизайн на схемата включва разделянето на голяма, монолитна схема на по-малки, по-лесно управляеми модули. Това улеснява разбирането, промяната и повторната употреба на отделни части от вашето API, дори без да се прибягва до федеративни схеми.

Как работи:

  1. Идентифицирайте логическите граници във вашата схема (напр. потребители, продукти, поръчки).
  2. Създайте отделни модули за всяка граница, дефинирайки типовете, заявките и мутациите, свързани с тази граница.
  3. Използвайте механизми за импортиране/експортиране (в зависимост от вашата GraphQL сървърна имплементация), за да комбинирате модулите в една единна, унифицирана схема.

Пример (използвайки JavaScript/Node.js):

Създайте отделни файлове за всеки модул:

  
    // users.graphql
    type User {
      id: ID!
      name: String!
      email: String!
    }

    type Query {
      user(id: ID!): User
    }

    // products.graphql
    type Product {
      id: ID!
      name: String!
      price: Float!
    }

    type Query {
      product(id: ID!): Product
    }
  

След това ги комбинирайте в основния си файл на схемата:

  
    // schema.js
    const { makeExecutableSchema } = require('graphql-tools');
    const { typeDefs: userTypeDefs, resolvers: userResolvers } = require('./users');
    const { typeDefs: productTypeDefs, resolvers: productResolvers } = require('./products');

    const typeDefs = [
      userTypeDefs,
      productTypeDefs,
      ""
    ];

    const resolvers = {
      Query: {
        ...userResolvers.Query,
        ...productResolvers.Query,
      }
    };

    const schema = makeExecutableSchema({
      typeDefs,
      resolvers,
    });

    module.exports = schema;
  

Предимства:

Съображения:

4. Интерфейсни и обединителни типове (Interface and Union Types)

Интерфейсните и обединителните типове ви позволяват да дефинирате абстрактни типове, които могат да бъдат имплементирани от множество конкретни типове. Това е полезно за представяне на полиморфни данни – данни, които могат да приемат различни форми в зависимост от контекста.

Как работи:

Пример:

  
    interface Node {
      id: ID!
    }

    type User implements Node {
      id: ID!
      name: String!
      email: String!
    }

    type Product implements Node {
      id: ID!
      name: String!
      price: Float!
    }

    union SearchResult = User | Product

    type Query {
      node(id: ID!): Node
      search(query: String!): [SearchResult!]!
    }
  

В този пример и User, и Product имплементират интерфейса Node, който дефинира общо поле id. Обединителният тип SearchResult представлява резултат от търсене, който може да бъде или User, или Product. Клиентите могат да заявят полето `search` и след това да използват полето `__typename`, за да определят какъв тип резултат са получили.

Предимства:

Съображения:

5. Модел на свързване (Connection Pattern)

Моделът на свързване е стандартен начин за имплементиране на пагинация в GraphQL API-та. Той предоставя последователен и ефективен начин за извличане на големи списъци с данни на части.

Как работи:

Пример:

  
    type User {
      id: ID!
      name: String!
      email: String!
    }

    type UserEdge {
      node: User!
      cursor: String!
    }

    type UserConnection {
      edges: [UserEdge!]!
      pageInfo: PageInfo!
    }

    type PageInfo {
      hasNextPage: Boolean!
      hasPreviousPage: Boolean!
      startCursor: String
      endCursor: String
    }

    type Query {
      users(first: Int, after: String, last: Int, before: String): UserConnection!
    }
  

Предимства:

Съображения:

Глобални съображения

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

Например, разгледайте поле за описание на продукт:


type Product {
 id: ID!
 name: String!
 description(language: String = "en"): String!
}

Това позволява на клиентите да заявят описанието на конкретен език. Ако не е посочен език, по подразбиране се използва английски (`en`).

Заключение

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

Като възприемете тези модели, можете да отключите пълния потенциал на GraphQL и да изградите API-та, които да захранват вашите приложения за години напред.