طوابير المهام الخلفية: لا تجعل المستخدم ينتظر

مفهوم الطوابير، أمثلة عملية، الفرق بين Redis وdatabase driver، إدارة العمال بـ Supervisor، ونصائح إنتاج مع Laravel كمثال.
ليش تحتاج طوابير المهام الخلفية؟
طوابير المهام الخلفية (queues) تسمح لتطبيقك ينفّذ المهام الثقيلة بعيداً عن الطلب المباشر، عشان المستخدم ما يجلس ينتظر أمام شاشة معلّقة. بدل ما يستنى المستخدم 8 ثوانٍ حتى يُرسل بريد ترحيبي وتُعالج صورة ويُحدَّث تقرير، يستلم الرد فوراً خلال جزء من الثانية، وتتم بقية المهام في الخلفية بلا ما يشعر بها. الفكرة الأساسية: افصل ما يحتاج المستخدم رؤيته الآن عمّا يقدر يصير بعد شوي.
الفرق ملموس بالأرقام: طلب يستغرق 6 ثوانٍ لأنه يرسل بريداً ويعالج صورة ينزل إلى أقل من 200 مللي ثانية لو حوّلت هذي المهام لطابور خلفي. تجربة المستخدم تتحسن جذرياً، والسيرفر يتحمل طلبات أكثر بنفس الموارد لأنه لا يحبس عمليات الويب في انتظار مهام بطيئة. هذا الفرق يحدد إن كان تطبيقك يحس سريعاً أو ثقيلاً.
أمثلة على المهام اللي تروح للطابور
أي مهمة تأخذ وقتاً ولا يحتاج المستخدم نتيجتها فوراً، مرشحة للطابور:
- إرسال البريد: بريد الترحيب، إعادة تعيين كلمة المرور، الإشعارات. الاتصال بخادم البريد قد يأخذ ثوانٍ، فلا سبب يحبس المستخدم أثناءه
- معالجة الصور: تصغير الصور المرفوعة، إنشاء نسخ بأحجام مختلفة، ضغطها. عمليات تستهلك المعالج وتأخذ وقتاً
- توليد التقارير: تقرير PDF كبير أو تصدير Excel لآلاف الصفوف يأخذ وقتاً، فيولَّد في الخلفية ويُرسل رابطه لما يجهز
- استدعاء خدمات خارجية: إرسال رسالة WhatsApp عبر API أو مزامنة بيانات مع نظام آخر، مهام تعتمد على استجابة طرف ثالث قد يتأخر
القاعدة: لو المهمة تأخذ أكثر من نصف ثانية ولا يحتاج المستخدم نتيجتها في نفس الشاشة، حوّلها لطابور. تطبيقك بيصير أسرع وأكثر استقراراً.
Redis مقابل database driver
الطابور يحتاج مكاناً يخزّن فيه المهام المنتظرة، وهنا تختار المحرك (driver). الخياران الأشهر:
- database: يخزّن المهام في جدول بقاعدة بياناتك. سهل الإعداد، لا يحتاج خدمة إضافية، ومناسب للتطبيقات الصغيرة والمتوسطة بحجم مهام معقول. عيبه أنه أبطأ نسبياً لأنه يعتمد على قاعدة البيانات
- Redis: يخزّن المهام في ذاكرة سريعة، أسرع بكثير ويتحمّل أعداداً ضخمة من المهام في الثانية. الخيار المفضّل للإنتاج بحجم كبير، مقابل الحاجة لتشغيل خدمة Redis وإدارتها
نصيحة عملية: ابدأ بمحرك database لو حجمك صغير، لأنه أبسط ويكفي. لما يكبر عدد المهام وتبدأ تلاحظ ضغطاً على قاعدة البيانات، انتقل لـ Redis. الانتقال سهل غالباً لأنه يتم بتغيير إعداد واحد في الأطر الحديثة.
Supervisor لإدارة العمال
العامل (worker) هو العملية اللي تسحب المهام من الطابور وتنفّذها. المشكلة: لو توقّف العامل لأي سبب (خطأ، إعادة تشغيل، استهلاك ذاكرة)، تتوقف معالجة الطابور بالكامل والمهام تتكدّس. الحل هو Supervisor، أداة تراقب العمال وتعيد تشغيلهم تلقائياً لو توقّفوا.
تضبط Supervisor يشغّل عدداً محدداً من العمال ويبقيهم شغّالين دائماً. لو مات عامل، Supervisor يعيده خلال ثوانٍ. تقدر تشغّل عدة عمال بالتوازي عشان تعالج مهاماً أكثر في نفس الوقت، وتضبط عددهم حسب موارد سيرفرك وحجم الطابور. بلا Supervisor أو بديل مثله، تشغيل العمال في الإنتاج يبقى هشاً وغير موثوق.
نصائح للإنتاج
تشغيل الطوابير على سيرفر إنتاج يحتاج انتباهاً لعدة نقاط عشان يبقى موثوقاً:
- أعد نشر العمال بعد كل تحديث: العامل يحمّل الكود في الذاكرة عند بدئه، فبعد نشر تحديث لازم تعيد تشغيل العمال عشان يشتغلوا بالكود الجديد
- اضبط إعادة المحاولة: حدد كم مرة تُعاد المهمة الفاشلة قبل ما تُعتبر فاشلة نهائياً، عشان لا تدور مهمة معطوبة إلى ما لا نهاية
- راقب المهام الفاشلة: الأطر الحديثة تخزّن المهام الفاشلة في جدول منفصل، راجعه دورياً وأعد تشغيل ما يستحق
- افصل الطوابير حسب الأولوية: ضع المهام الحرجة (بريد التحقق) في طابور عالي الأولوية والمهام الثقيلة (التقارير) في طابور منفصل، عشان لا تعطّل الثقيلة السريعة
في Laravel مثلاً، منظومة الطوابير جاهزة ومدمجة: تعرّف المهمة كصنف (class)، ترسلها للطابور بأمر واحد، وتشغّل العامل بأمر queue:work، وتديره بـ Supervisor. نفس المفاهيم موجودة في أطر أخرى بأسماء مختلفة، لكن المبدأ واحد: افصل الثقيل عن السريع.
في كلاود، سيرفرك في مركز بيانات الرياض يعطيك بيئة كاملة تشغّل فيها تطبيقك مع Redis وSupervisor والعمال تحت سيطرتك، بموارد تختارها حسب حجم الطوابير. تطبيق سريع يبدأ من بنية تحتية مستقرة قريبة من مستخدميك، حيث المهام الخلفية تشتغل بلا انقطاع وزمن الاستجابة للمستخدم السعودي يبقى قريباً من 8ms.
