هندسة أنظمة
هندسة الطوابير والمهام الخلفية
طوابير يمكنك تركها وشأنها - مهام لا تتأثر بالتكرار، وإعادات محاولة متباعدة، ومسار فشل يراقبه أحد فعلًا، وعمّال ينجون من النشر دون فقد عمل.
الطابور هو الجزء الأسهل إضافةً والأصعب تشغيلًا في تطبيق Laravel. الدالة
dispatch() سطر واحد، وكل ما يصنع الفرق بين طابور وطابور موثوق يحدث بعد ذلك
السطر.
الأسئلة الأربعة التي على الطابور الإجابة عنها
ماذا يحدث حين تفشل المهمة؟ ليس «إن». تنتهي مهلة واجهة طرف ثالث، ويُحذف سجل بين الإرسال والتنفيذ، ويعيد نشرٌ تشغيل العامل في منتصف المهمة. يجب أن تُكتب الإجابة كسياسة إعادة محاولة بتباعد، وعدد محاولات أقصى، ووجهة لما يظل فاشلًا في نهايتها.
ماذا يحدث حين تُنفَّذ مرتين؟ التسليم مرة واحدة على الأقل هو الضمان المعتاد، ما يعني أن كل مهمة يجب أن تكون آمنة للتكرار أو محروسة بشيء يجعل التكرار غير ضار. رسالة تُرسل مرتين إحراج. ودفعة تُحصَّل مرتين ردّ مبالغ وخيط دعم.
من يعلم؟ امتلاء failed_jobs بصمت هو أكثر عطل إنتاج يُستدعى إلينا للنظر
فيه، وهو ليس عطل طابور في الحقيقة قط. فشلت المهمة، وسجّل الإطار ذلك تمامًا كما
صُمِّم، ولم يكن شيء موصولًا بالتسجيل.
ماذا يحدث أثناء النشر؟ العامل الذي يحمل مهمة حين تتغير الشيفرة تحته إما يُعاد تشغيله بلطف أو يُقتل. وأيّهما يحدث يعتمد على إعداد ترثه أغلب الفرق ولا تختاره.
ماذا نفعل
نجعل المهام غير متأثرة بالتكرار. معرّف تحمله المهمة، يُفرض حيث يهبط الأثر فعلًا - قيد فريد، أو مفتاح عدم تكرار لدى مزوّد الدفع، أو انتقال حالة لا يمكن أن يحدث إلا مرة. لا فحصٌ ثم فعل في PHP، فذلك سيمرّ منه عاملان في آنٍ واحد يوم يهم الأمر.
نضبط سياسات إعادة المحاولة لكل مهمة لا لكل تطبيق. فشل HTTP العابر يريد عدة محاولات بتأخير متزايد. وفشل التحقق يريد صفرًا - إعادته تحرق الطابور وتؤخّر كل ما خلفه. والتمييز بينهما تغيير من سطرين ولا يكاد يُجرى.
نعطي الإخفاقات مكانًا تذهب إليه. المهام الفاشلة تُبلَّغ إلى ما يراقبه فريقك بالفعل، بسياق كافٍ للتصرف. ومسار رسائل ميتة لما لا يمكن إعادة محاولته. وتنبيه على المعدل لا على الحدث المفرد، ليكون إشارة لا ضجيجًا.
نضبط حجم الطوبولوجيا. فصل الطوابير بحسب متطلب زمن الاستجابة لا بحسب الوظيفة، كي لا يؤخّر تصدير ليلي إعادةَ تعيين كلمة مرور. وعمّال بحجم يناسب شكل العمل الفعلي. وHorizon مضبوطًا بمشرفين يطابقون ذلك، ومقاييس تجعل التراكم المتنامي مرئيًا قبل أن يصير حادثًا.
نجعل العمل الطويل قابلًا للنجاة. مهام مجمّعة بتقدّم، مقسّمة إلى دفعات كي تكلّف إعادةُ التشغيل دفعةً واحدة لا الجولة كلها، وطريقة للاستئناف بدل البدء من جديد.
العمل المجدول، وله المشكلات نفسها
يحظى المجدول باهتمام أقل من الطابور ويفشل بالطرق نفسها. مهمة تتداخل مع نفسها لأن الجولة السابقة لا تزال تعمل. مهمة تتوقف بصمت لأن مدخل cron كان على خادم استُبدل. مهمة فشلُها سطر سجل لا يقرؤه أحد.
نعامل المهام المجدولة كمهام بمُشغِّل: حماية من التداخل حيث يهم، ونبض قلب ليُلحظ توقف مهمة عن العمل، ومسار الفشل نفسه الذي لكل شيء آخر.
كيف يجري التعاقد
أرسلوا أصناف المهام، وإن كنتم تحتفظون بها، سجلّ أسبوع من المهام الفاشلة. فما أخفق فعلًا يقول عن التصميم أكثر مما تقوله الشيفرة.
ما يعود نطاقٌ: كل مهمة مع سلوكها عند الفشل، وبنية الطوابير، والمراقبة، وما يدخل المرحلة الأولى. يحمل سعرًا، والعقد يشير إليه لا إلى محادثة.
ويصل العمل كطلبات دمج قابلة للمراجعة في مستودعكم، وسلوك إعادة المحاولة وعدم التكرار مُختبَرًا لا موصوفًا.
ماذا تتسلّم
مراجعة لكل مهمة وكل مهمة مجدولة في التطبيق مع توثيق سلوكها عند الفشل، والإصلاحات كطلبات دمج قابلة للمراجعة، وطوبولوجيا الطوابير وإعداد العمّال كشيفرة، والمراقبة موصولة بما تستخدمه أصلًا.
والمُخرَج الذي يهمّنا هو الأصعب عرضًا: طابور لم يفكر فيه أحد منذ شهر، لأنه لم يحتج إلى أحد.
يقوم التصميم كله على افتراض واحد: أن كل مهمة ستُنفَّذ مرتين. ومعظم علل الطوابير خرقٌ له. وثانيها شيوعًا عامل ما زال يشغّل شيفرة الأسبوع الماضي، وهو خطأ نشر يبلّغ عن نفسه كأنه خطأ طابور. وإن كانت المهام بطيئة لا خاطئة، فالبداية عند عمل الأداء.
