نمط قاطع الدائرة
نمط قاطع الدائرة
في الأنظمة الموزّعة، يمكن أن تفشل الاستدعاءات البعيدة. فقد تكون الخدمة الفرعية بطيئة أو غير متاحة أو تُعيد أخطاء. وبدون آلية حماية، يمكن لتبعية واحدة معطوبة أن تُولّد انهيارًا متسلسلًا: تتراكم الخيوط في انتظار مهلة الاتصال، وينضب مجمّع الخيوط، وتتوقف خدمتك أيضًا — رغم أنّ كودك كان سليمًا تمامًا. قاطع الدائرة (Circuit Breaker) هو الحل المعياري لهذه المشكلة.
كيف يعمل قاطع الدائرة
يُغلّف قاطع الدائرة استدعاءً بعيدًا ويتتبّع نتائجه. يعمل في ثلاث حالات:
- CLOSED (مغلق) — حالة التشغيل الطبيعية. تمرّ الاستدعاءات كما هي. يَعُدّ القاطع الإخفاقات ضمن نافذة منزلقة.
- OPEN (مفتوح) — تمّ تجاوز عتبة الإخفاق. يرفض القاطع جميع الاستدعاءات فورًا بإلقاء
CallNotPermittedExceptionدون أي محاولة لاستدعاء الخدمة الفرعية، مما يمنح النظام الفرعي وقتًا للتعافي. - HALF_OPEN (مفتوح جزئيًا) — بعد مدّة انتظار قابلة للضبط، يسمح القاطع بمرور عدد محدود من الاستدعاءات الاستطلاعية. إن نجحت، عاد إلى CLOSED؛ وإن فشلت، عاد إلى OPEN.
Resilience4j: الخيار الحديث في Java
Netflix Hystrix، الذي كان المعيار يومًا، أصبح في وضع الصيانة. Resilience4j هو خلفه الخفيف الوزن والوظيفي، مصمَّم لـ Java 8+ بدون أي تبعيات خارجية. توفّر Spring Cloud CircuitBreaker طبقة تجريد، لكن من الشائع والمقبول استخدام تعليقات Resilience4j وإعداداته مباشرةً في تطبيق Spring Boot 3 — وهذا ما سنفعله هنا.
أضف المُبدِّئ إلى ملف pom.xml:
إعداد قاطع الدائرة
تُضبط قواطع الدائرة بالاسم في ملف application.yml. كل اسم يقابل طريقة أو أكثر مُعلَّقة في كودك.
slidingWindowSize بعناية. نافذة بحجم 5 تفتح القاطع بعد 3 إخفاقات فحسب — وهذا مفرط الحساسية لخدمة تتعرّض لدفعات من الأخطاء المشروعة. نافذة بحجم 100 تجعل القاطع بطيء التفاعل. لمعظم الخدمات، تُعدّ القيمة 10-20 مع عتبة 50% نقطة بداية معقولة.
تطبيق التعليق التوضيحي
ضع التعليق على الطريقة التي تُنجز الاستدعاء البعيد. يجب أن يطابق name مفتاح المثيل في ملف YAML. يُستدعى fallbackMethod عند فتح القاطع أو عند إلقاء أي استثناء مُسجَّل.
Throwable كمعامل أخير. إن لم تتطابق التواقيع، تجاهل Resilience4j الاحتياط صامتًا وأعاد رمي الاستثناء — وهو أمر مُحيّر لتصحيح الأخطاء.
انتقالات الحالة في الممارسة
ينشر Resilience4j أحداث قاطع الدائرة يمكنك الاشتراك بها للتسجيل أو المقاييس. في Spring Boot، تُعرض الأحداث تلقائيًا على نقطة نهاية /actuator/circuitbreakers عند وجود spring-boot-starter-actuator.
الأمان ومقايضات الأنظمة الموزّعة
لقواطع الدائرة تداعيات أمنية مهمة يسهل إغفالها:
- خطر تجاوز المصادقة: يجب ألّا يتجاوز الاحتياط الذي يُعيد استجابة متساهلة أو فارغة عمليات التحقق من التفويض. إن أعاد احتياطك "تمّت الدفعة" بصمت عند توقّف الخدمة الحقيقية، فقد يستغل المهاجم هذا التوقف. يجب أن تُعيد الاحتياطات حالات فشل آمنة وصريحة — لا نجاحًا صامتًا.
- تسريب المعلومات: لا ينبغي إيصال
CallNotPermittedExceptionورسالتها إلى عميل الـ API. تَرجَمها في طبقة المتحكّم (controller) إلى استجابة 503 عامة. - الاتساق: قد يترك قاطع مفتوح يرفض عمليات الكتابة فيما تتعافى الخدمة الفرعية قاعدة بياناتك في حالة ملتزَمة جزئيًا. صمّم احتياطك مع وضع التبادلية (idempotency) والمعاملات التعويضية في الحسبان.
RestClient أو عميل Feign لتحديد مدّة انتظار استدعاء واحد، وقاطع دائرة لوقف الاستدعاءات حين يتراكم عدد كافٍ من الإخفاقات. يعملان على مقاييس زمنية مختلفة ويتكاملان معًا.
الخلاصة
يحمي نمط قاطع الدائرة خدمتك من الانهيارات المتسلسلة بالفشل السريع حين تكون تبعية فرعية غير صحية. ينفّذ Resilience4j هذا النمط عبر تعليق بسيط (@CircuitBreaker) وإعداد YAML مُسمّى وطريقة احتياط اختيارية. القرارات الرئيسية هي: حجم النافذة المنزلقة وعتبة معدل الإخفاق ومدة الانتظار وما يُعدّ إخفاقًا قابلًا للتسجيل. اقرن قاطع الدائرة باحتياط ذي معنى، وسجّل ناشر الأحداث للمراقبة، واعرض الحالة عبر Actuator حتى يتمكّن فريق العمليات من رؤية الصحة الفورية. يضيف الدرس القادم إعادة المحاولات والمهلات والحواجز لاستكمال مجموعة أدوات المرونة.