يا جماعة الخير، اسمحوا لي أن أروي لكم قصة حدثت معي قبل بضع سنوات، قصة لا أزال أتذكر تفاصيلها كأنها البارحة. كنا في الشركة على وشك إطلاق ميزة جديدة وكبيرة في تطبيق التجارة الإلكترونية الذي نعمل عليه، وكان التوقيت حرجاً جداً، قبل موسم التخفيضات الكبير بأسبوع واحد فقط.
قضينا أسابيع طويلة في التطوير والاختبار. قمنا بكل شيء “حسب الكتاب”: اختبارات الوحدة (Unit Tests) غطت 95% من الكود، اختبارات التكامل (Integration Tests) أظهرت أن الخدمات تتحدث مع بعضها البعض بسلاسة، واختبارات التحميل (Load Tests) أثبتت أن النظام يمكنه تحمل ثلاثة أضعاف عدد المستخدمين المتوقع. كل الإشارات كانت خضراء، وثقتنا كانت في السماء.
جاء يوم الإطلاق. ضغطنا على زر النشر ونحن نبتسم. في الدقائق الأولى، كان كل شيء مثالياً. لكن بعد حوالي ساعة، بدأت التنبيهات تنهال علينا كالمطر. “API Latency High”, “Database Connection Errors”, “503 Service Unavailable”. شعرنا وكأن الأرض انشقت وابتلعتنا. تحول مكتبنا الهادئ إلى غرفة حرب، والأصوات تتعالى: “شو اللي بصير؟”، “افحصوا خدمة الدفع!”، “اعملوا Rollback بسرعة!”.
بعد ساعات من التوتر والبحث المحموم، اكتشفنا المشكلة. لم تكن في الكود الذي كتبناه مباشرةً، بل في خدمة ثانوية غير مهمة ظاهرياً، خدمة صغيرة مسؤولة عن “اقتراح منتجات مشابهة”. هذه الخدمة كانت تعتمد على واجهة برمجية (API) لجهة خارجية، وهذه الجهة الخارجية شهدت بطئاً مفاجئاً. الكود الخاص بنا، للأسف، لم يكن يحتوي على مهلة زمنية (timeout) مناسبة عند استدعاء هذه الخدمة. والنتيجة؟ كل طلب للصفحة الرئيسية كان ينتظر هذه الخدمة البطيئة حتى ينهار، مما أدى إلى استنفاد كل اتصالات قاعدة البيانات وتسبب في انهيار النظام بأكمله. ورطنا ورطة كبيرة بسبب تفصيل صغير لم يخطر على بالنا.
في ذلك اليوم، أدركت حقيقة مؤلمة: كل اختباراتنا كانت تبحث عن المشاكل التي *نتوقعها*. لكن ماذا عن المشاكل التي لا نتوقعها أبداً؟ هنا بدأت رحلتي مع مفهوم غيّر طريقة تفكيري في بناء البرمجيات إلى الأبد: **هندسة الفوضى (Chaos Engineering)**.
ما هي هندسة الفوضى؟ ليست مجرد تخريب عشوائي
عندما يسمع الناس مصطلح “هندسة الفوضى”، قد يتخيلون مبرمجاً مجنوناً يقطع كابلات الشبكة في مركز البيانات بشكل عشوائي. الحقيقة أبعد ما تكون عن ذلك. هندسة الفوضى هي **تخصص علمي يهدف إلى إجراء تجارب مدروسة على نظامك لاكتساب الثقة في قدرته على الصمود في وجه الظروف الصعبة وغير المتوقعة في بيئة الإنتاج.**
فكر فيها كأنها لقاح لنظامك. أنت تحقن النظام بفشل صغير ومسيطر عليه (مثل إبطاء الشبكة أو إيقاف خادم واحد) لترى كيف يتفاعل جهاز “المناعة” الخاص به (آليات الصمود مثل إعادة المحاولة، أو الـ Fallbacks). الهدف ليس كسر النظام، بل الكشف عن نقاط الضعف الخفية في بيئة محكومة قبل أن يكشفها المستخدمون في بيئة حقيقية وفوضوية.
“هندسة الفوضى لا تسبب المشاكل، بل تكشف عن المشاكل الموجودة أصلاً.”
لماذا لا تكفي الاختبارات التقليدية وحدها؟
القصة التي رويتها لكم هي خير دليل. لكن دعونا نفصّل الأسباب التي تجعل الاختبارات التقليدية غير كافية للأنظمة الحديثة والمعقدة (Microservices, Cloud-native applications).
1. اختبارات الوحدة والتكامل محدودة النطاق
هذه الاختبارات ممتازة للتأكد من أن قطعة صغيرة من الكود تعمل كما هو متوقع، أو أن خدمتين تتواصلان بشكل صحيح في بيئة مثالية. لكنها لا تستطيع محاكاة الظروف المعقدة التي تحدث في نظام موزع يتكون من عشرات أو مئات الخدمات، حيث يمكن لفشل صغير في مكان واحد أن يسبب سلسلة من الإخفاقات (Cascading Failures) في أماكن أخرى.
2. اختبارات التحميل تركز على “المسار السعيد”
اختبارات التحميل تجيب على سؤال: “هل يمكن لنظامنا التعامل مع عدد كبير من المستخدمين عندما يكون كل شيء يعمل بشكل جيد؟”. لكنها نادراً ما تجيب على سؤال أهم: “ماذا يحدث عندما يتعامل نظامنا مع عدد طبيعي من المستخدمين ولكن خدمة حيوية (مثل قاعدة البيانات أو بوابة الدفع) أصبحت بطيئة أو غير متاحة؟”.
3. بيئة الاختبار (Staging) ليست كالإنتاج (Production)
مهما حاولت، لن تكون بيئة الاختبار نسخة طبق الأصل عن بيئة الإنتاج. بيئة الإنتاج فوضوية، تتعرض لتقلبات في الشبكة، فشل في الأجهزة، تحديثات غير متوقعة، وسلوك مستخدمين لا يمكن التنبؤ به. هندسة الفوضى تسمح لك بإحضار هذه “الفوضى” إلى بيئة خاضعة للرقابة واختبار نظامك ضدها.
كيف بدأت رحلتي مع هندسة الفوضى: خطوات عملية
بعد تلك الحادثة، قررنا في الفريق تبني هندسة الفوضى بشكل تدريجي. لم يكن الأمر سهلاً في البداية، فقد كان هناك خوف طبيعي من “كسر” شيء ما عمداً. لكن باتباع منهجية واضحة، تمكنا من بناء الثقة وتحقيق نتائج مذهلة. إليكم الخطوات التي اتبعناها:
الخطوة الأولى: تحديد “الحالة المستقرة” (Define Steady State)
قبل أن تُحدث أي فوضى، يجب أن تعرف كيف يبدو “الوضع الطبيعي” لنظامك. هذه هي القاعدة التي ستقيس عليها تأثير تجربتك. بالنسبة لنا، كانت المقاييس الرئيسية هي:
- معدل نجاح الطلبات (Success Rate): يجب أن يكون أعلى من 99.9%.
- زمن استجابة الواجهات البرمجية (API Latency): يجب أن يكون P99 (النسبة المئوية 99) أقل من 300 ميللي ثانية.
- مؤشرات العمل (Business Metrics): عدد الطلبات المكتملة في الدقيقة يجب أن يبقى ضمن نطاق معين.
الخطوة الثانية: صياغة الفرضية (Form a Hypothesis)
هنا تضع افتراضاً واضحاً حول ما تعتقد أنه سيحدث. الفرضية الجيدة تكون على هذا النحو: “نحن نفترض أنه حتى لو حدث [فشل معين]، فإن [مقياس الحالة المستقرة] سيبقى ضمن حدوده الطبيعية”.
مثال على فرضيتنا الأولى: “نفترض أنه إذا قمنا بزيادة استهلاك وحدة المعالجة المركزية (CPU) إلى 90% على حاويات (containers) خدمة التوصيات، فإن الصفحة الرئيسية ستظل تعمل بشكل طبيعي، وستختفي فقط جزئية المنتجات الموصى بها، ولن يتأثر معدل نجاح الطلبات العام.”
الخطوة الثالثة: تصميم وتنفيذ التجربة (Run the Experiment)
هنا يبدأ المرح الحقيقي. الهدف هو محاكاة الفشل الذي وصفته في فرضيتك. من المهم جداً أن تبدأ بنطاق محدود جداً لتقليل أي مخاطر محتملة (Minimize the Blast Radius).
في مثالنا، أردنا زيادة استهلاك الـ CPU. بما أننا نستخدم Kubernetes، يمكننا استخدام أدوات مثل stress-ng لتنفيذ ذلك على Pod واحد فقط.
# مثال على تنفيذ التجربة باستخدام kubectl
# أولاً، ابحث عن اسم الـ Pod الخاص بخدمة التوصيات
$ kubectl get pods -l app=recommendation-service
# NAME READY STATUS RESTARTS AGE
# recommendation-service-5f7b9c9c4-abcde 1/1 Running 0 24h
# ثانياً، نفذ أمر stress داخل الـ Pod لزيادة حمل الـ CPU لمدة 60 ثانية
$ kubectl exec recommendation-service-5f7b9c9c4-abcde --
stress-ng --cpu 1 --cpu-load 95 --timeout 60s
خلال هذه الـ 60 ثانية، كنا نراقب لوحات المعلومات (Dashboards) التي تعرض مقاييس الحالة المستقرة التي حددناها في الخطوة الأولى.
الخطوة الرابعة: التحقق من النتائج والتعلم (Verify and Learn)
هذه هي لحظة الحقيقة. هل تطابقت النتائج مع فرضيتك؟
في تجربتنا الأولى تلك، لم تكن النتيجة كما توقعنا تماماً. صحيح أن الصفحة الرئيسية لم تنهار، لكننا لاحظنا زيادة طفيفة (حوالي 50 ميللي ثانية) في زمن استجابة الصفحة الرئيسية بالكامل. بعد التحقيق، اكتشفنا أن الواجهة الأمامية (Frontend) كانت تنتظر 100 ميللي ثانية كـ timeout قبل أن تتجاوز خدمة التوصيات. هذا لم يكن خطيراً، لكنه كشف لنا ضعفاً لم نكن على علم به. قمنا على الفور بتعديل الكود ليكون الـ timeout أقرب إلى الصفر (Fail Fast) وعرضنا رسالة “جاري تحميل التوصيات” بدلاً من الانتظار.
قمنا بتوثيق هذه النتيجة، وأصلحنا المشكلة، ثم أعدنا التجربة للتأكد من أن الإصلاح يعمل كما هو متوقع. لقد حولنا “فشلاً” محتملاً إلى فرصة لتحسين النظام.
أدوات تساعدك في رحلتك
لست بحاجة إلى بناء كل شيء من الصفر. هناك العديد من الأدوات الرائعة التي يمكن أن تساعدك في تطبيق هندسة الفوضى:
- Chaos Mesh: مشروع مفتوح المصدر تابع لـ CNCF، وهو قوي جداً وسهل الاستخدام في بيئات Kubernetes. يسمح لك بمحاكاة فشل الـ Pods، وتأخير الشبكة، وأكثر من ذلك.
- LitmusChaos: مشروع آخر من CNCF، يوفر مجموعة كبيرة من التجارب الجاهزة ومنصة لإدارة وتنظيم تجارب الفوضى.
- Gremlin: منصة تجارية قوية جداً (Failure-as-a-Service)، توفر واجهة سهلة الاستخدام ومجموعة واسعة من الهجمات المنظمة.
- AWS Fault Injection Simulator (FIS): إذا كنت تستخدم AWS بكثافة، فهذه الخدمة تسمح لك بتصميم وتنفيذ تجارب الفوضى على موارد AWS الخاصة بك مباشرة.
نصائح من قلب الميدان
من خلال تجربتي، تعلمت بعض الدروس التي أود مشاركتها معكم:
- ابدأ صغيراً وفي بيئة آمنة: لا تقفز مباشرة إلى بيئة الإنتاج. قم بتجاربك الأولى على بيئة التطوير أو الاختبار (Staging) لتتعلم أنت وفريقك كيفية عمل الأداة وتفسير النتائج.
- قلّل “نصف قطر الانفجار” (Blast Radius): عند الانتقال إلى الإنتاج، ابدأ بأصغر نطاق ممكن. استهدف نسبة صغيرة جداً من المستخدمين، أو خدمة داخلية غير حرجة، أو خادماً واحداً من بين عشرات الخوادم.
- الأتمتة هي المفتاح: لا تجعل تجارب الفوضى حدثاً يدوياً نادراً. قم بدمجها في خط أنابيب التكامل والنشر المستمر (CI/CD Pipeline) لتشغيلها بانتظام. هذا يضمن أن نظامك يظل مرناً مع كل تغيير جديد.
- نظّم “أيام اللعبة” (Game Days): خصص يوماً كل بضعة أشهر لمحاكاة سيناريو فشل كبير (مثل انقطاع منطقة توافر كاملة – Availability Zone). اجعل الفريق بأكمله يشارك في الاستجابة للحدث. هذا لا يختبر التكنولوجيا فحسب، بل يختبر أيضاً عمليات التواصل والاستجابة لدى فريقك.
- التركيز على التعلم، وليس اللوم: الهدف من هندسة الفوضى هو الكشف عن نقاط ضعف النظام، وليس إلقاء اللوم على المطور الذي كتب الكود. عزز ثقافة “اللوم الصفري” (Blameless Culture) التي تشجع على الشفافية والتعلم من الأخطاء.
الخلاصة: كن أنت مصدر الفوضى المتحكم بها
الأنظمة الحديثة معقدة بطبيعتها، والفشل ليس احتمالاً، بل هو حتمية. السؤال ليس “هل سيفشل نظامك؟”، بل “متى سيفشل، وكيف ستستجيب له؟”.
هندسة الفوضى تقلب المعادلة. بدلاً من انتظار الفشل ليحدث لك في أسوأ وقت ممكن، أنت تبادر وتصنع فشلاً صغيراً ومتحكماً به في الوقت الذي تختاره أنت، وبالطريقة التي تختارها أنت. كل تجربة فوضى ناجحة هي درس قيم يجعلك أنت وفريقك ونظامك أكثر استعداداً وثقة لمواجهة المجهول.
لا تنتظر الكارثة لتختبر صلابة قاربك. ابدأ اليوم، ولو بخطوة بسيطة، وحاول إغراق قاربك بنفسك في مياه ضحلة. فكل “فوضى” منظمة هي خطوة نحو بناء أنظمة لا تُقهر. 💪