طلباتنا كانت تتكدس وتموت: كيف أنقذتنا ‘طوابير الرسائل’ (Message Queues) من جحيم التجمد تحت الضغط؟

يا جماعة الخير، السلام عليكم ورحمة الله وبركاته. معكم أخوكم أبو عمر.

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

لحد ما إجا يوم “الجمعة البيضاء”. قررنا نعمل عروض قوية جداً، وفعلاً، الناس هجمت على التطبيق هجوم كاسح. في الدقائق الأولى، كنا بنحتفل بالأرقام اللي بنشوفها على لوحة التحكم. لكن فجأة، بدأت الكارثة. الهواتف في قسم الدعم الفني ما بطلت ترن، والرسائل على السوشيال ميديا انهالت علينا: “طلبي معلق!”، “دفعت الفلوس والطلب ما تأكد!”، “شو القصة يا جماعة؟ التطبيق مجمّد!”.

فتحنا أنظمة المراقبة، وشفنا المشهد المرعب: المعالجات (CPUs) للخوادم واصلة 100%، الذاكرة شبه ممتلئة، وقاعدة البيانات يا دوب بتتنفس. الطلبات كانت بتوصل للخادم، بس بتموت وهي بتحاول تتنفذ. كل طلب كان لازم يعمل ألف شغلة: يتأكد من الدفع، يبعت إشعار للمطعم، يحسب وقت التوصيل، يخصم من المخزون، يبعت إيميل تأكيد للمستخدم… كل هاد والمستخدم المسكين قاعد بستنى الشاشة تخلص تحميل. النظام كله صار “عنق زجاجة” (Bottleneck)، وكنا على وشك نفقد ثقة آلاف المستخدمين في يوم واحد.

في عز هالمعمعة، واحد من الشباب صرخ: “يا جماعة، إحنا بنقتل النظام بإيدينا! لازم نفصل استلام الطلب عن معالجته!”. وهون، زي ما بحكوها، “نورت اللمبة”. الحل كان قدامنا طول الوقت: طوابير الرسائل (Message Queues).

ما هي المشكلة الحقيقية؟ فهم المعالجة المتزامنة (Synchronous)

قبل ما نغوص في الحل، خلينا نفهم أصل المشكلة. نظامنا القديم كان شغال بطريقة “متزامنة” (Synchronous). تخيل حالك رايح على بقالة، وصاحب البقالة بعمل كل شي لحاله. أنت بتعطيه ورقة الطلبات، وهو بروح بجيبلك الغرض الأول، بعدين برجع بجيب التاني، بعدين بحاسبك، بعدين بعطيك الباقي… وأنت واقف محلك، ما بتقدر تعمل إشي غير إنك تستنى. والأسوأ، لو صار عنده مشكلة وهو بجيب غرض (مثلاً، ما لقاه)، كل العملية بتتعطل، والزبائن اللي وراك بالصف بستنوا.

هذا بالضبط اللي كان بصير في تطبيقنا:

  1. المستخدم يضغط على “تأكيد الطلب”.
  2. الخادم يستقبل الطلب.
  3. يبدأ الخادم بالعمل (والمستخدم ينتظر):
    • معالجة الدفع عبر بوابة الدفع الإلكتروني.
    • حفظ تفاصيل الطلب في قاعدة البيانات.
    • إرسال الطلب إلى نظام المطعم.
    • إرسال إشعار (Push Notification) للمستخدم.
    • إرسال بريد إلكتروني للتأكيد.
  4. بعد انتهاء كل هذا، الخادم يرسل استجابة للمستخدم: “تم طلبك بنجاح”.

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

الحل السحري: المعالجة غير المتزامنة (Asynchronous) وطوابير الرسائل

طابور الرسائل هو ببساطة وسيط، “ساعي بريد” رقمي يقف بين أجزاء تطبيقك المختلفة. بدل ما جزء يكلم الجزء التاني مباشرة، هو بحطله “رسالة” في صندوق بريد (الطابور)، والجزء التاني بقرأها وقت ما يفضى.

خلينا نرجع لمثال البقالة. تخيل لو البقالة كبرت وصارت هايبر ماركت. أنت بتروح على كاونتر، بتعطي الموظف ورقة طلباتك (وهي عملية سريعة جداً)، وهو بعطيك رقم وبحكيلك “طلبك قيد التجهيز، رح ننادي على رقمك بس يجهز”. أنت هسا صرت حر! بتقدر تروح تشرب قهوة، تتفرج على باقي الأغراض… وفي الخلفية، في فريق كامل من العمال (Consumers) كل واحد فيهم أخد طلب من “طابور” الطلبات وبجهزه. النظام صار أسرع وأكثر كفاءة.

هذا بالضبط ما فعلناه. قمنا بتغيير تدفق العمل ليصبح “غير متزامن” (Asynchronous) باستخدام طابور رسائل:

  1. المستخدم يضغط على “تأكيد الطلب”.
  2. الخادم يستقبل الطلب، ويقوم بشيء واحد فقط وسريع جداً: إنشاء رسالة تحتوي على تفاصيل الطلب ووضعها في طابور الرسائل.
  3. الخادم يرسل فوراً استجابة للمستخدم: “استلمنا طلبك وسنبدأ بمعالجته الآن!”. (المستخدم مبسوط، التطبيق صاروخ 🚀).
  4. في الخلفية، لدينا “عمال” (Consumers/Workers) وهي برامج منفصلة كل وظيفتها في الحياة هي مراقبة طابور الرسائل.
  5. عامل من هؤلاء العمال يأخذ رسالة الطلب من الطابور ويبدأ بتنفيذ المهام الثقيلة (معالجة الدفع، إرسال الإشعارات، إلخ) بهدوء وبدون ضغط.

الفوائد التي غيرت حياتنا

  • استجابة فائقة (Blazing Fast Response): واجهة المستخدم صارت سريعة جداً لأنها لم تعد تنتظر اكتمال العمليات الطويلة.
  • الموثوقية والمتانة (Reliability & Durability): ماذا لو تعطل “العامل” الذي يعالج الدفع؟ لا مشكلة! الرسالة تبقى محفوظة بأمان في الطابور. عندما يعود العامل للعمل، سيأخذ الرسالة ويكمل من حيث توقف. لم نعد نفقد أي طلبات!
  • قابلية التوسع الأفقية (Horizontal Scaling): هل تتذكرون ضغط يوم الجمعة البيضاء؟ الآن، الحل بسيط جداً. بدلاً من زيادة حجم الخادم الرئيسي (وهو أمر مكلف ومعقد)، كل ما علينا فعله هو تشغيل المزيد من “العمال” (Consumers). لو عنا 10,000 طلب في الطابور، بنشغل 50 عامل يشتغلوا عليهم بالتوازي. انتهى الضغط؟ بنطفي العمال الزيادة. مرونة مذهلة!
  • فصل الخدمات (Decoupling): أصبح الجزء المسؤول عن استقبال الطلبات (المنتِج/Producer) مفصولاً تماماً عن الجزء الذي يعالجها (المستهلِك/Consumer). يمكننا تحديث أو تعديل أو حتى إعادة كتابة أي جزء منهما بلغة برمجة مختلفة دون أن يؤثر على الآخر، طالما أنهما متفقان على شكل “الرسالة”.

مثال عملي بسيط باستخدام RabbitMQ و Python

يعتبر RabbitMQ من أشهر وأقوى أنظمة طوابير الرسائل. دعونا نرى كيف يمكن أن يبدو الكود بسيطاً. (هذا مجرد مثال توضيحي لتقريب الفكرة).

1. المُنتِج (Producer): الخادم الذي يستقبل الطلب

هذا الكود يمثل ما يحدث عندما يضغط المستخدم على زر الشراء. هو فقط يضع رسالة في الطابور المسمى `orders_queue`.


# producer.py
import pika
import json

# الاتصال بـ RabbitMQ
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

# نتأكد من وجود الطابور، إذا لم يكن موجوداً سيتم إنشاؤه
channel.queue_declare(queue='orders_queue', durable=True) # durable تعني أن الطابور لن يختفي لو تعطل السيرفر

# بيانات الطلب التي سنرسلها
order_details = {
    'user_id': 123,
    'product_id': 'XYZ-789',
    'amount': 99.95
}

# نشر الرسالة في الطابور
channel.basic_publish(
    exchange='',
    routing_key='orders_queue', # اسم الطابور الذي سنرسل إليه
    body=json.dumps(order_details), # نحول البيانات إلى نص JSON
    properties=pika.BasicProperties(
        delivery_mode=2,  # اجعل الرسالة ثابتة (persistent)
    ))

print(f" [x] Sent order: {order_details}")
connection.close()

2. المستهلِك (Consumer): العامل الذي يعالج الطلب

هذا الكود يمثل “العامل” الذي يعمل في الخلفية، يستمع باستمرار للطابور، وكلما وصلت رسالة، يأخذها وينفذ المهام المطلوبة.


# consumer.py
import pika
import time
import json

# الاتصال بـ RabbitMQ
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

channel.queue_declare(queue='orders_queue', durable=True)
print(' [*] Waiting for orders. To exit press CTRL+C')

# هذه هي الدالة التي سيتم استدعاؤها عند وصول رسالة جديدة
def process_order(ch, method, properties, body):
    order_details = json.loads(body)
    print(f" [x] Received order: {order_details}")

    # هنا تبدأ العمليات الطويلة
    print(" --> Processing payment...")
    time.sleep(2) # محاكاة لعملية الدفع
    print(" --> Sending notification to restaurant...")
    time.sleep(1) # محاكاة لإرسال إشعار
    print(" --> Sending confirmation email...")
    time.sleep(1) # محاكاة لإرسال إيميل

    print(f" [x] Done processing order for user {order_details['user_id']}")
    
    # نُخبر الطابور أننا انتهينا من معالجة هذه الرسالة بنجاح
    ch.basic_ack(delivery_tag=method.delivery_tag)

# نطلب من الطابور أن يرسل لنا رسالة واحدة في كل مرة
channel.basic_qos(prefetch_count=1)

# ربط دالة process_order مع الطابور
channel.basic_consume(queue='orders_queue', on_message_callback=process_order)

# بدء الاستماع إلى الطابور إلى الأبد
channel.start_consuming()

نصيحة من أبو عمر: عندما تبدأ، استخدم خاصية `durable=True` عند إنشاء الطابور وخاصية `delivery_mode=2` عند إرسال الرسائل. هذا يضمن أن طوابيرك ورسائلك لن تضيع إذا تم إعادة تشغيل خادم RabbitMQ. الموثوقية هي أهم ميزة هنا، فلا تتنازل عنها.

متى يجب أن تفكر في طوابير الرسائل؟

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

  • المهام الخلفية (Background Jobs): أي شيء لا يحتاج المستخدم إلى انتظار نتيجته فوراً. مثل إرسال نشرة بريدية، أو معالجة فيديو تم تحميله، أو إنشاء تقرير PDF ضخم.
  • امتصاص الصدمات (Load Buffering): عندما يكون لديك تدفق كبير ومفاجئ للبيانات أو الطلبات. الطابور يعمل كـ “مخزن مؤقت” يمتص هذا الضغط ويسمح لنظامك بمعالجته بالسرعة التي تناسبه.
  • التواصل بين الخدمات المصغرة (Microservices): إذا كانت بنيتك تعتمد على الخدمات المصغرة، فاستخدام طوابير الرسائل للتواصل بينها أفضل بكثير من استدعاءات API المباشرة (HTTP). هذا يمنع “سلسلة الفشل” (cascading failures)، حيث يؤدي فشل خدمة واحدة إلى انهيار كل الخدمات التي تعتمد عليها.
  • العمليات المجدولة أو المتأخرة: بعض الأنظمة تسمح لك بإرسال رسالة ليتم استهلاكها بعد فترة زمنية معينة (e.g., “أرسل تذكيراً للمستخدم بعد 24 ساعة”).

الخلاصة يا جماعة الخير 🙏

الدرس الذي تعلمناه من تلك الجمعة الصعبة كان قاسياً ولكنه ثمين: لا تجعل المستخدم يدفع ثمن تعقيدات نظامك.

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

نصيحتي الأخيرة لك: لا تنتظر حتى ينهار نظامك تحت الضغط لتبدأ بالتفكير في هذه الحلول. ابدأ بتعلمها اليوم، وجربها في مشروعك الجانبي القادم. قد تكون هي الشيء الذي ينقل تطبيقك من مجرد “تطبيق شغال” إلى “تطبيق موثوق وقابل للتوسع” قادر على مواجهة أي تحدٍ.

أبو عمر

سجل دخولك لعمل نقاش تفاعلي

كافة المحادثات خاصة ولا يتم عرضها على الموقع نهائياً

آراء من النقاشات

لا توجد آراء منشورة بعد. كن أول من يشارك رأيه!

آخر المدونات

الحوسبة السحابية

سيرفراتنا كانت تلتهم الميزانية وهي خاملة: كيف أنقذتنا ‘الحوسبة بدون خوادم’ (Serverless) من جحيم الفواتير المنتفخة؟

أشارككم قصة حقيقية من قلب المعركة البرمجية، كيف انتقلنا من فواتير سيرفرات باهظة وشبه خاملة إلى بنية تحتية مرنة وفعالة من حيث التكلفة بفضل الحوسبة...

11 أبريل، 2026 قراءة المزيد
التوظيف وبناء الهوية التقنية

سيرتي الذاتية كانت تذهب إلى ثقب أسود: كيف أنقذني فهم ‘أنظمة تتبع المتقدمين’ (ATS) من جحيم الرفض الآلي؟

هل ترسل سيرتك الذاتية مرارًا وتكرارًا دون أي رد؟ قد تكون المشكلة ليست في خبرتك، بل في روبوتات التوظيف (ATS). في هذه المقالة، أشارككم قصتي...

11 أبريل، 2026 قراءة المزيد
التكنلوجيا المالية Fintech

من الكابوس اليدوي إلى التحقق الفوري: كيف أنقذنا الذكاء الاصطناعي وOCR من جحيم عمليات KYC

في هذه المقالة، أشارككم قصة حقيقية من تجربتي كمطور برمجيات، وكيف انتقلنا من المعاناة اليدوية في عمليات التحقق من هوية العملاء (KYC) إلى نظام آلي...

10 أبريل، 2026 قراءة المزيد
البنية التحتية وإدارة السيرفرات

مراقبة السيرفرات: كيف أنقذنا Prometheus و Grafana من جحيم ‘لماذا تعطل كل شيء فجأة؟’

في إحدى الليالي، بينما كان الجميع نائمين، توقف كل شيء. كانت تلك الليلة نقطة التحول التي نقلتنا من عالم إطفاء الحرائق الفوضوي إلى عالم المراقبة...

10 أبريل، 2026 قراءة المزيد
ادارة الفرق والتنمية البشرية

مراجعات الكود: كيف حولنا ساحة المعركة إلى ورشة عمل إبداعية بفضل “السلامة النفسية”؟

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

10 أبريل، 2026 قراءة المزيد
اختبارات الاداء والجودة

بنيتنا التحتية كانت بيتًا من ورق: كيف أنقذتنا ‘هندسة الفوضى’ من جحيم الأعطال المفاجئة؟

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

10 أبريل، 2026 قراءة المزيد
البودكاست