العملاء التصريحيون مع OpenFeign
العملاء التصريحيون مع OpenFeign
في الدرس السابق أنشأت استدعاءات بين الخدمات باستخدام WebClient. يعمل هذا النهج، لكنه يُلزمك بتجميع عناوين URL يدويًا وإدارة الترويسات بشكل صريح وكتابة سلاسل تفاعلية إلزامية. مع نمو منظومة الخدمات المصغّرة لديك، يتراكم هذا الكود المتكرر بسرعة. يحلّ Spring Cloud OpenFeign هذه المشكلة بالسماح لك بتعريف عميل HTTP كواجهة Java بسيطة — نفس النموذج الذهني الذي تستخدمه بالفعل مع مستودعات Spring Data — ويُولّد الإطار التنفيذَ نيابةً عنك عند بدء التشغيل.
ما هو OpenFeign وكيف يعمل
OpenFeign (المعروف في الأصل بـ Netflix Feign، وهو الآن تحت إشراف مجتمع OpenFeign) هو عميل HTTP تصريحي. تُضيف تعليقات توضيحية إلى واجهة بـ @FeignClient وتعليقات Spring MVC القياسية (@GetMapping و@PostMapping ومتغيرات المسار ومعاملات الطلب وأجسام الطلبات). عند بدء التشغيل، يفحص Spring Cloud تلك الواجهات ويُنشئ وكلاء ديناميكيين JDK تُترجم كل استدعاء للأسلوب إلى طلب HTTP حقيقي.
WebClient تكتب الكيفية (بناء طلب، إضافة ترويسات، الاشتراك). مع Feign تكتب الماذا (استدعاء getOrder(id))، والإطار يتولى الباقي. النتيجة كود أقل بكثير وسطح تدقيق أسهل.
إضافة الاعتمادية
أضف مُشغّل Spring Cloud OpenFeign إلى ملف pom.xml الخاص بخدمتك. تحتاج أيضًا إلى BOM الخاص بـ Spring Cloud في كتلة إدارة الاعتمادية:
تفعيل Feign في تطبيقك
أضف تعليق @EnableFeignClients إلى فئتك الرئيسية (أو أي فئة @Configuration). بدون هذا، لن يفحص Spring أي واجهة @FeignClient.
تعريف أول عميل Feign
لنفترض أن خدمة الطلبات تحتاج إلى البحث عن المنتجات من خدمة المخزون. تعرض خدمة المخزون نقطة نهاية GET /products/{id}. إليك التعريف الكامل لعميل Feign:
بعض الملاحظات المهمة:
nameهو اسم منطقي يُستخدم للمقاييس و(عند دمجه مع سجل الخدمات) للبحث بالتوازن.urlهو عنوان URL الأساسي، يُقرأ هنا منapplication.yml. في بيئة اكتشاف الخدمات (Eureka أو Consul) يمكنك حذفurlويحلّ Feign عنوانها من السجل بالاستناد إلىname.- تعكس تواقيع الأساليب أساليب المتحكم في الخدمة الهدف — نفس التعليقات التوضيحية، نفس الأنواع.
حقن العميل واستخدامه
يُسجّل Spring الوكيل المُولَّد كحبة (bean) بنوع الواجهة. احقنه تمامًا كأي حبة Spring أخرى:
client مخصصة وضع بجانبها فئات DTO الخاصة بها أيضًا. يرسم هذا حدًا واضحًا: تمتلك حزمة client كل ما يتطلبه عقد الخدمة الخارجية، مما يُسهّل استبداله أو إصدار نسخة جديدة منه لاحقًا.
إرسال جسم الطلب
تعمل طلبات POST و PUT بنفس السلاسة. أضف تعليق @RequestBody إلى معاملة الجسم:
تخصيص ترويسات الطلب
كثيرًا ما تحتاج إلى تمرير الترويسات — معرّفات الارتباط، ورموز التفويض، ومعرّفات المستأجر — إلى الخدمات البعيدة. يوفر Feign آليتين:
١. تعليق الترويسة لكل أسلوب — لقيم الترويسة الثابتة أو المُقدَّمة من المُستدعي:
٢. معترض الطلب (Request Interceptor) — للترويسات التي تريد إضافتها لكل استدعاء من عميل معين (أو بشكل عالمي):
بما أن هذه الحبة هي @Component فهي تُطبَّق بشكل عالمي — كل عميل Feign في التطبيق سيُمرّر معرّف الارتباط. لتقييدها بعميل واحد، عرّفها داخل فئة @Configuration وأشر إليها عبر @FeignClient(configuration = MyConfig.class).
Authorization من الطلبات الواردة بصورة عمياء. إذا استقبلت الخدمة A رمز JWT لمستخدم وأرسلته دون تغيير إلى الخدمة B، فأنت أوجدت ثغرة أمنية: تقبل الخدمة B الآن رموزًا على مستوى المستخدم لما يجب أن يكون استدعاءً داخليًا بين الخدمات. استخدم آلية منفصلة — سرًا مشتركًا أو mTLS أو رمز حساب خدمة مخصص — للاتصال الداخلي، ولا تدع بيانات اعتماد المستخدم تتسرب بين الخدمات.
معالجة الأخطاء مع ErrorDecoder
افتراضيًا، تُثير أي استجابة 4xx أو 5xx من الخدمة البعيدة استثناء FeignException عامًا. يمكنك تعيين رموز أخطاء HTTP إلى استثناءات النطاق باستخدام ErrorDecoder مخصص:
سجّله في فئة تهيئة Feign وأشر إليه من تعليق العميل لتقييد النطاق، أو عرّفه كـ @Component للتطبيق العالمي.
ضبط المهلة الزمنية وإعدادات الاتصال
القيم الافتراضية لمهلة Feign مرتفعة بشكل خطر في بعض الإصدارات. عيّن قيمًا صريحة في application.yml:
OpenFeign مقابل WebClient — اختيار الأداة المناسبة
- استخدم OpenFeign حين تريد كودًا موجزًا وقابلًا للقراءة بأسلوب متزامن وإمكانية لحظر الخيط المُستدعي. يتكامل بسلاسة مع تطبيقات Spring MVC (servlet-stack) وهو الخيار الافتراضي لمعظم فرق الخدمات المصغّرة.
- استخدم WebClient حين يكون تطبيقك تفاعليًا (Spring WebFlux، إدخال/إخراج غير محجوب) أو عندما تحتاج إلى تحكم دقيق في البث أو الاستجابات الجزئية أو الضغط الخلفي.
- دمج استدعاءات Feign المحجوبة داخل خط أنابيب تفاعلي سيعطّل خيوط حلقة الأحداث ويُدهور التطبيق بأكمله — اختر نموذجًا واحدًا والتزم به لكل خدمة.
الخلاصة
يحوّل OpenFeign استدعاءات HTTP بين الخدمات إلى استدعاءات لأساليب واجهة Java بسيطة. تُعلن العقد، وتُضيف التعليقات التوضيحية للأساليب، وتحقن الحبة، وتستدعيها. تتولى معترضات الطلب نشر الترويسات العرضية؛ يُترجم ErrorDecoder رموز أخطاء HTTP إلى استثناءات النطاق؛ وتتحكم خصائص YAML في المهل الزمنية. تمنحك هذه القطع مجتمعةً طبقة اتصال نظيفة وآمنة من حيث الأنواع وقابلة للتدقيق، وتتسع بسلاسة مع نمو عدد الخدمات. في الدرس القادم ستُضيف أنماط المرونة — إعادة المحاولة وقاطعات الدوائر والحلول البديلة — لحماية هذه الاستدعاءات من أعطال الخدمات البعيدة.