التوسّع وموازنة الأحمال

فحوصات الصحة والتعافي من الأعطال

18 دقيقة الدرس 5 من 10

فحوصات الصحة والتعافي من الأعطال

إضافة المزيد من الخوادم تحل مشكلة الطاقة الاستيعابية، لكنها تطرح فوراً سؤالاً أصعب: كيف يعرف موزع الحمل أي الخوادم جاهزة فعلاً لخدمة حركة المرور؟ عملية متعطلة، أو تطبيق استنفد ذاكرته، أو مجموعة اتصالات قاعدة البيانات التي نفدت، أو خيط تنفيذ متوقف — كل هذه الحالات تُبقي الخادم "يعمل" على مستوى الشبكة بينما هو عاجز تماماً عن خدمة الطلبات. بدون آلية منهجية لاكتشاف هذه الأعطال والتحويل حولها، سيستمر موزع الحمل في إرسال حركة المرور إلى فراغ، وسيرى مستخدموك أخطاء متتالية.

فحوصات الصحة والتعافي من الأعطال هي الآليات التي تحوّل مجموعة من الخوادم المستقلة إلى مجموعة تتعافى ذاتياً. وهي العمود الفقري التشغيلي لأي نظام عالي التوفر.

ما الذي يفحصه فحص الصحة فعلاً؟

ثمة ثلاثة مستويات من فحوصات الصحة تتصاعد في العمق، واختيار المستوى المناسب قرار تصميمي متعمد:

  • المستوى الأول — فحص TCP / Ping: هل يمكننا فتح اتصال TCP على المنفذ 8080؟ هذا يخبرك أن نظام التشغيل حي والعملية تستمع. لكنه لا يقول شيئاً عن قدرة التطبيق على معالجة الطلبات فعلياً. معدل الإنذار الكاذب: مرتفع.
  • المستوى الثاني — فحص حالة HTTP: هل يُعيد GET /health استجابة HTTP 200؟ هذا يخبرك أن خادم الويب يستجيب. لكنه لا يخبرك عن إمكانية الوصول إلى التبعيات المصبّية (قاعدة البيانات، الذاكرة المؤقتة، قائمة الانتظار). معدل الإنذار الكاذب: متوسط.
  • المستوى الثالث — الفحص العميق / فحص التبعيات: هل يُعيد GET /health/ready استجابة 200 ويتحقق أيضاً من حيوية اتصال قاعدة البيانات وإمكانية الوصول إلى الذاكرة المؤقتة وعمل قائمة الانتظار؟ هذا أدق إشارة للجاهزية الفعلية، لكنه يضيف كموناً للفحص نفسه وقد يتسبب في موجة من حركة مرور الفحص تحت الضغط.
الحيوية مقابل الجاهزية (مصطلحات Kubernetes، مفيدة على نطاق واسع): مسبار الحيوية يجيب عن "هل هذه العملية حية أساساً؟ هل يجب إعادة تشغيلها؟" أما مسبار الجاهزية فيجيب عن "هل هذا المثيل جاهز لاستقبال حركة المرور الآن؟" هذان سؤالان مختلفان. يمكن لخادم أن يكون حياً (لا يجب إيقافه) لكن غير جاهز (يجب إزالته من مجموعة موزع الحمل لأنه لا يزال يسخّن ذاكرته المؤقتة).

معاملات تكوين فحص الصحة

كل موزع حمل يعرض على الأقل هذه المعاملات الأربعة، وضبطها بشكل صحيح يصنع الفارق بين نظام يتعافى في 5 ثوانٍ وآخر يحتاج 3 دقائق:

  • الفاصل الزمني (Interval) — مدة تكرار المسبار. النموذجي: 5–15 ثانية. أقصر = اكتشاف أسرع، لكن حركة مرور فحص أكبر.
  • المهلة (Timeout) — مدة الانتظار للاستجابة قبل احتساب الفشل. النموذجي: 2–5 ثوانٍ. يجب أن تكون أقل من الفاصل الزمني.
  • عتبة عدم الصحة (Unhealthy threshold) — عدد الإخفاقات المتتالية قبل إزالة المثيل من التدوير. النموذجي: 2–3. عتبة 1 تسبب تذبذباً عند حدوث اضطرابات شبكية عابرة.
  • عتبة الصحة (Healthy threshold) — عدد النجاحات المتتالية قبل إعادة إضافة مثيل متعافٍ للتدوير. النموذجي: 2–3. هذا يمنع إعادة إضافة مثيل نجح عشوائياً في فحص واحد أثناء حالة متدهورة.
مثال ضبط عملي: الإعدادات الافتراضية لـAWS Application Load Balancer — فاصل 30 ثانية، مهلة 5 ثوانٍ، عتبة غير صحية 2، عتبة صحية 5. بهذه الإعدادات، يستغرق الاكتشاف 60 ثانية والتعافي 150 ثانية. لواجهة برمجية حساسة للكمون، شدد الإعدادات إلى فاصل 10 ثوانٍ / مهلة 3 ثوانٍ / عتبات 2/2 لتقليل نافذة الاكتشاف إلى ~20 ثانية.
Health check cycle: detection and removal from pool Load Balancer health probe every 10 s Server A HTTP 200 IN POOL Server B timeout × 2 FAILING Server C REMOVED FROM POOL probe probe probe 200 OK no response traffic no traffic Detection timeline with interval=10s, timeout=3s, unhealthy threshold=2 t=0: first failure → t=10s: second failure → t=13s (timeout): removed from pool → worst-case ~23s to detect Recovery: 2 consecutive 200s required → re-added after ~20s of clean responses
دورة مسبار الصحة: يقوم موزع الحمل بفحص جميع الخوادم بفاصل زمني ثابت؛ الخوادم التي تتجاوز عتبة الفشل تُزال من المجموعة وتُعاد توزيع حركة المرور.

فحوصات الصحة السلبية مقابل النشطة

ثمة استراتيجيتان متكاملتان لاكتشاف الأعطال، وأنظمة الإنتاج تستخدم كلتيهما:

الفحوصات النشطة (استباقية): يبادر موزع الحمل بإرسال طلب مسبار مخصص لكل خادم خلفي وفق جدول زمني. ميزتها أنك تكتشف الأعطال حتى عند غياب حركة المرور الحقيقية. عيبها أن نقطة نهاية الصحة يجب أن تكون خفيفة — فحص تبعيات ثقيل كل 5 ثوانٍ على 50 خادماً يولّد حملاً كبيراً.

الفحوصات السلبية (تفاعلية): يراقب موزع الحمل استجابات الطلبات الحقيقية أثناء مرورها. إذا أعاد خادم ما أخطاء 5xx أو انتهت مهلته في N طلبات متتالية، يُعلَّم على أنه غير صحي. ميزتها عدم توليد حركة مرور إضافية. عيبها أنها لا تُشغَّل إلا عند تعرض المستخدمين الحقيقيين لأخطاء — لا يمكنك اكتشاف العطل قبل أن يصطدم به المستخدمون.

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

الإغلاق السلس وتفريغ الاتصالات

إزالة خادم من المجموعة أثناء نشر متداول أو حدث تقليص يمثل سيناريو فشل مقنّع. إذا أوقف موزع الحمل إرسال الاتصالات الجديدة في اللحظة التي يتلقى فيها إشارة الإغلاق، فإن الطلبات الجارية — التي قد تستغرق 0.5 إلى 30 ثانية — ستُقطع فجأة. يرى المستخدمون أخطاء ليس لها علاقة بالبق في كودك.

الحل هو تفريغ الاتصالات (تسميه AWS "تأخير إلغاء التسجيل"؛ وNGINX يسميه proxy_next_upstream). التسلسل هو:

  1. يُشير المثيل إلى أنه يغلق (SIGTERM، أو نقطة نهاية الصحة تُعيد 503).
  2. يوقف موزع الحمل توجيه الطلبات الجديدة لذلك المثيل.
  3. ينتظر موزع الحمل حتى مهلة تفريغ قابلة للتكوين (عادةً 30–90 ثانية) حتى تكتمل الطلبات الجارية.
  4. بعد انتهاء المهلة، تُغلق أي اتصالات متبقية قسراً ويُلغى تسجيل المثيل.

التعافي من الأعطال: التلقائي مقابل اليدوي

عند فشل خادم ما، يجب إعادة توزيع حركة المرور. هذه إعادة التوزيع هي التعافي من الأعطال، وتحدث على مستويين:

التعافي على مستوى المثيل يتم تلقائياً بواسطة موزع الحمل. عند إزالة الخادم C من المجموعة، تُعاد توزيع حصته من وزن الاتصالات على الخوادم السليمة المتبقية. يحدث هذا في غضون ثوانٍ ولا يتطلب أي تدخل بشري. الخطر هو الفشل المتتالي: إذا كانت الخوادم A وB تعملان بالفعل عند طاقة 70%، فإن استيعاب حركة مرور C ترفعهما إلى 105% — وتبدآن بالفشل هي أيضاً.

التعافي على مستوى المنطقة/الإقليم يتعامل مع الحالة التي يصبح فيها منطقة توفر كاملة أو مركز بيانات كاملاً غير متاح. Route 53 وموزعات الحمل العالمية الأخرى تدعم تحويل الفشل المستند إلى فحص الصحة عبر DNS: إذا فشل نقطة النهاية الأساسية في فحصها، يُحدَّث DNS تلقائياً للإشارة إلى المنطقة الثانوية. يجب تعيين TTL لـ DNS منخفضاً (60–120 ثانية) ليكون هذا فعّالاً — TTL بمقدار 300 ثانية يعني 5 دقائق من الأعطال قبل أن يرى العملاء السجل المحدَّث.

Cascading failure scenario vs. capacity-aware failover Cascading Failure Risk Load Balancer distributes evenly Server A 70% CPU Server B 70% CPU Server C FAILED C fails: A and B absorb extra load, hit 105%, cascade! Server A OVERLOADED Server B OVERLOADED Capacity-Aware Failover Load Balancer + Auto-Scaling trigger Server A 40% CPU Server B 40% CPU C fails: Auto-Scaler adds Server D in 90s Server A 60% CPU — OK Server B 60% CPU — OK Server D new — warming up
يسار: مجموعة تعمل عند 70% سعة تنهار عند فشل عقدة واحدة. يمين: مجموعة بهامش كافٍ ومع التوسع التلقائي تستوعب الفشل وتستبدل العقدة المفقودة دون إرهاق الخوادم الناجية.

قواطع الدائرة: منع موجات إعادة المحاولة

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

قاطع الدائرة آلة حالة لها ثلاث حالات:

  • مغلق (التشغيل العادي): تتدفق الطلبات بشكل طبيعي. يُحصي القاطع الإخفاقات. إذا تجاوز معدل الفشل عتبة ما (مثلاً 50% من الطلبات في نافذة 10 ثوانٍ)، تنفتح الدائرة.
  • مفتوح (الفشل السريع): جميع الاستدعاءات للخدمة المصبّية تُعيد خطأً فوراً دون إجراء أي استدعاء شبكي. هذا يمنح الخدمة المصبّية وقتاً للتعافي. بعد مهلة قابلة للتكوين (مثلاً 30 ثانية)، تدخل الدائرة في حالة نصف مفتوحة.
  • نصف مفتوح (الاختبار): يُسمح لعدد محدود من طلبات الاختبار بالمرور. إذا نجحت، تُغلق الدائرة. وإذا فشلت، تُفتح مرة أخرى.
خطأ شائع — نقطة نهاية فحص الصحة تفعل الكثير: نقطة نهاية فحص الصحة التي تستدعي بنفسها قاعدة البيانات والذاكرة المؤقتة وواجهتين خارجيتين ستفشل أحياناً بسبب اضطرابات عابرة في أي من هذه التبعيات — وستتسبب في إزالة خادمك بشكل غير صحيح من المجموعة. احرص على أن يركز فحص الجاهزية على المسار الحرج فقط: هل يمكن للتطبيق قبول الطلبات ومعالجتها؟ استخدم نقطة نهاية مراقبة منفصلة لفحوصات التبعية الكاملة التي لا تؤثر على قرار إضافة الخادم لمجموعة موزع الحمل.

المقاييس الأساسية للمراقبة

تُطلق فحوصات الصحة إنذاراتها قبل أن تصبح الأعطال مرئية للمستخدمين، لكنك تحتاج أيضاً إلى إشارات فورية لفريق العمليات:

  • نسبة صحة المثيلات: ما نسبة المثيلات التي تجتاز فحوصات الصحة حالياً؟ أطلق تنبيهاً عند أقل من 80%.
  • معدل أحداث التعافي: كم مثيلاً أُزيل من المجموعة في الساعة الأخيرة؟ معدل غير صفري في الحالة الطبيعية يُشير إلى خطأ متكرر أو تسرب ذاكرة أو تبعية خارجية تنقطع بشكل دوري.
  • متوسط وقت الاكتشاف (MTTD): كم يمر بين وقوع العطل وتحويل موزع الحمل حوله؟ هدفك يجب أن يكون أقل من 30 ثانية للخدمات المواجهة للمستخدم.
  • معدل أخطاء 5xx أثناء التعافي: بعض الأخطاء خلال نافذة الاكتشاف (قبل إزالة المثيل غير الصحي) لا مفر منها. الهدف هو تقليص هذه النافذة، لا القضاء على الأخطاء كلياً.
القاعدة الذهبية للتعافي من الأعطال: صمم على افتراض أنه في أي لحظة معينة، قد يكون ما يصل إلى 30% من مثيلاتك غير صحية، ويجب على نظامك خدمة 100% من حركة المرور. هذا يعني أنك تحتاج إلى هامش سعة لا يقل عن ~43% في مجموعتك في جميع الأوقات. عند N=10 خوادم: يمكن لـ3 أن تفشل ويجب على 7 أن تتحمل الحمل الكامل — كل منها بحصة تساوي ~143% من حصتها في الحالة الطبيعية... ما لم تخطط لـ30% من السعة الفائضة. هذه الحسبة جزء أساسي من تخطيط الطاقة الاستيعابية.

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