استعمال Circuit Breakers باش تحبس المشاكل ديال Dependency Failures
الأنظمة والمعماريةتعلم كيفاش تمنع الانهيار المتسلسل (cascading failures) في السيستيمات الموزعة باستعمال Circuit Breaker باش تحكم في الخدمات اللي مكاتجاوبش.
فهاد المقال
المشكل: الانهيار المتسلسل (Cascading Failures)
فاش كيكون عندك سيستيم موزّع، واحد السيرفيس كيحتاج يسول سيرفيس آخر باش يكمل الخدمة ديالو. تخيل مثلاً سيرفيس ديال Checkout (الخلاص) كيعيط لسيرفيس ديال Shipping Estimates (تقدير مصاريف الشحن). إلا كان سيرفيس الشحن تقيل بزاف ولا مابقاش كيجاوب (بلا ما يكون فيه timeout)، الـ worker threads ديال Checkout غادي يبقاو يتسناو. ومع الضغط، كاع الـ threads غادي يتسدوا، وهادشي كيخلي سيرفيس Checkout يطيح كامل، حتى بالنسبة للناس اللي ما محتاجينش يحسبو الشحن. هادشي هو اللي كنسميوه cascading failure.
كيفاش كيخدم الـ Circuit Breaker
الـ Circuit Breaker كيخدم بحال واحد “القاطع” بين السيرفيس اللي كيعيط والسيرفيس اللي كيتعيط ليه. كيبقى حاضي واش كاينين أخطاء وكيبدل الحالة ديالو بين تلاتة ديال الحالات:
- Closed (مسدود): هادي هي الحالة العادية. الطلبات كيدوزو عادي. الـ breaker كيحسب شحال من مرة وقع خطأ. إلا فات عدد أو نسبة الأخطاء واحد الحد (مثلاً 5 ديال الأخطاء أو 50% من آخر 100 طلب)، الـ breaker كيتحول للحالة Open.
- Open (محلول): هنا الـ breaker كيقطع الطريق ومكيبقاش يصيفط حتى طلب للسيرفيس اللي طايح. كيرجع جواب ديال خطأ أو جواب بديل (fallback) ديك الساعة. هادشي كيخلي السيرفيس ديالنا ما يضيعش الوقت والـ threads، وكيعطي الوقت للسيرفيس اللي طايح باش يرجع يخدم.
- Half-Open (نص محلول): من بعد واحد الوقت محدد (sleep window)، الـ breaker كيسمح لواحد العدد قليل ديال الطلبات (probes) باش يدوزو. إلا نجحو، كيرجع الحالة لـ Closed. وإلا فشل غير واحد منهم، كيرجع فوراً لـ Open.
العلاقة مع Timeouts و Retries
الـ Circuit Breaker ماشي بديل لـ timeouts أو retries، ولكن كيكملهم:
- Timeouts: ضروريين باش الـ threads ما يبقاوش يتسناو للأبد. الـ timeout هو اللي كيعلم الـ Circuit Breaker بلي كاين خطأ باش يبدا يحسب.
- Retries: إلا بقيتي كتعاود الطلب (retry) لسيرفيس طايح، غادي تزيد تضغط عليه وتطيحو كتر (retry storm). الـ Circuit Breaker كيمنع هادشي حيت كيقطع الطريق (Open) حتى كيتأكد بلي السيرفيس رجع خدام.
مثال تطبيقي: Checkout → Shipping
تخيل سيرفيس الشحن فيه مشكل. درنا Circuit Breaker بـ threshold ديال 3 ديال الأخطاء و sleep window ديال 5 ثواني.
شنو كيوقع (Trace):
- الطلبات 1-3: سيرفيس الشحن مكيجاوبش (timeout). الـ breaker سجل 3 ديال الأخطاء. الحالة: Closed → Open.
- الطلبات 4-10: الـ breaker لقى الحالة Open. كيرجع فوراً
FallbackShippingEstimate(مثلاً ثمن ثابت ديال 10 دراهم) بلا ما يعيط لسيرفيس الشحن. الـ threads كيتحررو بسرعة. - انتظار: دازت 5 ثواني.
- الطلب 11: الحالة كتولي Half-Open. الـ breaker كيسمح لطلب واحد يدوز لسيرفيس الشحن.
- النتيجة A: الطلب 11 فشل → الحالة كترجع Open. التوقيت كيبدا من جديد.
- النتيجة B: الطلب 11 نجح → الحالة كترجع Closed. الخدمة كترجع عادية.
جودة الـ Fallback والمدى ديالو
الـ fallback هو الكود اللي كيتنفذ فاش كيكون السيرفيس طايح (Open). الجودة ديالو هي اللي كتحدد تجربة المستخدم:
- Static Fallback: ترجع قيمة ثابتة (مثلاً: “مصاريف الشحن غتحسب فالمرحلة الجاية”).
- Cached Fallback: ترجع آخر قيمة كانت خدامة من واحد الـ cache محلي.
- Degraded Functionality: تحيد ديك الميزة كاملة ولكن تخلي المستخدم يكمل العملية ديالو.
تمرين
حدد policy قبل الحساب: toy breaker هنا كتفتح من5 failures فـ window ديال10 calls، success ما كتصفّرش count وopen interval10ثواني. أربع failures وsuccess ومن بعد جوج failures كتدوز threshold فالأولى ديال آخر جوج؛ الأخرى كتترفض وهي open. بعد الانتظار probe half-open وحدة كتفشل وكتعاود تفتح.
Policy ديال5 failures متتالين كتعطي جواب آخر حيت success كتصفّر count. Libraries يقدرو يستعملو rates وminimum samples وslow calls وprobes بزاف. حدد timeout/retry order؛ breaker ما كتلغيش hanging call بوحدها وما كتضمنش غياب retry amplification. Shipping fallback خليها estimation ماشي quote ملزمة مخترعة وقت outage.