سجل الخدمات مع Eureka
سجل الخدمات مع Eureka
في الدرس السابق رأيت سبب انهيار نهج ترميز عناوين الخدمات بمجرد تشغيل أكثر من نسخة واحدة من أي شيء. سجل الخدمات هو الحل: مخزن مركزي تُعلن فيه كل نسخة خدمة عن وجودها عند الإقلاع، وتُلغي تسجيلها عند الإيقاف. يمكن لأي مُستدعٍ بعد ذلك أن يطلب من السجل عنوانًا حيًا بدلًا من أن يكون مُضمَّنًا في ملف إعداد.
يأتي Spring Cloud بدعم متكامل لـ Netflix Eureka الذي اختُبر في بيئات إنتاج واسعة النطاق. يتبع Eureka نموذجًا بسيطًا: Eureka Server مخصص يحتضن السجل، وتُشغّل كل خدمة مصغرة Eureka Client يُسجّل نفسه ويجدد النبضة القلبية ويسترجع السجل لاستخدامه في موازنة الحمل من جانب العميل.
تشغيل Eureka Server
أنشئ مشروع Spring Boot 3 جديدًا وأضف تبعيتين:
ثم أضف التعليق التوضيحي @EnableEurekaServer على الفئة الرئيسية:
يحتاج الخادم إلى application.yml بسيط يُخبره بعدم تسجيل نفسه لدى ذاته (فهو السجل وليس عميلًا):
شغّل الخادم وافتح http://localhost:8761. ستظهر لوحة تحكم Eureka — فارغة حاليًا وجاهزة لاستقبال التسجيلات.
eureka.client.service-url في بيئة التطوير، مما يزيل فئة كاملة من أخطاء الإعداد.
تسجيل خدمة: عميل Eureka
تُضيف كل خدمة تريد أن تكون قابلة للاكتشاف تبعية عميل Eureka:
لا حاجة لأي تعليق توضيحي في Spring Boot 3 / Spring Cloud 2023 — وجود المُبدّئ في مسار الفئات يُنشّط الإعداد التلقائي. كل ما تحتاجه هو اسم الخدمة في application.yml:
شغّل هذه الخدمة وأعد تحميل لوحة تحكم Eureka. ستجد ORDER-SERVICE ظاهرة في جدول "Instances currently registered with Eureka" مع عنوان IP والمنفذ والحالة UP.
ما يحدث عند التسجيل
عند بدء تشغيل عميل Eureka يُرسل طلب HTTP من نوع POST إلى /eureka/apps/{appName} على الخادم، حاملًا حمولة JSON تسمى InstanceInfo. تحتوي على:
- اسم التطبيق (
order-serviceبأحرف كبيرة) - المضيف والمنفذ
- عنوان URL لفحص الصحة (يُعيَّن افتراضيًا لنقطة نهاية Actuator
/actuator/healthإن وُجدت) - الحالة — تبدأ بـ
STARTINGثم تصبحUPفور جهوزية السياق - خريطة بيانات وصفية — أزواج مفتاح/قيمة عشوائية يمكن استخدامها لتلميحات التوجيه
بعد التسجيل يُرسل العميل نبضة قلبية (PUT) لتجديد العقد كل lease-renewal-interval-in-seconds ثانية. إذا لم يتلقَّ الخادم أي تجديد خلال lease-expiration-duration-in-seconds ثانية يُعلّم النسخة بـ DOWN ثم يحذفها في النهاية.
اكتشاف الخدمات برمجيًا
بمجرد تسجيل خدمة، يمكن لأي عميل Eureka آخر في المجموعة ذاتها تحليل عنوانها بالاسم. أبسط طريقة هي DiscoveryClient الذي يُحقنه Spring:
يُعيد استدعاء getInstances() جميع النسخ الحية المسجّلة تحت ذلك الاسم. عنوان URI مُجمَّع بالكامل من بيانات النسخة الوصفية. من الناحية العملية نادرًا ما تستدعي DiscoveryClient مباشرةً — بل تترك لـ Spring Cloud LoadBalancer (الدرس القادم) اختيار النسخة — لكن فهم هذه الواجهة البرمجية الخام ضروري للتنقيح وللمنطق المخصص للتوجيه.
اعتبارات أمنية للسجل
لوحة تحكم Eureka وواجهة REST البرمجية غير مصادَق عليهما بشكل افتراضي. في أي بيئة يمكن فيها الوصول إلى السجل من شبكات غير موثوقة يُعدّ هذا خطأ إعداد حرجًا: يمكن لعميل خبيث تسجيل نسخة مزيفة وإعادة توجيه الحركة إليها (هجوم انتحال هوية خدمة).
الإجراء الوقائي المعياري هو إضافة Spring Security لمشروع Eureka Server وطلب مصادقة HTTP Basic، ثم تضمين بيانات الاعتماد في عناوين URL للعملاء:
وضع الحفاظ الذاتي
يمتلك Eureka آلية مدمجة تُسمى وضع الحفاظ الذاتي (self-preservation mode). إذا توقف الخادم عن تلقي تجديدات من نسبة كبيرة من النسخ المسجّلة (تتجاوز عتبة قابلة للإعداد)، يفترض وجود تجزئة في الشبكة لا أن تلك الخدمات انهارت جميعًا، ويوقف حذف النسخ. هذا يحفظ مدخلات قديمة لكنها ربما لا تزال حية بدلًا من إفراغ السجل أثناء اضطراب الشبكة.
وضع الحفاظ الذاتي مناسب للإنتاج لكنه قد يُربك في التطوير حيث يُفترض أن إيقاف خدمة يزيلها فورًا. يمكنك تعطيله لكل بيئة على حدة:
الخلاصة
خادم Eureka هو تطبيق Spring Boot مُعلَّق بـ @EnableEurekaServer. تضيف كل خدمة عميلة المُبدّئ وتضبط spring.application.name؛ والتسجيل والنبضات القلبية تلقائيان. تكتشف الخدمات الأخرى النسخ الحية بالاسم عبر DiscoveryClient أو عمليًا من خلال Spring Cloud LoadBalancer. أمّن نقطة نهاية السجل دائمًا ببيانات اعتماد وTLS في أي بيئة غير محلية، وافهم وضع الحفاظ الذاتي كيلا يفاجئك أثناء الحوادث.