مشروع: إعداد خدمات مصغّرة قابلة للاكتشاف
مشروع: إعداد خدمات مصغّرة قابلة للاكتشاف
استعرضت الدروس التسعة السابقة كل طبقة من طبقات حزمة Spring Cloud بشكل مستقل: Eureka للتسجيل، وSpring Cloud Config للإعدادات المركزية، وSpring Cloud Gateway لنقطة الدخول الوحيدة. يجمع هذا الدرس الأخير كل هذه الطبقات في نظام عامل وقابل للنشر. في النهاية ستمتلك ثلاث خدمات قابلة للتشغيل — Config Server وسجل Eureka وAPI Gateway — بالإضافة إلى خدمة أعمال واحدة تسجّل نفسها مع Eureka وتجلب إعداداتها من Config Server ويمكن الوصول إليها عبر Gateway. كل شيء مُوصَّل بالطريقة التي يوصّلها فريق إنتاج فعليًا.
طبولوجيا النظام
قبل كتابة أي كود، تصوّر العمليات الأربع وترتيب بدء تشغيلها:
- Config Server — يبدأ أولًا؛ يقرأ الخصائص من مستودع Git (أو مجلد classpath محلي لأغراض المشروع). جميع الخدمات الأخرى هي عملاؤه.
- Eureka Server — يبدأ ثانيًا؛ يجلب إعداداته الخاصة من Config Server، ثم يفتح سجله للعمل. تسجّل الخدمات الأخرى نفسها هنا.
- API Gateway — يبدأ ثالثًا؛ يسجّل نفسه مع Eureka ويجلب قواعد التوجيه من Config Server. يحل عناوين الخدمات عبر Eureka عند معالجة الطلبات.
- Order Service (خدمة أعمال نموذجية) — يبدأ أخيرًا؛ يسجّل نفسه مع Eureka ويجلب ملف
application.propertiesالخاص به من Config Server. يوجّه Gateway حركة المرور الواردة إليه باستخدام معرّف خدمة Eureka، وليس بعنوان مضيف أو منفذ مكتوب بشكل ثابت.
readinessProbe) أو عبر آلية إعادة المحاولة عند الاتصال في Spring Cloud. للتشغيل المحلي، ابدأ الخدمات الأربع بالترتيب المذكور مع فاصل زمني بسيط بينها.
١. Config Server
أنشئ مشروع Spring Boot مع تبعية spring-cloud-config-server، ثم زيّن الفئة الرئيسية بالتعليق المناسب:
ملف src/main/resources/application.yml — أشر إليه نحو مجلد classpath محلي حتى يعمل المشروع بدون خادم Git بعيد:
أنشئ المجلد src/main/resources/config-repo/ وأضف ملفًا واحدًا لكل خدمة مصب. الصيغة المتبعة هي {application-name}.yml.
eureka-server.yml
api-gateway.yml
order-service.yml
spring.application.name للعميل المتصل. لا تكتب أبدًا بشكل ثابت أي خدمة تحصل على أي ملف — تعرّف الخدمة عن نفسها والخادم يقوم بالمطابقة.
٢. Eureka Server
أنشئ مشروعًا ثانيًا بتبعية spring-cloud-starter-netflix-eureka-server، وزيّن الفئة الرئيسية بـ @EnableEurekaServer، واضبط إقلاعه ليسحب من Config Server:
هذا السطر الواحد spring.config.import هو كل ما تحتاجه للإقلاع. يعترض Spring Cloud Config Client (الموجود في classpath) عملية البدء، ويتصل بـ http://localhost:8888/eureka-server/default، ويدمج الخصائص البعيدة قبل إنشاء أي Bean. ملف eureka-server.yml الذي وضعته في مستودع الإعدادات يتحكم الآن في المنفذ 8761 وعلامات السجل المستقل.
٣. API Gateway
أنشئ مشروعًا بتبعيات spring-cloud-starter-gateway وspring-cloud-starter-netflix-eureka-client وspring-cloud-starter-config. الفئة الرئيسية:
خصائص الإقلاع:
مع الإعداد discovery.locator.enabled: true (المضبوط في الملف البعيد api-gateway.yml)، ينشئ Gateway تلقائيًا مسارًا لكل خدمة مسجلة في Eureka. طلب على http://localhost:8080/order-service/api/orders يُحل بحذف بادئة معرّف الخدمة وإعادة التوجيه إلى أي نسخة من order-service يعرفها Eureka — دون الحاجة إلى تعريف مسارات يدويًا.
ReactorLoadBalancerExchangeFilterFunction المدعومة بـ Spring Cloud LoadBalancer. عندما يعيد Eureka نسخًا متعددة من order-service، يختار Gateway واحدة باستخدام استراتيجية round-robin افتراضيًا. لا Ribbon ولا كود إضافي.
٤. Order Service
خدمة REST بسيطة تقرأ قيمة إعداد وتسجّل نفسها مع Eureka:
يخبر الإعداد prefer-ip-address: true سجل Eureka بتسجيل عنوان IP للخدمة بدلًا من اسم المضيف، مما يتجنب مشاكل تحليل DNS داخل الحاويات وهو الإعداد المعياري للنشر في بيئات الحاويات.
اختبار شامل للتدخين
ابدأ العمليات الأربع بالترتيب، ثم تحقق من كل طبقة:
- صحة Config Server:
GET http://localhost:8888/order-service/default— يجب أن يعيد JSON للخصائص المدمجة. - لوحة تحكم Eureka: افتح
http://localhost:8761— يجب أن ترىAPI-GATEWAYوORDER-SERVICEمدرجَين بحالة UP. - استدعاء مباشر:
GET http://localhost:8081/api/orders— يتجاوز Gateway ويؤكد عمل الخدمة. - استدعاء عبر Gateway:
GET http://localhost:8080/order-service/api/orders— يُوجَّه عبر Eureka ويؤكد عمل الاكتشاف والتوجيه معًا. - قراءة الإعداد:
GET http://localhost:8080/order-service/api/orders/config— يجب أن يعيد{"maxPerCustomer": 10}مما يثبت أن القيمة جاءت من Config Server.
اعتبارات الأمان
يحتاج الإعداد الإنتاجي إلى عدة خطوات تصليب يتعمّد هيكل المشروع هذا تجاهلها للوضوح:
- تأمين نقاط actuator والإعدادات في Config Server. أضف Spring Security إلى Config Server واشترط بيانات اعتماد HTTP Basic أو OAuth2. بدون ذلك، يمكن لأي شخص يصل إلى المنفذ 8888 قراءة أسرار كل خدمة.
- تشفير القيم الحساسة. يدعم Config Server التشفير المتماثل (AES) وغير المتماثل (RSA) عبر بادئات
{cipher}. خزّن النص المشفّر في Git؛ يقوم الخادم بفك التشفير عند التسليم. - تقييد منفذ إدارة Eureka. واجهة برمجة
/eureka/appsغير محمية بمصادقة افتراضيًا. في الإنتاج، ضع Eureka خلف شبكة خاصة أو أضف Spring Security بكلمة مرور لحساب الخدمة. - لا تعرض نقاط إدارة Gateway للعامة. تكشف نقطة النهاية
/actuator/gateway/routesعن جدول التوجيه بالكامل. اربط منفذ الإدارة بواجهة غير عامة.
discovery.locator.enabled: true، تصبح كل خدمة في Eureka قابلة للوصول عبر Gateway. إذا سجّلت خدمة إدارة داخلية مع Eureka، فهي الآن متاحة للعامة ما لم تضف محددات مسار صريحة أو مرشّح أمان لحجبها. في الإنتاج، يُفضَّل استخدام تعريفات مسارات صريحة بدلًا من محدد الاكتشاف التلقائي، أو إدراج معرّفات الخدمات المسموح بتعريضها في قائمة بيضاء.
مقايضات الأنظمة الموزعة
تحل هذه البنية مشاكل حقيقية لكنها تُدخل مشاكل جديدة. تعرّف على المقايضات قبل الالتزام:
- Config Server نقطة فشل منفردة. إذا توقف عند الإقلاع، لا تستطيع الخدمات التابعة البدء. تُخفَّف هذه المشكلة بتشغيل مجموعة من Config Server أو بتخزين نسخة محلية مؤقتة من الخصائص عبر
spring.cloud.config.fail-fast: falseمع ملفapplication.ymlاحتياطي محلي. - اتساق Eureka في نهاية المطاف. يستخدم Eureka نموذج نبضات القلب، وليس بروتوكول توافق. يمكن أن تبقى خدمة أُلغي تسجيلها حديثًا في السجل لمدة تصل إلى 90 ثانية (3 نبضات قلب فائتة). يجب أن يتحمّل عملاؤك عددًا صغيرًا من الاستدعاءات إلى نسخ غير نشطة — وهذا بالضبط السبب الذي يجعل قواطع الدائرة (Resilience4j، المغطى في الدرس القادم) تتكامل بشكل طبيعي مع اكتشاف الخدمات.
- Gateway نقطة اختناق. تمر كل حركة المرور العامة عبر عملية واحدة. شغّل نسختين على الأقل من Gateway خلف موازن حمل خارجي أو سحابي، وحجّمهما لذروة التحميل على أكثر مساراتك تكلفةً.
الخلاصة
لديك الآن هيكل عظمي كامل وعامل: Config Server يمتلك جميع الخصائص، وسجل Eureka يمتلك جميع العناوين، وGateway يحل كليهما عند معالجة الطلبات. لا تعرف Order Service أبدًا أين تقع نظيراتها — إنها تسأل Eureka. ولا تمتلك إعداداتها الخاصة — إنها تسأل Config Server. إضافة خدمة جديدة لهذا النظام تعني كتابة منطق الأعمال وspring.application.name؛ والبنية التحتية تتكفّل بالباقي. هذا هو المكسب الحقيقي للأنماط التي درستها في هذا البرنامج التعليمي.