كيف تستخدم RabbitMQ لبناء Notification System يشبه WhatsApp

كيف تستخدم RabbitMQ لبناء Notification System يشبه WhatsApp

في تطبيقات الدردشة مثل WhatsApp أو Telegram، نظام الإشعارات والرسائل (Messaging / Notification System) يعتبر قلب التطبيق. هذا النظام يجب أن يكون سريع، موثوق، وقابل للتوسع ليخدم ملايين المستخدمين في نفس الوقت. واحدة من أقوى الأدوات لبناء هذا النوع من الأنظمة هي RabbitMQ.

في هذا المقال سنشرح rabbitmq messaging system design لبناء نظام إشعارات ورسائل يشبه WhatsApp، بداية من الفكرة المعمارية (System Design) وحتى تصميم الـ Queues وExchange Types وكيفية التعامل مع الـ Online/Offline Users.

لماذا RabbitMQ لبناء نظام شبيه بـ WhatsApp؟

تطبيقات مثل WhatsApp تحتاج إلى:

  • إرسال واستقبال الرسائل في الوقت الحقيقي (Real-Time)
  • التعامل مع ملايين الرسائل في الثانية
  • ضمان عدم ضياع الرسائل حتى لو المستخدم Offline
  • إشعارات Push Notifications للجوال
  • Delivery Reports: رسالة وصلت / تم قراءتها

هنا يأتي دور RabbitMQ كـ Message Broker يربط بين الخدمات المختلفة، ويتحكم في تدفق الرسائل، ويساعد في فصل (Decoupling) بين:

  • خدمة إدارة الجلسات (Sessions & Presence)
  • خدمة إرسال الرسائل (Messaging Service)
  • خدمة الإشعارات (Notification Service)
  • خدمات التخزين (Message Store / Database)
  • خدمات Push Notifications (Firebase APNs, etc.)

لو أردت تعمّق أكثر في تصميم الأنظمة بشكل عام، يمكنك مراجعة مقال: مقدمة في System Design للمطورين: كيف تفكر الشركات الكبيرة عند بناء الأنظمة.

المفهوم العام لـ rabbitmq messaging system design لتطبيق دردشة

قبل الدخول في التفاصيل التقنية، لنضع صورة عامة للنظام:

  1. المستخدم A يرسل رسالة للمستخدم B عبر واجهة الـ API أو WebSocket.
  2. خدمة الـ Chat Backend تستقبل الرسالة وتدفعها (Publish) إلى RabbitMQ.
  3. RabbitMQ يوزع الرسالة على الـ Queues المناسبة اعتماداً على نوع Exchange و Routing Keys.
  4. Workers / Consumers مختلفة تتعامل مع الرسالة:
    • Consumer لتخزين الرسالة في قاعدة البيانات
    • Consumer لإرسال إشعار فوري (WebSocket) لو B أونلاين
    • Consumer لإرسال Push Notification لو B أوفلاين
  5. المستخدم B يستقبل الرسالة وإشعارات الوصول والقراءة يتم التعامل معها بنفس الآلية عبر RabbitMQ.

تصميم الـ Exchanges والـ Queues في نظام شبيه بـ WhatsApp

1. أنواع الرسائل في نظام الدردشة

نحتاج في العادة لأكثر من نوع من الرسائل داخل النظام:

  • Chat Messages: رسائل نصية / صور / ملفات بين المستخدمين أو داخل المجموعات.
  • Typing Indicators: إشعار أن المستخدم يكتب الآن.
  • Status Updates: متصل الآن / آخر ظهور / حالة تم القراءة.
  • Notifications: إشعارات Push / إشعارات داخل التطبيق.

كل نوع من هذه الأنواع يمكنه أن يتعامل مع Exchange وQueues بطريقة مختلفة لضمان أفضل أداء.

2. اختيار نوع الـ Exchange المناسب

في RabbitMQ، نوع الـ Exchange مهم جداً في تصميم rabbitmq messaging system design. لتطبيقات شبيهة بـ WhatsApp، يمكن استخدام المزيج التالي:

  • Direct Exchange:

    مناسب لتوجيه رسالة من مستخدم لمستخدم آخر بحسب user_id أو queue per user. مثالي للـ One-to-One chat.

  • Topic Exchange:

    مناسب للـ Group Chats حيث نحتاج Broadcast لعدة مستخدمين في نفس الغرفة باستخدام Routing Key مثل: chat.room.<room_id>.

  • Fanout Exchange:

    مناسب للإشعارات العامة أو Broadcasting مثل: maintenance messages أو system-wide notifications.

3. نموذج تصميم Queues للمستخدمين

هناك أكثر من Strategy لتصميم Queues في نظام دردشة:

أ) Queue لكل مستخدم (Per-User Queue)

  • لكل مستخدم Queue خاصة به: user.<user_id>.queue
  • Exchange من نوع Direct أو Topic يقوم بتوجيه الرسالة لصف (Queue) المستخدم الهدف.
  • الباك إند أو WebSocket Server الخاص بالمستخدم يستهلك (Consume) من نفس الـ Queue.

مزايا:

  • تحكم كامل في رسائل كل مستخدم
  • سهولة إدارة حالة المستخدم (Online / Offline)
  • قابل للتوسع أفقياً: يمكن توزيع Queues على Nodes مختلفة في Cluster RabbitMQ

عيوب:

  • عدد كبير من الـ Queues لو عندك ملايين المستخدمين
  • تحتاج ضبط جيد للـ Cluster والـ Resources

ب) Queue لكل Connection أو Session

في بعض التصاميم، يكون لكل Session أو لكل WebSocket Connection Queue خاصة. هذا يعطي مرونة أكبر لكن يزيد التعقيد. الغالب في الأنظمة الكبيرة هو الاعتماد على Per-User Queue.

تدفق الرسالة من User A إلى User B باستخدام RabbitMQ

1. إرسال الرسالة (Publish)

عند إرسال رسالة من A إلى B:

  1. Client (تطبيق الجوال أو الويب) يرسل الرسالة إلى API أو WebSocket Gateway.
  2. الخدمة الخلفية (Chat Service) تقوم بعمل:
    • تحقق من صلاحيات المرسل (Authentication & Authorization).
    • إضافة Metadata مثل message_id, timestamp.
    • دفع الرسالة إلى RabbitMQ بإحدى الصيغ:
      • Exchange: chat.direct
      • Routing Key: user.<receiver_id>

من المهم استخدام delivery_mode=2 (Persistent Messages) لضمان عدم ضياع الرسالة حتى لو RabbitMQ عمل Restart، مع تفعيل durable queues.

2. استهلاك الرسالة وتسليمها للمستلم

الـ Consumer المسؤول عن تسليم الرسالة للمستخدم B يمكن أن يكون WebSocket Server:

  • كل WebSocket Server يحتفظ بقائمة اتصال للمستخدمين المتصلين عليه.
  • هذا السيرفر يعمل Consumer على Queues خاصة بالمستخدمين المتصلين عليه.
  • عند استقبال رسالة من Queue user.<user_id>.queue:
    • لو B متصل على هذا السيرفر: يتم إرسال الرسالة عبر WebSocket بشكل فوري.
    • لو B غير متصل:
      • تُترك الرسالة في Queue حتى إعادة الاتصال (أو)
      • يتم دفع Event لخدمة Push Notifications لإرسال إشعار جوال.

لمن يريد تفاصيل أكثر حول بناء نظام Real-Time، يمكن الرجوع لمقال: بناء نظام إشعارات Real-Time باستخدام RabbitMQ وWebSockets خطوة بخطوة.

تصميم إشعارات Online/Offline و Delivery Status

1. إشعارات حالة الاتصال (Presence)

تطبيق مثل WhatsApp يحتاج لمعرفة:

  • المستخدم متصل الآن (Online)
  • المستخدم خرج (Offline)
  • آخر ظهور (Last Seen)

يمكن تصميم Presence System باستخدام RabbitMQ كالتالي:

  • عند اتصال المستخدم عبر WebSocket:
    • يتم نشر (Publish) رسالة إلى Exchange: presence.topic
    • Routing Key مثل: user.<user_id>.online
  • عند قطع الاتصال:
    • نفس الشيء لكن Routing Key: user.<user_id>.offline
  • Consumers مختلفة يمكنها:
    • تحديث حالة المستخدم في Cache (Redis) أو DB
    • إرسال إشعارات للطرف الآخر لو مطلوب (مثلاً "فلان متصل الآن")

2. حالة الرسالة (Delivered / Seen)

كل رسالة في WhatsApp تمر بمراحل:

  • Sent: تم إرسالها من جهاز المرسل
  • Delivered: وصلت لجهاز المستقبل
  • Seen: تم قراءتها

يمكن عمل ذلك عبر Events تمر أيضاً عبر RabbitMQ:

  1. عند استلام B للرسالة، Client يرسل Event لـ Backend: message_delivered.
  2. Backend ينشر رسالة إلى Exchange: message.status مع Routing Key مثل: status.<message_id>.delivered.
  3. Consumer يقوم بتحديث حالة الرسالة في قاعدة البيانات + دفع إشعار للمرسل A بأن الحالة أصبحت Delivered.
  4. نفس الفكرة لـ Seen مع Event message_seen.

التعامل مع Push Notifications للمستخدمين Offline

عندما يكون المستخدم B Offline، نحتاج لإشعاره عبر Push Notification (Firebase أو APNs). RabbitMQ يجعل دمج هذه الخدمات سهلاً:

  1. Consumer مسؤول عن مراقبة Queue مثل offline.notifications.
  2. عند وجود رسالة جديدة، يتحقق من حالة المستخدم من Cache/DB.
  3. لو المستخدم Offline:
    • يرسل طلب إلى خدمة Push Service (تتصل بـ Firebase أو APNs).
    • تُسجل في DB لأغراض Analytics أو Retry.

إذا أردت تصميم نظام Push Notifications متكامل، راجع: تصميم نظام Push Notifications للتطبيقات باستخدام RabbitMQ وFirebase.

اعتبارات الأداء والتوسع (Scalability & High Availability)

1. توسيع RabbitMQ أفقياً (Clustering)

لتطبيقات شبيهة بـ WhatsApp، عدد الرسائل هائل، لذا يجب:

  • استخدام RabbitMQ Cluster يتكون من عدة Nodes.
  • توزيع الـ Queues والـ Connections على هذه الـ Nodes.
  • استخدام Load Balancer أمام الـ Nodes.

كما يُنصح باستخدام:

  • Mirrored Queues / Quorum Queues لضمان High Availability
  • تفعيل Publisher Confirms للتأكد من استلام الرسائل على الـ Broker

لبناء أنظمة High Availability، يمكنك الرجوع للمقال: تصميم نظام High Availability: كيف تبني تطبيق لا يتوقف عن العمل.

2. ضبط الـ Prefetch و Consumer Concurrency

لتحقيق أعلى أداء:

  • استخدم prefetch لإدارة عدد الرسائل التي يمكن للـ Consumer سحبها قبل عمل Acknowledge.
  • قم بزيادة عدد الـ Consumers لكل Queue لتوزيع الحمل.
  • قم بفصل أنواع الـ Traffic: Queues للرسائل النصية، أخرى للصور/الملفات، وأخرى للـ Notifications.

3. تصميم Retry & Dead Letter Queues

بعض الرسائل قد تفشل معالجتها (مثل فشل الاتصال بـ Firebase أو مشكلة في DB). في rabbitmq messaging system design احترافي، نحتاج:

  • Dead Letter Exchange (DLX) لتحويل الرسائل الفاشلة إلى Dead Letter Queue.
  • Retry Mechanism عبر:
    • إعادة إرسال الرسالة بعد Delay
    • تحديد عدد معين من المحاولات
  • Logging و Monitoring للرسائل الفاشلة لتحليل المشاكل.

Integrations مع Backend Frameworks

يمكنك دمج RabbitMQ مع عدة أطر عمل لبناء Backends لنظام شبيه بـ WhatsApp، مثل:

  • Python (FastAPI, Django)
  • Node.js (NestJS, Express)
  • Golang
  • Java / Spring Boot

لو كنت تستخدم FastAPI، يمكنك الاستفادة من المقال: دمج RabbitMQ مع FastAPI: بناء نظام إشعارات عالي الأداء.

أفضل الممارسات لتصميم نظام شبيه بـ WhatsApp باستخدام RabbitMQ

  • استخدم Exchanges متعددة لكل نوع من الرسائل (Chat، Status، Notifications، Presence).
  • صمم Per-User Queue أو Per-Room Queue بحسب طبيعة التطبيق.
  • فصل الخدمات:
    • Messaging Service
    • Notification Service
    • Presence Service
    • Media Service (لرفع الملفات والصور)
  • تأكد من:
    • Durable Queues
    • Persistent Messages
    • Publisher Confirms & Consumer Acknowledgements
  • استخدم Monitoring عبر أدوات مثل Prometheus, Grafana, RabbitMQ Management UI.
  • صمم Backpressure & Rate Limiting لمنع إغراق النظام بالرسائل.

خلاصة: كيف تبدأ فعلياً؟

لبناء نظام Notifications و Messaging يشبه WhatsApp باستخدام RabbitMQ، ركّز على:

  1. رسم معمارية واضحة تحدد الخدمات (Microservices أو Modules) وكيف تتواصل عبر RabbitMQ.
  2. تحديد أنواع الرسائل (Chat, Status, Presence, Notifications) وتصميم Exchanges وRouting Keys لكل نوع.
  3. اختيار Strategy لQueues (Per-User, Per-Room) بما يناسب حجم التطبيق.
  4. تنفيذ Flow الرسائل الأساسية:
    • إرسال رسالة من A إلى B
    • تخزين الرسالة
    • تسليمها عبر WebSocket
    • إرسال Push Notifications لو المستخدم Offline
    • تتبع حالة الرسالة (Sent, Delivered, Seen)
  5. ضبط Scalability & High Availability مبكراً لتجنب المشاكل عند نمو عدد المستخدمين.

باستخدام تصميم جيد لـ rabbitmq messaging system design، يمكنك بناء نظام دردشة وإشعارات قوي يشبه WhatsApp أو Telegram، قادر على التعامل مع ملايين الرسائل في اليوم بدون التأثير على أداء التطبيق الأساسي، وبنفس الوقت يحتفظ بمرونة عالية في التطوير والتوسع المستقبلي.

حول المحتوى:

شرح تصميم نظام إشعارات ورسائل مشابه لتطبيقات الدردشة باستخدام RabbitMQ.

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

أضف تعليقك