العربية

أطلق العنان لقوة اتحاد GraphQL مع تجميع المخططات. تعلم كيفية بناء واجهة برمجة تطبيقات GraphQL موحدة من خدمات متعددة، مما يحسن قابلية التوسع والصيانة.

اتحاد GraphQL: تجميع المخططات - دليل شامل

في المشهد المتطور باستمرار لتطوير التطبيقات الحديثة، أصبحت الحاجة إلى بنيات قابلة للتطوير والصيانة أمرًا بالغ الأهمية. ظهرت الخدمات المصغرة، بفضل نمطيتها الفطرية وقابليتها للنشر المستقل، كحل شائع. ومع ذلك، يمكن أن تؤدي إدارة العديد من الخدمات المصغرة إلى تعقيدات، خاصة عندما يتعلق الأمر بكشف واجهة برمجة تطبيقات موحدة لتطبيقات العميل. وهنا يأتي دور اتحاد GraphQL، وتحديدًا تجميع المخططات.

ما هو اتحاد GraphQL؟

اتحاد GraphQL هو بنية قوية تسمح لك ببناء واجهة برمجة تطبيقات GraphQL واحدة وموحدة من عدة خدمات 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
    }
  }
}

يسترد هذا الاستعلام المنتج بالمعرف "101" ويجلب أيضًا المستخدم المرتبط به من خدمة المستخدم، مما يوضح كيف يسمح لك تجميع المخططات بالاستعلام عن البيانات عبر خدمات متعددة في طلب واحد.

تقنيات تجميع المخططات المتقدمة

إلى جانب المثال الأساسي، إليك بعض التقنيات المتقدمة التي يمكن استخدامها لتعزيز تنفيذ تجميع المخططات الخاص بك:

الاختيار بين تجميع المخططات واتحاد أبولو

بينما يعد تجميع المخططات خيارًا قابلاً للتطبيق لاتحاد GraphQL، فقد أصبح اتحاد أبولو الخيار الأكثر شيوعًا نظرًا لميزاته المتقدمة وتجربة المطور المحسنة. إليك مقارنة بين النهجين:

الميزة تجميع المخططات اتحاد أبولو
تعريف المخطط يستخدم لغة مخطط GraphQL الحالية يستخدم لغة مخططات تعريفية مع توجيهات
تخطيط الاستعلام يتطلب تفويضًا يدويًا للاستعلام تخطيط تلقائي للاستعلام بواسطة بوابة أبولو
امتدادات الأنواع دعم محدود دعم مدمج لامتدادات الأنواع
توجيهات المفاتيح غير مدعوم يستخدم توجيه @key لتحديد الكيانات
التتبع الموزع يتطلب تنفيذًا يدويًا دعم مدمج للتتبع الموزع
الأدوات والنظام البيئي أدوات أقل نضجًا أدوات أكثر نضجًا ومجتمع كبير
التعقيد يمكن أن يكون معقدًا للإدارة في الأنظمة الكبيرة مصمم للأنظمة الكبيرة والمعقدة

متى تختار تجميع المخططات:

متى تختار اتحاد أبولو:

أمثلة واقعية وحالات استخدام

فيما يلي بعض الأمثلة الواقعية لكيفية استخدام اتحاد GraphQL، بما في ذلك تجميع المخططات:

أفضل الممارسات لتجميع المخططات

لضمان تنفيذ ناجح لتجميع المخططات، اتبع أفضل الممارسات التالية:

الخاتمة

يقدم اتحاد GraphQL مع تجميع المخططات نهجًا قويًا لبناء واجهات برمجة تطبيقات موحدة من خدمات متعددة في بنية الخدمات المصغرة. من خلال فهم مفاهيمه الأساسية وفوائده وقيوده وتقنيات تنفيذه، يمكنك الاستفادة من تجميع المخططات لتبسيط الوصول إلى البيانات وتحسين قابلية التوسع وتعزيز قابلية الصيانة. بينما ظهر اتحاد أبولو كحل أكثر تقدمًا، يظل تجميع المخططات خيارًا قابلاً للتطبيق للسيناريوهات الأبسط أو عند دمج خدمات GraphQL الحالية. فكر بعناية في احتياجاتك ومتطلباتك المحددة لاختيار أفضل نهج لمؤسستك.