كيف تبني واجهة برمجة تطبيقات متعددة البروتوكولات باستخدام REST و GraphQL و gRPC؟

Ashley Innocent

Ashley Innocent

13 مارس 2026

كيف تبني واجهة برمجة تطبيقات متعددة البروتوكولات باستخدام REST و GraphQL و gRPC؟

ملخص سريع

ابنِ واجهات برمجة تطبيقات (APIs) متعددة البروتوكولات عن طريق فصل منطق الأعمال عن طبقات البروتوكول. أنشئ طبقة نطاق (domain layer) مشتركة، ثم أضف عليها محولات REST و GraphQL و gRPC. يوضح Modern PetstoreAPI هذه البنية بنماذج بيانات متسقة عبر جميع البروتوكولات الثلاثة.

مقدمة

تعمل واجهة برمجة التطبيقات (API) الخاصة بك على خدمة عملاء الويب وتطبيقات الجوال والخدمات المصغرة الداخلية. يريد عملاء الويب REST للبساطة. ترغب تطبيقات الجوال في GraphQL لتقليل نقل البيانات. تريد الخدمات المصغرة gRPC للأداء. هل تبني ثلاث واجهات برمجة تطبيقات منفصلة؟

لا. أنت تبني واجهة برمجة تطبيقات واحدة بثلاث طبقات بروتوكول. يظل منطق الأعمال كما هو. تتغير محولات البروتوكول فقط. هذه هي بنية واجهة برمجة التطبيقات متعددة البروتوكولات.

يطبق Modern PetstoreAPI بروتوكولات REST و GraphQL و gRPC من نواة مشتركة. يخدم نفس منطق متجر الحيوانات الأليفة جميع البروتوكولات الثلاثة بسلوك متسق.

💡
إذا كنت تبني أو تختبر واجهات برمجة تطبيقات متعددة البروتوكولات، يدعم Apidog اختبار REST و GraphQL و gRPC في أداة واحدة. يمكنك التحقق من أن جميع البروتوكولات تُرجع بيانات متسقة واختبار سير العمل عبر البروتوكولات.
زر

في هذا الدليل، ستتعلم كيفية تصميم واجهات برمجة التطبيقات متعددة البروتوكولات، وتنفيذ طبقات البروتوكول، وضمان الاتساق عبر البروتوكولات باستخدام Modern PetstoreAPI كمرجع.

بنية متعددة البروتوكولات

تفصل واجهات برمجة التطبيقات متعددة البروتوكولات الاهتمامات إلى طبقات.

بنية الطبقات

┌─────────────────────────────────────────┐
│  طبقة البروتوكول (REST/GraphQL/gRPC)     │
├─────────────────────────────────────────┤
│  طبقة التطبيق (حالات الاستخدام)          │
├─────────────────────────────────────────┤
│  طبقة النطاق (منطق الأعمال)              │
├─────────────────────────────────────────┤
│  طبقة البيانات (قاعدة البيانات، الذاكرة المؤقتة) │
└─────────────────────────────────────────┘

طبقة البروتوكول: تتعامل مع HTTP، استعلامات GraphQL، مكالمات gRPC
طبقة التطبيق: تنسق حالات الاستخدام (إنشاء حيوان أليف، تقديم طلب)
طبقة النطاق: قواعد العمل (التحقق، الحسابات)
طبقة البيانات: التخزين الدائم (قاعدة البيانات، الذاكرة المؤقتة)

المبادئ الأساسية

1. نواة مستقلة عن البروتوكول

لا يعرف منطق الأعمال شيئًا عن HTTP أو GraphQL أو gRPC. إنه يعمل مع كائنات النطاق.

2. محولات بروتوكول نحيفة

تُترجم طبقات البروتوكول بين تنسيقات البروتوكول وكائنات النطاق. لا تحتوي على منطق أعمال.

3. نماذج البيانات المشتركة

تستخدم جميع البروتوكولات نفس نماذج النطاق داخليًا، مما يضمن الاتساق.

4. نشر مستقل

يمكن نشر كل بروتوكول بشكل منفصل إذا لزم الأمر.

طبقة النطاق المشتركة

تحتوي طبقة النطاق على منطق أعمال مشترك عبر جميع البروتوكولات.

نماذج النطاق

// Domain model (protocol-agnostic)
class Pet {
  id: string;
  name: string;
  species: Species;
  status: PetStatus;
  price: number;

  constructor(data: PetData) {
    this.validate(data);
    Object.assign(this, data);
  }

  validate(data: PetData): void {
    if (!data.name || data.name.length < 2) {
      throw new ValidationError('Name must be at least 2 characters');
    }
    if (data.price < 0) {
      throw new ValidationError('Price cannot be negative');
    }
  }

  adopt(userId: string): Order {
    if (this.status !== PetStatus.AVAILABLE) {
      throw new BusinessError('Pet is not available for adoption');
    }
    this.status = PetStatus.ADOPTED;
    return new Order({
      petId: this.id,
      userId,
      total: this.price
    });
  }
}

يعمل هذا النموذج مع REST و GraphQL و gRPC. قواعد التحقق والأعمال هي نفسها.

حالات الاستخدام

// Use case (protocol-agnostic)
class AdoptPetUseCase {
  constructor(
    private petRepository: PetRepository,
    private orderRepository: OrderRepository
  ) {}

  async execute(petId: string, userId: string): Promise<Order> {
    const pet = await this.petRepository.findById(petId);
    if (!pet) {
      throw new NotFoundError('Pet not found');
    }

    const order = pet.adopt(userId);
    await this.petRepository.save(pet);
    await this.orderRepository.save(order);

    return order;
  }
}

تعمل حالة الاستخدام هذه بغض النظر عما إذا كانت مستدعاة من REST أو GraphQL أو gRPC.

طبقة بروتوكول REST

تُترجم طبقة REST طلبات HTTP إلى عمليات النطاق.

متحكم REST

// REST adapter
class PetsController {
  constructor(private adoptPetUseCase: AdoptPetUseCase) {}

  async adoptPet(req: Request, res: Response): Promise<void> {
    try {
      const { petId } = req.params;
      const { userId } = req.body;

      const order = await this.adoptPetUseCase.execute(petId, userId);

      res.status(201).json({
        id: order.id,
        petId: order.petId,
        userId: order.userId,
        total: order.total,
        status: order.status
      });
    } catch (error) {
      this.handleError(error, res);
    }
  }

  private handleError(error: Error, res: Response): void {
    if (error instanceof NotFoundError) {
      res.status(404).json({
        type: 'https://petstoreapi.com/errors/not-found',
        title: 'Not Found',
        status: 404,
        detail: error.message
      });
    } else if (error instanceof ValidationError) {
      res.status(400).json({
        type: 'https://petstoreapi.com/errors/validation-error',
        title: 'Validation Error',
        status: 400,
        detail: error.message
      });
    } else {
      res.status(500).json({
        type: 'https://petstoreapi.com/errors/internal-error',
        title: 'Internal Server Error',
        status: 500
      });
    }
  }
}

مسارات REST

app.post('/v1/pets/:petId/adopt', (req, res) =>
  petsController.adoptPet(req, res)
);

نقاط نهاية REST في Modern PetstoreAPI

طبقة بروتوكول GraphQL

تُترجم طبقة GraphQL استعلامات GraphQL إلى عمليات النطاق.

مخطط GraphQL

type Pet {
  id: ID!
  name: String!
  species: Species!
  status: PetStatus!
  price: Float!
}

type Order {
  id: ID!
  petId: ID!
  userId: ID!
  total: Float!
  status: OrderStatus!
}

type Mutation {
  adoptPet(petId: ID!, userId: ID!): Order!
}

محلل GraphQL

// GraphQL adapter
const resolvers = {
  Mutation: {
    adoptPet: async (
      _parent: any,
      args: { petId: string; userId: string },
      context: Context
    ): Promise<Order> => {
      try {
        return await context.adoptPetUseCase.execute(
          args.petId,
          args.userId
        );
      } catch (error) {
        throw new GraphQLError(error.message, {
          extensions: {
            code: error instanceof NotFoundError ? 'NOT_FOUND' :
                  error instanceof ValidationError ? 'BAD_USER_INPUT' :
                  'INTERNAL_SERVER_ERROR'
          }
        });
      }
    }
  }
};

طلب GraphQL

mutation {
  adoptPet(
    petId: "019b4132-70aa-764f-b315-e2803d882a24"
    userId: "user-123"
  ) {
    id
    total
    status
  }
}

مخطط GraphQL في Modern PetstoreAPI

طبقة بروتوكول gRPC

تُترجم طبقة gRPC رسائل Protocol Buffer إلى عمليات النطاق.

تعريف Protocol Buffer

syntax = "proto3";

package petstore.v1;

service PetService {
  rpc AdoptPet(AdoptPetRequest) returns (AdoptPetResponse);
}

message AdoptPetRequest {
  string pet_id = 1;
  string user_id = 2;
}

message AdoptPetResponse {
  string order_id = 1;
  string pet_id = 2;
  string user_id = 3;
  double total = 4;
  string status = 5;
}

تنفيذ خدمة gRPC

// gRPC adapter
class PetServiceImpl implements IPetService {
  constructor(private adoptPetUseCase: AdoptPetUseCase) {}

  async adoptPet(
    call: ServerUnaryCall<AdoptPetRequest, AdoptPetResponse>,
    callback: sendUnaryData<AdoptPetResponse>
  ): Promise<void> {
    try {
      const { petId, userId } = call.request;

      const order = await this.adoptPetUseCase.execute(petId, userId);

      callback(null, {
        orderId: order.id,
        petId: order.petId,
        userId: order.userId,
        total: order.total,
        status: order.status
      });
    } catch (error) {
      callback({
        code: error instanceof NotFoundError ? status.NOT_FOUND :
              error instanceof ValidationError ? status.INVALID_ARGUMENT :
              status.INTERNAL,
        message: error.message
      });
    }
  }
}

خدمة gRPC في Modern PetstoreAPI

كيف يطبق Modern PetstoreAPI البروتوكولات المتعددة

يوضح Modern PetstoreAPI بنية متعددة البروتوكولات بأمثلة حقيقية.

نظرة عامة على البنية

Modern PetstoreAPI
├── طبقة النطاق
│   ├── حيوان أليف (كيان)
│   ├── طلب (كيان)
│   └── حالات الاستخدام
│       ├── إنشاء حيوان أليف
│       ├── تبني حيوان أليف
│       └── تقديم طلب
├── طبقة REST
│   ├── /v1/pets
│   ├── /v1/orders
│   └── مواصفات OpenAPI 3.2
├── طبقة GraphQL
│   ├── محللات الاستعلام
│   ├── محللات التحويل
│   └── مخطط GraphQL
└── طبقة gRPC
    ├── PetService
    ├── OrderService
    └── تعريفات .proto

نماذج البيانات المتسقة

تُرجع جميع البروتوكولات نفس البيانات:

REST:

{
  "id": "019b4132-70aa-764f-b315-e2803d882a24",
  "name": "Fluffy",
  "species": "CAT"
}

GraphQL:

{
  "data": {
    "pet": {
      "id": "019b4132-70aa-764f-b315-e2803d882a24",
      "name": "Fluffy",
      "species": "CAT"
    }
  }
}

gRPC:

{
  pet_id: "019b4132-70aa-764f-b315-e2803d882a24"
  name: "Fluffy"
  species: CAT
}

نفس البيانات، تنسيقات مختلفة.

التحقق المشترك

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

// Domain validation (shared)
if (name.length < 2) {
  throw new ValidationError('Name must be at least 2 characters');
}

تُرجع REST:

{
  "type": "https://petstoreapi.com/errors/validation-error",
  "status": 400,
  "detail": "Name must be at least 2 characters"
}

تُرجع GraphQL:

{
  "errors": [{
    "message": "Name must be at least 2 characters",
    "extensions": {"code": "BAD_USER_INPUT"}
  }]
}

تُرجع gRPC:

code: INVALID_ARGUMENT
message: "Name must be at least 2 characters"

نفس التحقق، تنسيقات أخطاء خاصة بالبروتوكول.

اختبار واجهات برمجة التطبيقات متعددة البروتوكولات باستخدام Apidog

يدعم Apidog اختبار جميع البروتوكولات الثلاثة.

اختبار نقطة نهاية REST

POST https://petstoreapi.com/v1/pets/019b4132-70aa-764f-b315-e2803d882a24/adopt
Content-Type: application/json

{
  "userId": "user-123"
}

اختبار تحويل GraphQL

mutation {
  adoptPet(
    petId: "019b4132-70aa-764f-b315-e2803d882a24"
    userId: "user-123"
  ) {
    id
    total
  }
}

اختبار خدمة gRPC

grpc.petstore.v1.PetService/AdoptPet
{
  "pet_id": "019b4132-70aa-764f-b315-e2803d882a24",
  "user_id": "user-123"
}

التحقق من الاتساق

اختبر أن جميع البروتوكولات الثلاثة تُرجع نفس البيانات:

  1. استدعاء نقطة نهاية REST
  2. استدعاء تحويل GraphQL
  3. استدعاء خدمة gRPC
  4. مقارنة النتائج

يمكن لـ Apidog أتمتة هذا الاختبار عبر البروتوكولات.

استراتيجيات النشر

الاستراتيجية 1: خدمة واحدة

نشر جميع البروتوكولات في خدمة واحدة:

┌─────────────────────────┐
│  خدمة PetstoreAPI      │
│  ├── REST (منفذ 8080)   │
│  ├── GraphQL (منفذ 8081)│
│  └── gRPC (منفذ 50051)  │
└─────────────────────────┘

الإيجابيات: نشر بسيط، موارد مشتركة
السلبيات: تتوسع جميع البروتوكولات معًا

الاستراتيجية 2: خدمات منفصلة

نشر كل بروتوكول بشكل منفصل:

┌──────────────┐  ┌──────────────┐  ┌──────────────┐
│ خدمة REST     │  │ خدمة GraphQL  │  │ خدمة gRPC    │
│ (منفذ 8080)  │  │ (منفذ 8081)  │  │ (منفذ 50051) │
└──────────────┘  └──────────────┘  └──────────────┘
       │                 │                  │
       └─────────────────┴──────────────────┘
                         │
                  ┌──────────────┐
                  │ نواة مشتركة   │
                  │   مكتبة      │
                  └──────────────┘

الإيجابيات: توسع مستقل، عزل البروتوكول
السلبيات: نشر أكثر تعقيدًا

الاستراتيجية 3: بوابة API

استخدم بوابة API لتوجيهها إلى الواجهات الخلفية الخاصة بالبروتوكول:

                ┌─────────────┐
                │ بوابة API    │
                └─────────────┘
                       │
        ┌──────────────┼──────────────┐
        │              │              │
┌───────▼──────┐ ┌────▼─────┐ ┌──────▼──────┐
│ واجهة REST خلفية │ │ GraphQL  │ │ واجهة gRPC خلفية│
└──────────────┘ └──────────┘ └─────────────┘

الإيجابيات: توجيه مركزي، تحديد المعدل، المصادقة
السلبيات: زمن استجابة إضافي، تعقيد البوابة

يستخدم Modern PetstoreAPI الاستراتيجية 1 للبساطة.

الخلاصة

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

يوضح Modern PetstoreAPI هذه البنية بنماذج بيانات متسقة، وتحقق مشترك، ومحولات خاصة بالبروتوكول. سواء استخدم العملاء REST للبساطة، أو GraphQL للمرونة، أو gRPC للأداء، فإنهم يصلون إلى نفس متجر الحيوانات الأليفة بنفس قواعد العمل.

اختبر واجهات برمجة التطبيقات متعددة البروتوكولات باستخدام Apidog لضمان الاتساق عبر البروتوكولات. استكشف Modern PetstoreAPI لترى بنية البروتوكولات المتعددة عمليًا.

زر

الأسئلة الشائعة

هل أحتاج إلى دعم جميع البروتوكولات الثلاثة؟

لا. ابدأ بـ REST لواجهات برمجة التطبيقات العامة. أضف GraphQL إذا كان العملاء بحاجة إلى جلب بيانات مرن. أضف gRPC للخدمات المصغرة الداخلية. أضف البروتوكولات فقط عندما يكون لديك حالة استخدام واضحة.

كيف أحافظ على اتساق البروتوكولات؟

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

هل يمكنني إصدار البروتوكولات بشكل مستقل؟

نعم. يمكن أن يكون REST في الإصدار 2 بينما GraphQL في الإصدار 1. لكن هذا يخلق تعقيدًا. حاول إبقاء البروتوكولات متزامنة قدر الإمكان.

كيف أتعامل مع المصادقة عبر البروتوكولات؟

استخدم نفس المصادقة في جميع البروتوكولات. تستخدم REST رموز Bearer في الرؤوس. تستخدم GraphQL نفس الرموز. يستخدم gRPC البيانات الوصفية. تتحقق طبقة النطاق من الرموز بنفس الطريقة.

ماذا عن WebSocket و SSE؟

WebSocket و SSE هما بروتوكولا نقل، وليسا بروتوكولات API. يمكنك إضافتهما جنبًا إلى جنب مع REST/GraphQL/gRPC للتحديثات في الوقت الفعلي. يتضمن Modern PetstoreAPI كلاهما.

كيف أوثق واجهات برمجة التطبيقات متعددة البروتوكولات؟

استخدم OpenAPI لـ REST، ومخطط GraphQL لـ GraphQL، وملفات .proto لـ gRPC. يوفر Modern PetstoreAPI جميع الثلاثة على https://docs.petstoreapi.com/

هل يمكنني استخدام قواعد بيانات مختلفة لبروتوكولات مختلفة؟

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

كيف أختبر واجهات برمجة التطبيقات متعددة البروتوكولات؟

استخدم Apidog لاختبار جميع البروتوكولات في أداة واحدة. أنشئ مجموعات اختبار تتحقق من الاتساق عبر البروتوكولات. اختبر أن REST و GraphQL و gRPC تُرجع نفس البيانات لنفس العمليات.

ممارسة تصميم API في Apidog

اكتشف طريقة أسهل لبناء واستخدام واجهات برمجة التطبيقات