JavaRush /مدونة جافا /Random-AR /دليل لخدمات جافا الصغيرة. الجزء الأول: أساسيات وهندسة الخ...

دليل لخدمات جافا الصغيرة. الجزء الأول: أساسيات وهندسة الخدمات المصغرة

نشرت في المجموعة
في هذا البرنامج التعليمي، سوف تتعلم ما هي خدمات Java المصغرة، وكيفية تصميمها وإنشائها. ويغطي أيضًا أسئلة حول مكتبات خدمات Java الصغيرة وجدوى استخدام الخدمات الصغيرة. ترجمة وتكييف خدمات Java Microservices: دليل عملي .

خدمات جافا الدقيقة: الأساسيات

لفهم الخدمات الصغيرة، يجب عليك أولاً تحديد ما ليست عليه. أليست "متراصة" - مونوليث جافا: ما هي وما هي مزاياها أو عيوبها؟ دليل لخدمات جافا الصغيرة.  الجزء 1: أساسيات وهندسة الخدمات المصغرة - 1

ما هو متراصة جافا؟

تخيل أنك تعمل في أحد البنوك أو شركة ناشئة في مجال التكنولوجيا المالية. أنت تزود المستخدمين بتطبيق جوال يمكنهم استخدامه لفتح حساب مصرفي جديد. في كود Java سيؤدي هذا إلى وجود فئة تحكم. بشكل مبسط، يبدو الأمر كما يلي:
@Controller
class BankController {

    @PostMapping("/users/register")
    public void register(RegistrationForm form) {
        validate(form);
        riskCheck(form);
        openBankAccount(form);
        // etc..
    }
}
تحتاج إلى وحدة التحكم من أجل:
  1. تم تأكيد استمارة التسجيل.
  2. التحقق من مخاطر عنوان المستخدم لتحديد ما إذا كان سيتم تزويده بحساب مصرفي.
  3. فتحت حسابا مصرفيا.
سيتم تجميع الفصل BankControllerمع بقية مصادرك في ملفbank.jar أو ملفbank.war للنشر - وهو عبارة عن كتلة متراصة قديمة جيدة تحتوي على جميع التعليمات البرمجية اللازمة لتشغيل البنك الذي تتعامل معه. كتقدير تقريبي، سيتراوح الحجم الأولي لملف ‎.jar (أو ‎.war) من 1 إلى 100 ميغابايت. يمكنك الآن ببساطة تشغيل ملف ‎.jar على الخادم الخاص بك... وهذا كل ما عليك فعله لنشر تطبيق Java الخاص بك. دليل لخدمات جافا الصغيرة.  الجزء 1: أساسيات وهندسة الخدمات المصغرة - 2الصورة، المستطيل الأيسر العلوي: نشر بنك أحادي (حجري) java -jar Bank.jar (cp .war/.ear في خادم التطبيقات). المستطيل الأيمن: افتح المتصفح.

ما هي المشكلة مع متراصة جافا؟

لا يوجد شيء خاطئ بطبيعته مع كتل جافا. ومع ذلك، فقد أظهرت التجربة أنه إذا كان في مشروعك:
  • هناك العديد من المبرمجين/الفرق/الاستشاريين الذين يعملون...
  • ...على نفس المنضدة تحت ضغط من العملاء بمتطلبات غامضة للغاية...
  • في غضون بضع سنوات ...
... ثم في هذه الحالة، يتحول ملف Bank.jar الصغير الخاص بك إلى غيغابايت هائلة من التعليمات البرمجية وحدها، وهو أمر مخيف حتى عند الاقتراب منه، ناهيك عن نشره.

كيفية تقليل حجم متراصة جافا؟

يطرح سؤال طبيعي: كيف نجعل المتراصة أصغر؟ في الوقت الحالي، يتم تشغيل Bank.jar الخاص بك على JVM واحد، وعملية واحدة على خادم واحد. لا أكثر ولا أقل. والآن قد تتبادر إلى ذهني فكرة منطقية: "ولكن يمكن للأقسام الأخرى في شركتي استخدام خدمة التحقق من المخاطر! لا يرتبط الأمر مباشرة بتطبيقي المصرفي المتجانس! ربما ينبغي قطعها من المتراصة ونشرها كمنتج منفصل؟ وهذا يعني، من الناحية الفنية، تشغيلها كعملية Java منفصلة.

ما هي خدمة جافا الصغيرة؟

من الناحية العملية، تعني هذه العبارة أنه لن يتم الآن إجراء استدعاء الأسلوب riskCheck()من BankController: سيتم نقل هذا الأسلوب أو مكون الفول مع جميع فئاته المساعدة إلى مشروع Maven أو Gradle الخاص به. وسيتم أيضًا نشره ووضعه تحت التحكم في الإصدار بشكل مستقل عن الكتلة المصرفية. ومع ذلك، فإن عملية الاستخراج بأكملها لا تحول وحدة RiskCheck الجديدة الخاصة بك إلى خدمة صغيرة في حد ذاتها، نظرًا لأن تعريف الخدمة الصغيرة مفتوح للتفسير. وهذا يؤدي إلى مناقشات متكررة داخل الفرق والشركات.
  • هل 5-7 فصول في مشروع صغير أم ماذا؟
  • 100 أو 1000 فصل... لا تزال صغيرة؟
  • هل الخدمة المصغرة مرتبطة بشكل عام بعدد الفئات أم لا؟
دعونا نترك المنطق النظري وراءنا، ونلتزم بدلاً من ذلك بالاعتبارات العملية ونقوم بما يلي:
  1. دعنا نطلق على جميع الخدمات المنشورة بشكل منفصل خدمات صغيرة، بغض النظر عن حجمها أو حدود المجال.
  2. دعونا نفكر في كيفية ترتيب الاتصالات بين الخدمات. تحتاج خدماتنا الصغيرة إلى طرق للتواصل مع بعضها البعض.
لذا، لتلخيص ما يلي: في السابق كان لديك عملية JVM واحدة، وهي عبارة عن كتلة صلبة لإدارة البنك. الآن لديك عملية JVM متجانسة مصرفية وخدمة صغيرة منفصلة RiskCheck تعمل ضمن عملية JVM الخاصة بها. والآن، للتحقق من المخاطر، يجب أن تقوم وحدة متراصة لديك باستدعاء هذه الخدمة الصغيرة. كيف نفعل ذلك؟

كيفية إنشاء اتصال بين خدمات Java الصغيرة؟

بشكل عام، هناك خياران - الاتصال المتزامن وغير المتزامن.

الاتصال المتزامن: (HTTP)/REST

عادةً ما يحدث الاتصال المتزامن بين الخدمات الصغيرة عبر خدمات HTTP والخدمات المشابهة لـ REST والتي تقوم بإرجاع XML أو JSON. بالطبع، قد تكون هناك خيارات أخرى - خذ على الأقل Google Protocol Buffers . إذا كنت بحاجة إلى استجابة فورية، فمن الأفضل استخدام اتصال REST. في مثالنا، هذا هو بالضبط ما يجب القيام به، حيث أن التحقق من المخاطر مطلوب قبل فتح الحساب. إذا لم يكن هناك فحص للمخاطر، فلا يوجد حساب. سنناقش الأدوات أدناه، في قسم " ما المكتبات الأفضل لاستدعاءات Java REST المتزامنة ".

المراسلة - الاتصال غير المتزامن

عادةً ما يتم تحقيق اتصال الخدمات الصغيرة غير المتزامن عن طريق تبادل الرسائل مع تطبيق JMS و/أو استخدام بروتوكول مثل AMQP . لقد كتبنا "عادة" هنا لسبب ما: لنفترض أنه لا يمكن الاستهانة بعدد عمليات تكامل البريد الإلكتروني/SMTP. استخدمه عندما لا تحتاج إلى استجابة فورية. على سبيل المثال، يقوم المستخدم بالنقر فوق الزر "اشتر الآن"، وأنت بدورك تريد إنشاء فاتورة. من المؤكد أنه لا ينبغي أن تحدث هذه العملية ضمن دورة الاستجابة لطلب الشراء الخاصة بالمستخدم. سنصف أدناه الأدوات الأفضل لمراسلة Java غير المتزامنة .

مثال: استدعاء REST API في Java

لنفترض أننا اخترنا اتصالات الخدمات الصغيرة المتزامنة. في هذه الحالة، كود Java الخاص بنا (الذي قدمناه أعلاه) سيبدو على مستوى منخفض مثل هذا. (نعني بالمستوى المنخفض هنا حقيقة أنه بالنسبة لاتصالات الخدمات الصغيرة، يتم عادةً إنشاء مكتبات العملاء التي تجردك من مكالمات HTTP الفعلية).
@Controller
class BankController {

    @Autowired
    private HttpClient httpClient;

    @PostMapping("/users/register")
    public void register(RegistrationForm form) {
        validate(form);
        httpClient.send(riskRequest, responseHandler());
        setupAccount(form);
        // etc..
    }
}
بناءً على الكود، يصبح من الواضح أننا بحاجة الآن إلى نشر خدمتين Java (micro)، Bank وRiskCheck. ونتيجة لذلك، سيكون لدينا عمليتين JVM قيد التشغيل. دليل لخدمات جافا الصغيرة.  الجزء 1: أساسيات وهندسة الخدمات المصغرة - 3هذا هو كل ما تحتاجه لتطوير مشروع Java microservices: ما عليك سوى إنشاء ونشر أجزاء أصغر (ملفات .jar أو .war) بدلاً من مجموعة واحدة متجانسة. لا تزال الإجابة على السؤال غير واضحة: كيف يمكننا تقسيم المونوليث إلى خدمات صغيرة؟ ما مدى صغر حجم هذه القطع وكيفية تحديد الحجم الصحيح؟ دعونا تحقق.

بنية الخدمات الدقيقة لجافا

ومن الناحية العملية، تقوم الشركات بتطوير مشاريع الخدمات الصغيرة بطرق مختلفة. يعتمد الأسلوب على ما إذا كنت تحاول تحويل وحدة متراصة موجودة إلى مشروع خدمات صغيرة أو بدء المشروع من الصفر.

من متراصة إلى الخدمات الصغيرة

إحدى الأفكار الأكثر منطقية هي استخراج الخدمات الصغيرة من وحدة متراصة موجودة. لاحظ أن البادئة "micro" هنا لا تعني في الواقع أن الخدمات المستخرجة ستكون صغيرة حقًا؛ وهذا ليس هو الحال بالضرورة. دعونا ننظر إلى الخلفية النظرية.

الفكرة: تقسيم المونوليث إلى خدمات صغيرة

يمكن تطبيق نهج الخدمات الصغيرة على المشاريع القديمة. ولهذا السبب:
  1. في أغلب الأحيان، يصعب الحفاظ على مثل هذه المشاريع أو تغييرها أو توسيعها.
  2. الجميع، من المطورين إلى الإدارة، يريدون التبسيط.
  3. لديك حدود مجال واضحة (نسبيًا)، مما يعني أنك تعرف بالضبط ما يجب أن يفعله برنامجك.
بالعودة إلى مثالنا، هذا يعني أنه يمكنك إلقاء نظرة على وحدة Java المصرفية الخاصة بك ومحاولة تقسيمها عبر حدود النطاق.
  • لذلك، سيكون من المعقول فصل معالجة بيانات المستخدم (مثل الأسماء والعناوين وأرقام الهواتف) في خدمة صغيرة منفصلة "إدارة الحساب".
  • أو "وحدة فحص المخاطر" المذكورة أعلاه والتي تتحقق من مستويات المخاطر لدى المستخدم ويمكن استخدامها من قبل العديد من المشاريع الأخرى أو حتى أقسام الشركة.
  • أو وحدة الفواتير التي ترسل الفواتير بتنسيق PDF أو عن طريق البريد.

تنفيذ الفكرة: السماح لشخص آخر بتنفيذها

يبدو النهج الموصوف أعلاه رائعًا على الورق والرسوم البيانية المشابهة لـ UML. ومع ذلك، كل شيء ليس بهذه البساطة. يتطلب تنفيذها العملي إعدادًا فنيًا جادًا: فالفجوة بين فهمنا لما قد يكون من الجيد استخلاصه من قطعة متراصة وعملية الاستخراج نفسها هائلة. تصل معظم مشاريع المؤسسات إلى مرحلة يخشى فيها المطورون، على سبيل المثال، ترقية إصدار عمره 7 سنوات من Hibernate إلى إصدار أحدث. سيتم تحديث المكتبات معه، ولكن هناك خطر حقيقي من كسر شيء ما. إذن، يتعين على هؤلاء المطورين أنفسهم الآن البحث في التعليمات البرمجية القديمة ذات الحدود غير الواضحة لمعاملات قاعدة البيانات واستخراج خدمات دقيقة محددة جيدًا؟ في أغلب الأحيان، تكون هذه المشكلة معقدة للغاية ولا يمكن "حلها" على السبورة البيضاء أو في اجتماعات الهندسة المعمارية. دليل لخدمات جافا الصغيرة.  الجزء 1: أساسيات وهندسة الخدمات المصغرة - 4على حد تعبير مطور تويتر @simonbrown: سأقول هذا مرارًا وتكرارًا... إذا لم يتمكن الأشخاص من بناء وحدات متراصة بشكل صحيح، فلن تساعد الخدمات الصغيرة. سيمون براون

مشروع من الصفر يعتمد على بنية الخدمات الصغيرة

بالنسبة لمشاريع Java الجديدة، تبدو العناصر الثلاثة المرقمة من الجزء السابق مختلفة قليلاً:
  1. عليك أن تبدأ بسجل نظيف، لذلك ليس هناك "أمتعة" يجب الحفاظ عليها.
  2. يرغب المطورون في إبقاء الأمور بسيطة في المستقبل.
  3. المشكلة: لديك صورة أكثر غموضًا عن حدود النطاق: فأنت لا تعرف ما الذي من المفترض أن يفعله برنامجك فعليًا (تلميح: Agile ;))
يؤدي هذا إلى قيام الشركات بتجربة مشاريع جديدة باستخدام خدمات Java الصغيرة.

بنية الخدمات الدقيقة التقنية

يبدو أن النقطة الأولى هي الأكثر وضوحًا بالنسبة للمطورين، ولكن هناك أيضًا من لا يشجعونها بشدة. يوصي هادي الحريري بإعادة هيكلة "Extract Microservice" في IntelliJ. وعلى الرغم من أن المثال التالي مبسط للغاية، إلا أن التطبيقات التي تمت ملاحظتها في المشاريع الحقيقية، للأسف، لا تبتعد عنه كثيرًا. قبل الخدمات المصغرة
@Service
class UserService {

    public void register(User user) {
        String email = user.getEmail();
        String username =  email.substring(0, email.indexOf("@"));
        // ...
    }
}
مع سلسلة فرعية Java microservice
@Service
class UserService {

    @Autowired
    private HttpClient client;

    public void register(User user) {
        String email = user.getEmail();
        //теперь вызываем substring microservice via http
        String username =  httpClient.send(substringRequest(email), responseHandler());
        // ...
    }
}
لذا، فأنت تقوم بشكل أساسي بتغليف استدعاء أسلوب Java في استدعاء HTTP، دون سبب واضح للقيام بذلك. ومع ذلك، أحد الأسباب هو: الافتقار إلى الخبرة ومحاولة فرض نهج خدمات Java الصغيرة. التوصية: لا تفعل هذا.

بنية الخدمات الصغيرة الموجهة نحو سير العمل

الطريقة الشائعة التالية هي تقسيم خدمات Java الصغيرة إلى وحدات تعتمد على سير العمل. مثال من الحياة الواقعية: في ألمانيا، عندما تذهب إلى طبيب (عام)، يجب عليه تسجيل زيارتك في نظام إدارة علاقات العملاء الطبي الخاص به. للحصول على دفعة من التأمين، سيرسل بيانات حول علاجك (وعلاج المرضى الآخرين) إلى الوسيط عبر XML. سوف ينظر الوسيط إلى ملف XML هذا و(مبسط):
  1. سيتم التحقق من استلام ملف XML الصحيح.
  2. سيتم التحقق من معقولية الإجراءات: على سبيل المثال، يبدو الطفل البالغ من العمر عام واحد، الذي تلقى ثلاث إجراءات لتنظيف الأسنان في يوم واحد من طبيب أمراض النساء، مشبوهًا إلى حد ما.
  3. سيتم دمج XML مع بعض البيانات البيروقراطية الأخرى.
  4. سيتم إرسال ملف XML إلى شركة التأمين لبدء الدفعات.
  5. وسيتم إرسال النتيجة إلى الطبيب، مع تزويده برسالة "النجاح" أو "الرجاء إعادة إرسال هذا التسجيل بمجرد أن يصبح منطقيًا".
ملحوظة. في هذا المثال، لا يلعب الاتصال بين الخدمات الصغيرة دورًا، ولكن من الممكن أن يتم بشكل غير متزامن بواسطة وسيط رسائل (مثل RabbitMQ)، نظرًا لأن الطبيب لا يتلقى تعليقات فورية على أي حال. دليل لخدمات جافا الصغيرة.  الجزء 1: أساسيات وهندسة الخدمات المصغرة - 5مرة أخرى، يبدو هذا رائعًا على الورق، ولكن هناك أسئلة طبيعية تطرح:
  • هل من الضروري نشر ستة تطبيقات لمعالجة ملف XML واحد؟
  • هل هذه الخدمات الصغيرة مستقلة حقًا عن بعضها البعض؟ هل يمكن نشرها بشكل مستقل عن بعضها البعض؟ مع إصدارات مختلفة ومخططات API؟
  • ماذا تفعل خدمة مصداقية المعلومات الصغيرة إذا لم تعمل خدمة التحقق الصغيرة؟ هل النظام لا يزال يعمل؟
  • هل تشترك هذه الخدمات الصغيرة في نفس قاعدة البيانات (تحتاج بالتأكيد إلى بعض البيانات المشتركة في جداول قاعدة البيانات)، أم أن لكل منها بياناتها الخاصة؟
  • … وأكثر بكثير.
ومن المثير للاهتمام أن الرسم البياني أعلاه يبدو أبسط لأن كل خدمة لها الآن غرضها الدقيق والمحدد جيدًا. كان يبدو مثل هذا الحجر المترابط المخيف: دليل لخدمات جافا الصغيرة.  الجزء 1: أساسيات وهندسة الخدمات المصغرة - 6بينما يمكنك الجدال حول بساطة هذه المخططات، فأنت بالتأكيد بحاجة الآن إلى حل هذه التحديات التشغيلية الإضافية.
  • لا تحتاج إلى نشر تطبيق واحد فقط، بل ستة على الأقل.
  • قد تحتاج أيضًا إلى نشر قواعد بيانات متعددة، اعتمادًا على المدى الذي تريد الوصول إليه في بنية الخدمات الصغيرة.
  • تحتاج إلى التأكد من أن كل نظام متصل بالإنترنت ويعمل بشكل صحيح.
  • أنت بحاجة إلى التأكد من أن مكالماتك بين الخدمات الصغيرة مرنة حقًا (راجع كيفية جعل خدمة Java الصغيرة مرنة؟).
  • وكل شيء آخر يتضمنه هذا الإعداد - بدءًا من إعدادات التطوير المحلي وحتى اختبار التكامل.
لذلك ستكون التوصية:
  • إذا لم تكن Netflix (هناك احتمالات أنك لست Netflix)...
  • إلا إذا كانت لديك مهارات عمل قوية للغاية حيث تفتح بيئة التطوير ويتسبب في حدوث فوضى تؤدي إلى التخلص من قاعدة بيانات الإنتاج الخاصة بك والتي يمكن استعادتها بسهولة في 5 ثوانٍ.
  • أو أنك تشعر وكأنك @monzo وترغب في تجربة 1500 خدمة صغيرة فقط لأنك تستطيع ذلك.
→ لا تفعل هذا. والآن أصبح الأمر أقل زائدية. تبدو محاولة تصميم الخدمات الصغيرة عبر حدود المجال أمرًا معقولًا تمامًا. ولكن هذا لا يعني أنك بحاجة إلى أخذ سير عمل واحد وتقسيمه إلى أجزاء فردية صغيرة (استلام XML، التحقق من صحة XML، إعادة توجيه XML). وبالتالي، عندما تبدأ مشروعًا جديدًا باستخدام خدمات Java الصغيرة ولا تزال حدود النطاق غامضة للغاية، حاول إبقاء حجم خدماتك الصغيرة عند مستوى منخفض. يمكنك دائمًا إضافة المزيد من الوحدات لاحقًا. وتأكد من حصولك على DevOps المتقدمة في الفريق/الشركة/القسم لدعم البنية التحتية الجديدة الخاصة بك.

متعدد اللغات أو بنية الخدمات المصغرة الموجهة نحو الفريق

هناك نهج ثالث، يكاد يكون تحرريًا، لتطوير الخدمات الصغيرة: السماح للفرق أو حتى الأفراد بتنفيذ قصص المستخدم باستخدام أي عدد من اللغات أو الخدمات الصغيرة (يطلق المسوقون على هذا النهج اسم "البرمجة متعددة اللغات"). وبالتالي، يمكن كتابة خدمة التحقق من صحة XML الموصوفة أعلاه بلغة Java، في حين يمكن كتابة خدمة التحقق الصغيرة في نفس الوقت بلغة Haskell (لجعلها سليمة رياضيًا). بالنسبة إلى الخدمة الصغيرة لإعادة توجيه التأمين، يمكنك استخدام Erlang (لأنها تحتاج بالفعل إلى التوسع؛)). ما قد يبدو ممتعًا من وجهة نظر المطور (تطوير النظام المثالي بلغتك المثالية في بيئة معزولة) ليس في الواقع ما تريده المنظمة أبدًا: التجانس والتوحيد القياسي. وهذا يعني مجموعة موحدة نسبيًا من اللغات والمكتبات والأدوات حتى يتمكن المطورون الآخرون من الاستمرار في دعم خدمة Haskell الصغيرة الخاصة بك في المستقبل عندما تنتقل إلى مراعي أكثر خضرة. دليل لخدمات جافا الصغيرة.  الجزء 1: أساسيات وهندسة الخدمات المصغرة - 8يُظهر التاريخ أن توحيد المعايير عادة ما يصبح متأصلاً بعمق. على سبيل المثال، لم يُسمح في بعض الأحيان للمطورين في شركات Fortune 500 الكبيرة باستخدام Spring لأنه "لم يكن جزءًا من خريطة الطريق التكنولوجية للشركة". ومع ذلك، فإن الانتقال الكامل إلى النهج متعدد اللغات هو نفس الشيء تقريبًا، وهو الوجه الآخر لنفس العملة. توصية: إذا كنت ستستخدم البرمجة متعددة اللغات، فجرب تنوعًا أقل في نفس النظام البيئي للغة البرمجة. لذلك، من الأفضل استخدام Kotlin وJava معًا (تعتمد كلتا اللغتين على JVM ومتوافقتان بنسبة 100٪ مع بعضهما البعض)، بدلاً من Java وHaskell على سبيل المثال. في الجزء التالي، ستتعرف على نشر واختبار خدمات Java الصغيرة.
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION