تخطَّ إلى المحتوى

🏗️ شرح المايكروسيرفيس (Microservices)

التواصل عبر قوائم الرسائل (Message Queues)

الدرس 5 من 25· ⏱ 2 دقائق قراءة

لماذا قوائم الرسائل؟

التواصل غير المتزامن يفصل الخدمات عن بعضها ويحسن المرونة والأداء.

RabbitMQ مثال

import { OrderRepositoryProtocol, OrderNotFoundError } from './lib/base_repository';

// Producer — يستخدم Repository لحفظ الطلب قبل إرسال الرسالة
// لا يستدعي db.orders.create() مباشرة
class OrderEventProducer {
  constructor(
    private readonly orderRepo: OrderRepositoryProtocol,
    private readonly amqpChannel: any,
  ) {}

  async sendOrderCreated(order: Order): Promise<void> {
    const existing = await this.orderRepo.findById(order.id);
    if (existing) throw new OrderNotFoundError(order.id);

    await this.orderRepo.save(order);
    this.amqpChannel.sendToQueue(
      'orders.created',
      Buffer.from(JSON.stringify(order)),
      { persistent: true },
    );
  }
}
import { SagaExecutionError, OrderRepositoryProtocol, generateIdempotencyKey } from './lib/base_repository';

// Consumer — يستخدم Repository للتحقق من Idempotency قبل المعالجة
class OrderEventConsumer {
  constructor(
    private readonly orderRepo: OrderRepositoryProtocol,
    private readonly amqpChannel: any,
  ) {}

  async consumeOrderCreated(): Promise<void> {
    const queue = 'orders.created';
    await this.amqpChannel.assertQueue(queue, { durable: true });

    this.amqpChannel.consume(queue, async (msg: any) => {
      const order = JSON.parse(msg.content.toString());
      const idemKey = generateIdempotencyKey();

      try {
        const existing = await this.orderRepo.findById(order.id);
        if (existing) {
          // Idempotency: طلب مكرر — نتجاوز بسلام
          this.amqpChannel.ack(msg);
          return;
        }
        await this.orderRepo.save(order);
        this.amqpChannel.ack(msg);
      } catch (err) {
        throw new SagaExecutionError(
          order.id, 'consumeOrderCreated', (err as Error).message,
        );
      }
    });
  }
}

أنماط التوجيه

Direct Exchange

channel.publish('orders_exchange', 'order.created', Buffer.from(data));

Topic Exchange

channel.publish('events', 'orders.created.eur', Buffer.from(data));

Fanout Exchange

channel.publish('notifications', '', Buffer.from(data));
// يرسل لكل الـ queues المرتبطة

Kafka مثال

const { Kafka } = require('kafkajs');

const kafka = new Kafka({
  clientId: 'order-service',
  brokers: ['kafka:9092'],
});

const producer = kafka.producer();
await producer.connect();

await producer.send({
  topic: 'order-events',
  messages: [
    { key: 'order-123', value: JSON.stringify(order) },
  ],
});

مقارنة

الأداةالأداءالترتيبالاحتفاظ بالرسائل
RabbitMQجيدمضمونحتى يتم الإقرار
Kafkaعالٍ جداًضمن الـ Partitionقابل للتكوين
SQSجيدBest Effortحتى يتم الحذف

⚠️ اختر الأداة المناسبة: RabbitMQ للـ Task Queues، Kafka لـ Event Streaming

🎯 التالي: 05-api-gateway

شرح التواصل عبر قوائم الرسائل (Message Queues) — المايكروسيرفيس (Microservices) بالعربي
التواصل عبر قوائم الرسائل (Message Queues)المايكروسيرفيس (Microservices) بالعربي · The Code Fix

هل كان هذا الدرس مفيدًا؟