قد يبدأ انهيار النظام الموزع بخطأ يبدو محدوداً، لكنه يتحول سريعاً إلى سلسلة من الأعطال عندما تعتمد مكونات كثيرة على بعضها بعضاً. في عرض قدمه Sam Newman، يربط المستشار المستقل في هندسة البرمجيات بين مفهوم الانهيار المتسلسل (Progressive Collapse) في الهندسة المدنية ومشكلات المرونة في الأنظمة الرقمية، ويخلص إلى أن منع كل الأخطاء غير ممكن، لكن يمكن تقليل فرص انتشارها وتأثيرها.
من مبنى Ronan Point إلى الخدمات السحابية
يعود Newman إلى حادثة انهيار جزئي في برج Ronan Point بمنطقة Canning Town في لندن عام 1968. تسبب انفجار غاز محدود داخل شقة Mrs. Ivy Hodge في اقتلاع جدار خارجي كان يحمل جزءاً من المبنى. انهارت الطوابق الأربعة الواقعة فوق موضع الانفجار، ثم أدى ذلك إلى سقوط جزء من زاوية البرج بتأثير متتابع. توفي أربعة أشخاص، وكان توقيت الحادثة قبيل السادسة صباحاً عاملاً ساعد على الحد من عدد الضحايا.
المغزى بالنسبة إلى البرمجيات ليس التشابه المادي بين مبنى وخدمة رقمية، بل نمط الفشل: عطل أولي صغير يعطل مكوّناً تعتمد عليه مكونات أخرى، فتتسع دائرة الضرر. ويصعب فهم هذه السلسلة في الأنظمة الموزعة لأن العلاقات بين الخدمات، وقواعد البيانات، وموازنات الأحمال، وأنظمة DNS لا تكون مرئية دائماً كصف من قطع الدومينو.
أمثلة رقمية على الفشل المتسلسل
في انقطاع منطقة us-east-1 من AWS خلال أكتوبر، واجه مكوّن فرعي في DynamoDB مشكلة أثناء تحديث مسارات DNS داخل بنية AWS. أدى خلل في عملية تحديث الخطط إلى حذف مسارات في Route 53، ثم بدأت خدمات تعتمد على تلك المسارات في التعطل، بما فيها موازنات الأحمال الشبكية، والحوسبة، وقوائم الانتظار، وEKS. وبما أن هذه الخدمات الأساسية تستخدمها خدمات أخرى، انتقلت المشكلة إلى منتجات وشركات تواجه المستخدمين، من بينها Alexa وRing وSlack وSnapchat وZoom وShopify، مع تأثر بعضها جزئياً وبعضها الآخر كلياً.
وبحسب شرح Newman المستند إلى تقرير AWS، كان النظام يتضمن مخططاً ينشئ خطط تغييرات DNS وعدة منفذين يطبقونها. استغرق أحد الخطط وقتاً أطول من المعتاد، ثم أنشئَت خطة أخرى نفذها منفذ مختلف بسرعة. عندما اكتمل تنفيذ الخطة القديمة لاحقاً، أزال المسارات التي كانت الخطة الجديدة قد أنشأتها. كانت النتيجة سباقاً (Race Condition) أدى إلى حذف إدخالات DNS.
أما المثال الثاني فكان موقعاً لبيع السيارات المستعملة والدراجات النارية والمقطورات، وكان يعمل عبر تطبيق باسم رمزي هو Sauron على عشرة خوادم. اعتاد التطبيق التعامل مع 30 إلى 60 طلباً متزامناً، لكنه واجه أكثر من 800 طلب. كان أحد المواقع التابعة يقبل الاتصالات ثم يعلق دون استجابة، بينما انتظر التطبيق 30 ثانية قبل إنهاء الطلب. استُنفد مخزن الاتصالات، ثم تراكمت الخيوط البرمجية واستهلكت المعالجات وقتها في إدارتها، فتوقف النظام بالكامل. وزاد المستخدمون الضغط بالضغط المتكرر على زر التحديث.
ثلاثة مسارات لتقليل الانهيار
يرى Newman أن التركيز على «سبب جذري» واحد يقود إلى تبسيط مخل. فقد يكون منع الشرارة مفيداً، لكنه لا يعالج كل الظروف التي تسمح للحريق بالانتشار. لذلك تركز هندسة المرونة على قبول احتمال وقوع الأعطال والاستعداد للحد من آثارها عبر ثلاث فئات مترابطة:
- تقليل المخاطر: إزالة مصادر الخطر أو الحد من قدرتها على استنزاف الموارد. في حالة AWS، شمل ذلك إيقاف إدارة DNS الآلية مؤقتاً إلى حين معالجة المشكلة، وإضافة اختبارات أفضل للمكوّن. وفي تطبيق Sauron، كان من الممكن استخدام إسقاط الحمل (Load Shedding) لقبول عدد محدد من الطلبات ورفض ما يتجاوز قدرة النظام، بدلاً من السماح بتراكمها حتى الانهيار.
- تقوية المكونات: رفع قدرة الخدمة على تحمل فشل جزء منها، عبر التكرار، والمراقبة، والاختبارات، وتحسين التنفيذ. قد يعني ذلك تشغيل نسخ متعددة من الخدمة خلف موازن أحمال، لكن القرار لا ينفصل عن أهمية المكوّن وتكلفته؛ فقد كان تطبيق Sauron في مرحلة تقاعد ولا يمثل سوى جزء من الإيرادات، ما جعل تشغيل نسخ احتياطية إضافية خياراً غير جذاب تجارياً في ذلك الوقت.
- تقليل الترابط: منع عطل مكوّن واحد من الانتقال إلى بقية النظام. يتضمن ذلك استخدام العوازل (Bulkheads)، وحدود المهلة، ومسارات بديلة، وتصاميم محلية أولاً عندما يكون ذلك ممكناً. فكلما قل اعتماد جزء من النظام على جزء آخر، أمكن احتواء الفشل بدلاً من نشره.
ما الذي يتغير عملياً أمام فرق التقنية؟
لا تعني المرونة تشغيل النظام في منطقتين أو سحابتين تلقائياً. يوضح Newman أن الخيارات تمتد من النسخ الاحتياطي والاستعادة، إلى بنية Pilot Light التي تكرر البيانات دون تشغيل البنية كاملة، ثم التعافي الدافئ، وصولاً إلى تشغيل موقعين نشطين في الوقت نفسه. تقلل هذه الخيارات زمن التوقف وفقدان البيانات تدريجياً، لكنها ترفع التكلفة والتعقيد.
كما يحذر من اعتبار التزامن ثنائي الاتجاه بين المواقع أمراً بسيطاً، خصوصاً عند إضافته إلى تطبيق قائم لم يُصمم له. وينطبق الأمر نفسه على تعدد السحابات؛ فهو قد يقلل الاعتماد على مزود واحد، لكنه يتطلب مهارات وتشغيلاً مختلفين لكل منصة، ولا يكفي نشر الكود نفسه على AWS وAzure لضمان الاستقلال، لأن العيب البرمجي ذاته قد يعطل البيئتين.
الخلاصة
الدرس الأساسي هو أن المرونة ليست بحثاً عن بيئة لا تفشل، بل تصميم النظام بحيث يبقى جزء منه قابلاً للعمل عندما يفشل جزء آخر. لذلك ينبغي تقييم المخاطر، وحدود السعة، ونقاط الاختناق، ومسارات الاعتماد، ثم الموازنة بين التكرار والعزل والتكلفة. وتظل القرارات مثل التشغيل متعدد المناطق أو متعدد السحابات خيارات هندسية وتجارية مرتبطة بأهمية الخدمة، لا وصفة عامة تصلح لكل نظام.