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

دليل لخدمات جافا الصغيرة. الجزء الثالث: أسئلة عامة

نشرت في المجموعة
ترجمة وتكييف خدمات Java Microservices: دليل عملي . الأجزاء السابقة من الدليل: دعونا نلقي نظرة على المشاكل المتأصلة في الخدمات الصغيرة في Java، بدءًا من الأشياء المجردة وانتهاءً بالمكتبات الملموسة. دليل لخدمات جافا الصغيرة.  الجزء 3: أسئلة عامة - 1

كيفية جعل خدمة Java الصغيرة مرنة؟

تذكر أنه عندما تقوم بإنشاء خدمات صغيرة، فإنك تقوم بشكل أساسي بتداول استدعاءات طريقة JVM لمكالمات HTTP المتزامنة أو الرسائل غير المتزامنة. على الرغم من ضمان اكتمال استدعاء الأسلوب في الغالب (باستثناء إيقاف تشغيل JVM غير المتوقع)، فإن استدعاء الشبكة غير موثوق به بشكل افتراضي. قد ينجح الأمر، لكنه قد لا يعمل لأسباب مختلفة: زيادة التحميل على الشبكة، وتنفيذ قاعدة جديدة لجدار الحماية، وما إلى ذلك. لمعرفة كيف يُحدث هذا فرقًا، دعنا نلقي نظرة على مثال BillingService.

أنماط مرونة HTTP/REST

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

    @Autowired
    private HttpClient client;

     public void bill(User user, Plan plan) {
        Invoice invoice = createInvoice(user, plan);
        httpClient.send(invoiceRequest(user.getEmail(), invoice), responseHandler());
        // ...
    }
}
لتلخيص ذلك، إليك ثلاث نتائج محتملة لاستدعاء HTTP هذا.
  • حسنًا: تمت المكالمة وتم إنشاء الحساب بنجاح.
  • تأخير: تمت المكالمة، ولكن استغرق إكمالها وقتًا طويلاً.
  • خطأ. فشلت المكالمة، ربما تكون قد أرسلت طلبًا غير متوافق، أو ربما لا يعمل النظام.
من المتوقع أن يتعامل أي برنامج مع حالات الخطأ، وليس فقط الحالات الناجحة. الأمر نفسه ينطبق على الخدمات المصغرة. حتى إذا كنت بحاجة إلى بذل جهد إضافي للتأكد من أن جميع الإصدارات المنشورة من واجهة برمجة التطبيقات (API) متوافقة بمجرد البدء في عمليات النشر وإصدارات الخدمات الصغيرة الفردية. دليل لخدمات جافا الصغيرة.  الجزء 3: أسئلة عامة - 2ومن الحالات المثيرة للاهتمام التي يجب النظر فيها هي حالة التأخير. على سبيل المثال، يكون محرك الأقراص الثابتة الخاص بالخدمة الصغيرة للمستجيب ممتلئًا، وبدلاً من أن يستغرق 50 مللي ثانية، يستغرق الاستجابة 10 ثوانٍ. يصبح الأمر أكثر إثارة للاهتمام عندما تواجه حملًا معينًا بحيث يبدأ عدم استجابة BillingService في الانتشار عبر نظامك. وكمثال توضيحي، تخيل أن المطبخ يبدأ ببطء في تشغيل "كتلة" من جميع النوادل في المطعم. من الواضح أن هذا القسم لا يمكنه تقديم نظرة شاملة حول موضوع مرونة الخدمات الصغيرة، ولكنه بمثابة تذكير للمطورين بأن هذا في الواقع شيء يحتاج إلى معالجة وعدم تجاهله قبل الإصدار الأول (والذي يحدث، من خلال الخبرة، في كثير من الأحيان أكثر من مرة) لا).يتبع). إحدى المكتبات الشهيرة التي تساعدك على التفكير في زمن الاستجابة والتسامح مع الأخطاء هي Hystrix من Netflix. استخدم وثائقها للتعمق أكثر في الموضوع.

أنماط مرونة المراسلة

دعونا نلقي نظرة فاحصة على الاتصالات غير المتزامنة. قد يبدو برنامج BillingService الآن بهذا الشكل، بافتراض أننا نستخدم Spring وRabbitMQ للمراسلة. لإنشاء حساب، نقوم الآن بإرسال رسالة إلى وسيط الرسائل الخاص بنا RabbitMQ، حيث يوجد العديد من العاملين في انتظار رسائل جديدة. يقوم هؤلاء العمال بإنشاء فواتير PDF وإرسالها إلى المستخدمين المناسبين.
@Service
class BillingService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

     public void bill(User user, Plan plan) {
        Invoice invoice = createInvoice(user, plan);
        // преобразует счет, например, в json и использует его How тело messages
        rabbitTemplate.convertAndSend(exchange, routingkey, invoice);
        // ...
    }
}
تبدو الأخطاء المحتملة مختلفة بعض الشيء الآن، حيث لم تعد تتلقى استجابات "موافق" أو "خطأ" فورية كما فعلت مع اتصال HTTP المتزامن. وبدلاً من ذلك، قد يكون لدينا ثلاثة سيناريوهات محتملة قد تسوء، مما قد يثير الأسئلة التالية:
  1. هل تم تسليم رسالتي واستخدامها من قبل الموظف؟ أم أنها فقدت؟ (لا يتلقى المستخدم فاتورة).
  2. هل تم تسليم رسالتي مرة واحدة فقط؟ أم يتم تسليمها أكثر من مرة ومعالجتها مرة واحدة فقط؟ (سيتلقى المستخدم فواتير متعددة).
  3. التكوين: من "هل استخدمت مفاتيح/أسماء التوجيه الصحيحة للتبادل" إلى "هل تم تكوين وسيط الرسائل الخاص بي وصيانته بشكل صحيح أم أن قوائم الانتظار الخاصة به ممتلئة؟" (لا يتلقى المستخدم فاتورة).
إن الوصف التفصيلي لكل نمط مرونة للخدمات الصغيرة غير المتزامنة يقع خارج نطاق هذا الدليل. ومع ذلك، هناك علامات في الاتجاه الصحيح. علاوة على ذلك، فإنها سوف تعتمد على تكنولوجيا الرسائل. أمثلة:
  • إذا كنت تستخدم تطبيقات JMS مثل ActiveMQ، فيمكنك استبدال السرعة بضمان الالتزامات على مرحلتين (XA).
  • إذا كنت تستخدم RabbitMQ، فاقرأ هذا الدليل أولاً، ثم فكر جيدًا في التأكيدات والتسامح مع الأخطاء وموثوقية الرسالة بشكل عام.
  • ربما يكون شخص ما على دراية جيدة بتكوين خوادم Active أو RabbitMQ، خاصة بالاشتراك مع المجموعات وDocker (أي شخص؟ ;))

ما هو الإطار الذي سيكون الحل الأفضل لخدمات Java الصغيرة؟

من ناحية، يمكنك تثبيت خيار شائع جدًا مثل Spring Boot . إنه يجعل من السهل جدًا إنشاء ملفات .jar، ويأتي مزودًا بخادم ويب مدمج مثل Tomcat أو Jetty، ويمكن تشغيله بسرعة وفي أي مكان. مثالية لبناء تطبيقات الخدمات الصغيرة. في الآونة الأخيرة، ظهر اثنان من أطر الخدمات الصغيرة المتخصصة، Kubernetes أو GraalVM ، مستوحاة جزئيًا من البرمجة التفاعلية. فيما يلي بعض المتنافسين الأكثر إثارة للاهتمام: Quarkus و Micronaut و Vert.x و Helidon . في النهاية، سيتعين عليك الاختيار بنفسك، ولكن يمكننا أن نقدم لك بعض التوصيات التي قد لا تكون قياسية تمامًا: باستثناء Spring Boot، يتم عادةً تسويق جميع أطر عمل الخدمات الصغيرة على أنها سريعة بشكل لا يصدق، مع بدء تشغيل فوري تقريبًا ، انخفاض استخدام الذاكرة، وقابلية التوسع إلى ما لا نهاية. تتميز المواد التسويقية عادةً برسومات رائعة تُظهر النظام الأساسي بجوار Spring Boot العملاق أو مع بعضها البعض. وهذا، من الناحية النظرية، يريح أعصاب المطورين الذين يدعمون المشاريع القديمة، والتي يستغرق تحميلها أحيانًا عدة دقائق. أو المطورين الذين يعملون في السحابة والذين يرغبون في بدء/إيقاف أي عدد من الحاويات الصغيرة التي يحتاجونها حاليًا في غضون 50 مللي ثانية. دليل لخدمات جافا الصغيرة.  الجزء 3: أسئلة عامة - 3ومع ذلك، تكمن المشكلة في أن أوقات بدء التشغيل وأوقات إعادة التوزيع (المصطنعة) هذه لا تساهم في النجاح الشامل للمشروع. على الأقل تأثيرهم أقل بكثير من البنية التحتية القوية لإطار العمل، والتوثيق القوي، والمجتمع، ومهارات المطورين القوية. لذا فمن الأفضل أن ننظر إلى الأمر بهذه الطريقة: إذا كان الأمر كذلك حتى الآن:
  • يمكنك السماح لـ ORMs الخاصة بك بالعمل على نطاق واسع، مما يؤدي إلى إنشاء مئات الاستعلامات لسير العمل البسيط.
  • أنت بحاجة إلى عدد لا نهائي من الجيجابايت لتشغيل وحدة متراصة معقدة إلى حد ما.
  • لديك الكثير من التعليمات البرمجية والتعقيد مرتفع جدًا (نحن لا نتحدث عن عمليات التشغيل التي يحتمل أن تكون بطيئة مثل Hibernate الآن) بحيث يستغرق تحميل التطبيق الخاص بك عدة دقائق.
إذا كان الأمر كذلك، فإن إضافة مشكلات mycoservice إضافية (مرونة الشبكة، والمراسلة، وDevOps، والبنية التحتية) سيكون لها تأثير أكبر بكثير على مشروعك من تحميل عالم Hello فارغ. وبالنسبة لعمليات إعادة التوزيع السريعة أثناء التطوير، قد ينتهي بك الأمر إلى حلول مثل JRebel أو DCEVM . دعونا نتوقف لحظة لنقتبس من سايمون براون مرة أخرى : " إذا لم يتمكن الناس من بناء وحدات متراصة (سريعة وفعالة)، فسيواجهون صعوبة في بناء خدمات صغيرة (سريعة وفعالة)، بغض النظر عن الهيكل ." لذا اختر أطرك بحكمة.

ما المكتبات الأفضل لاستدعاءات Java REST المتزامنة؟

على الجانب الفني منخفض المستوى، من المحتمل أن ينتهي بك الأمر بإحدى مكتبات عملاء HTTP التالية: HttpClient الأصلي لـ Java (منذ Java 11)، أو HttpClient الخاص بـ Apache ، أو OkHttp . لاحظ أنني أقول "ربما" هنا لأن هناك خيارات أخرى، بدءًا من عملاء JAX-RS القدامى الجيدين إلى عملاء WebSocket الحديثين . على أية حال، الاتجاه هو إنشاء عميل HTTP، والابتعاد عن العبث باستدعاءات HTTP بنفسك. للقيام بذلك، تحتاج إلى إلقاء نظرة على مشروع OpenFeign ووثائقه كنقطة انطلاق لمزيد من القراءة.

ما هي أفضل الوسطاء لمراسلة جافا غير المتزامنة؟

على الأرجح، ستصادف ActiveMQ (Classic أو Artemis) الشهير أو RabbitMQ أو Kafka .
  • ActiveMQ وRabbitMQ هما وسطاء رسائل تقليديون متكاملون. أنها تنطوي على تفاعل "الوسيط الذكي" و "المستخدمين الأغبياء".
  • تاريخيًا، يتمتع ActiveMQ بميزة التضمين السهل (للاختبار)، والذي يمكن تخفيفه باستخدام إعدادات RabbitMQ/Docker/TestContainer.
  • لا يمكن أن يُطلق على كافكا اسم الوسيط "الذكي" التقليدي. وبدلاً من ذلك، فهو عبارة عن مخزن رسائل "غبي" نسبيًا (ملف سجل) يتطلب معالجة مستهلكين أذكياء.
لفهم متى يجب استخدام RabbitMQ (أو وسطاء الرسائل التقليديين الآخرين بشكل عام) أو كافكا بشكل أفضل، قم بإلقاء نظرة على هذا المنشور المحوري كنقطة بداية. بشكل عام، عند اختيار وسيط مراسلة، حاول تجاهل أسباب الأداء المصطنعة. لقد مر وقت كانت فيه الفرق والمجتمعات عبر الإنترنت تتجادل باستمرار حول مدى سرعة RabbitMQ ومدى بطء ActiveMQ. الآن يتم تقديم نفس الحجج فيما يتعلق بـ RabbitMQ، حيث يقولون إنه يعمل ببطء مع 20-30 ألف رسالة في الثانية. كافكا يسجل 100 ألف رسالة في الثانية. بصراحة، مثل هذه المقارنات تشبه مقارنة الدفء بالناعم. بالإضافة إلى ذلك، في كلتا الحالتين، قد تكون قيم الإنتاجية في النطاق المنخفض إلى المتوسط، على سبيل المثال، لمجموعة علي بابا. ومع ذلك، من غير المرجح أن تواجه مشاريع بهذا الحجم (ملايين الرسائل في الدقيقة) في الواقع. إنهم موجودون بالتأكيد وسيكون لديهم مشاكل. على عكس 99٪ الأخرى من مشاريع Java التجارية "العادية". لذلك لا تهتم بالموضة والضجيج. اختر بحكمة.

ما المكتبات التي يمكنني استخدامها لاختبار الخدمات الصغيرة؟

ذلك يعتمد على المكدس الخاص بك. إذا كان لديك نظام Spring البيئي منشورًا، فسيكون من الحكمة استخدام الأدوات المحددة لإطار العمل . إذا كان JavaEE يشبه Arquillian . قد يكون من المفيد إلقاء نظرة على Docker ومكتبة Testcontainers الجيدة حقًا ، والتي تساعد بشكل خاص على إعداد قاعدة بيانات Oracle بسهولة وسرعة للتطوير المحلي أو اختبارات التكامل. لإجراء اختبار وهمي لخوادم HTTP بأكملها، راجع Wiremock . لاختبار المراسلة غير المتزامنة، حاول تنفيذ ActiveMQ أو RabbitMQ ثم كتابة الاختبارات باستخدام Awaitility DSL . بالإضافة إلى ذلك، يتم استخدام جميع أدواتك المعتادة - Junit و TestNG لـ AssertJ و Mockito . يرجى ملاحظة أن هذه ليست قائمة كاملة. إذا لم تجد أداتك المفضلة هنا، يرجى نشرها في قسم التعليقات.

كيفية تمكين التسجيل لجميع خدمات Java الصغيرة؟

يعد تسجيل الدخول في حالة الخدمات الصغيرة موضوعًا مثيرًا للاهتمام ومعقدًا إلى حد ما. بدلاً من أن يكون لديك ملف سجل واحد يمكنك معالجته بأوامر less أو grep، لديك الآن ملفات سجل n، وتريد ألا تكون متناثرة للغاية. تم وصف ميزات النظام البيئي للتسجيل بشكل جيد في هذه المقالة (باللغة الإنجليزية). تأكد من قراءته وانتبه إلى القسم التسجيل المركزي من منظور الخدمات الصغيرة . من الناحية العملية، سوف تصادف طرقًا مختلفة: يقوم مسؤول النظام بكتابة نصوص برمجية معينة تجمع وتدمج ملفات السجل من خوادم مختلفة في ملف سجل واحد وتضعها على خوادم FTP للتنزيل. تشغيل مجموعات cat/grep/unig/sort في جلسات SSH المتوازية. هذا هو بالضبط ما تفعله Amazon AWS، ويمكنك إخبار مديرك بذلك. استخدم أداة مثل Graylog أو ELK Stack (Elasticsearch، Logstash، Kibana)

كيف تجد خدماتي الصغيرة بعضها البعض؟

حتى الآن، افترضنا أن خدماتنا الصغيرة تعرف بعضها البعض وتعرف IPS المقابل. دعونا نتحدث عن التكوين الثابت. لذا، فإن وحدتنا المصرفية [ip = 192.168.200.1] تعرف أنها تحتاج إلى التحدث إلى خادم المخاطر [ip = 192.168.200.2]، والذي تم ترميزه ضمن ملف الخصائص. ومع ذلك، يمكنك جعل الأمور أكثر ديناميكية:
  • استخدم خادم تكوين قائم على السحابة حيث تسحب جميع الخدمات الصغيرة تكويناتها بدلاً من نشر ملفات application.properties على خدماتها الصغيرة.
  • نظرًا لأن مثيلات الخدمة الخاصة بك يمكنها تغيير موقعها ديناميكيًا، فمن المفيد النظر إلى الخدمات التي تعرف مكان وجود خدماتك، وما هي عناوين IP الخاصة بها، وكيفية توجيهها.
  • والآن بعد أن أصبح كل شيء ديناميكيا، تظهر مشاكل جديدة، مثل الانتخاب التلقائي للقائد: من هو السيد الذي يعمل على مهام معينة حتى لا يعالجها مرتين، على سبيل المثال؟ من يحل محل القائد عندما يفشل؟ وعلى أي أساس يتم الاستبدال؟
بشكل عام، هذا ما يسمى تنسيق الخدمات الصغيرة وهو موضوع آخر لا نهاية له. تحاول مكتبات مثل Eureka أو Zookeeper "حل" هذه المشكلات من خلال إظهار الخدمات المتوفرة. ومن ناحية أخرى، فإنها تضيف تعقيدًا إضافيًا. اسأل أي شخص قام بتثبيت ZooKeeper من قبل.

كيفية تنظيم الترخيص والمصادقة باستخدام خدمات Java المصغرة؟

هذا الموضوع يستحق أيضًا قصة منفصلة. مرة أخرى، تتراوح الخيارات من مصادقة HTTPS الأساسية المشفرة مع أطر عمل أمان مخصصة إلى تشغيل تثبيت Oauth2 باستخدام خادم التفويض الخاص به.

كيف يمكنني التأكد من أن جميع البيئات الخاصة بي تبدو متشابهة؟

ما ينطبق على عمليات النشر بدون خدمة صغيرة ينطبق أيضًا على عمليات النشر التي تحتوي على خدمة صغيرة. جرب مزيجًا من Docker/Testcontainers وScripting/Ansible.

لا يوجد سؤال: باختصار حول YAML

دعونا نبتعد عن المكتبات والقضايا ذات الصلة للحظة ونلقي نظرة سريعة على Yaml. يُستخدم تنسيق الملف هذا فعليًا كتنسيق "لكتابة التكوين كرمز". يتم استخدامه أيضًا بواسطة أدوات بسيطة مثل Ansible وعمالقة مثل Kubernetes. لتجربة ألم المسافة البادئة YAML، حاول كتابة ملف Ansible بسيط وانظر كم يتعين عليك تحرير الملف قبل أن يعمل كما هو متوقع. وهذا على الرغم من دعم التنسيق من قبل جميع بيئات التطوير المتكاملة الرئيسية! وبعد ذلك، عد لإنهاء قراءة هذا الدليل.
Yaml:
  - is:
    - so
    - great

ماذا عن المعاملات الموزعة؟ اختبار أداء؟ موضوعات أخرى؟

ربما يوما ما، في الإصدارات المستقبلية من الدليل. في الوقت الحالي، هذا كل شيء. ابقى معنا!

القضايا المفاهيمية مع الخدمات المصغرة

إلى جانب المشاكل المحددة للخدمات الصغيرة في Java، هناك مشاكل أخرى، دعنا نقول، تلك التي تظهر في أي مشروع خدمة صغيرة. وهي تتعلق في الغالب بالتنظيم والفريق والإدارة.

عدم تطابق الواجهة الأمامية والخلفية

يعد عدم تطابق الواجهة الأمامية والواجهة الخلفية مشكلة شائعة جدًا في العديد من مشاريع الخدمات الصغيرة. ماذا يعني ذلك؟ فقط في الوحدات القديمة الجيدة، كان لدى مطوري واجهة الويب مصدر واحد محدد للحصول على البيانات. في مشاريع الخدمات الصغيرة، أصبح لدى مطوري الواجهة الأمامية فجأة عدد n من المصادر للحصول على البيانات منها. تخيل أنك تقوم بإنشاء نوع من مشروع الخدمات الصغيرة لإنترنت الأشياء (إنترنت الأشياء) في جافا. لنفترض أنك تدير الآلات الجيوديسية والأفران الصناعية في جميع أنحاء أوروبا. وترسل لك هذه الأفران تحديثات منتظمة بدرجات حرارتها وما شابه. عاجلاً أم آجلاً، قد ترغب في العثور على أفران في واجهة المستخدم الإدارية، وربما باستخدام خدمات "البحث عن الأفران" الصغيرة. اعتمادًا على مدى صرامة تطبيق نظرائك في الواجهة الخلفية للتصميم المستند إلى المجال أو قوانين الخدمات الصغيرة، قد تقوم الخدمة الصغيرة "البحث عن فرن" بإرجاع معرفات الفرن فقط وليس بيانات أخرى مثل النوع أو الطراز أو الموقع. للقيام بذلك، سيحتاج مطورو الواجهة الأمامية إلى إجراء مكالمة إضافية واحدة أو ن (اعتمادًا على تطبيق الترحيل) في الخدمة المصغرة "الحصول على بيانات الفرن" باستخدام المعرفات التي تلقوها من الخدمة المصغرة الأولى. دليل لخدمات جافا الصغيرة.  الجزء 3: أسئلة عامة - 4وعلى الرغم من أن هذا مجرد مثال بسيط، على الرغم من أنه مأخوذ من مشروع حقيقي (!)، إلا أنه يوضح المشكلة التالية: أصبحت محلات السوبر ماركت تحظى بشعبية كبيرة. وذلك لأنه لن يتعين عليك الذهاب إلى 10 أماكن مختلفة لشراء الخضروات وعصير الليمون والبيتزا المجمدة وورق التواليت. بدلاً من ذلك، تذهب إلى مكان واحد، فهو أسهل وأسرع. الأمر نفسه ينطبق على مطوري الواجهة الأمامية والخدمات الصغيرة.

توقعات الإدارة

لدى الإدارة انطباع خاطئ بأنها بحاجة الآن إلى توظيف عدد لا حصر له من المطورين لمشروع (شامل)، حيث يمكن للمطورين الآن العمل بشكل مستقل تمامًا عن بعضهم البعض، كل منهم على الخدمة الصغيرة الخاصة به. مطلوب فقط القليل من العمل التكاملي في النهاية (قبل وقت قصير من الإطلاق). دليل لخدمات جافا الصغيرة.  الجزء 3: أسئلة عامة - 5في الواقع، هذا النهج يمثل مشكلة كبيرة. وفي الفقرات التالية سنحاول توضيح السبب.

"القطع الأصغر" لا تساوي "القطع الأفضل"

سيكون من الخطأ الكبير افتراض أن الكود المقسم إلى 20 جزءًا سيكون بالضرورة ذا جودة أعلى من جودة قطعة واحدة كاملة. حتى لو أخذنا الجودة من وجهة نظر فنية بحتة، فقد تستمر خدماتنا الفردية في تشغيل 400 استعلام إسبات لاختيار مستخدم من قاعدة البيانات، واجتياز طبقات من التعليمات البرمجية غير المدعومة. مرة أخرى، نعود إلى مقولة سايمون براون: إذا فشلت في بناء وحدات متراصة بشكل صحيح، سيكون من الصعب بناء خدمات صغيرة مناسبة. غالبًا ما يكون الوقت متأخرًا جدًا للحديث عن التسامح مع الخطأ في مشاريع الخدمات الصغيرة. لدرجة أنه يكون من المخيف أحيانًا رؤية كيفية عمل الخدمات الصغيرة في المشاريع الحقيقية. والسبب في ذلك هو أن مطوري Java ليسوا مستعدين دائمًا لدراسة التسامح مع الأخطاء والشبكات والمواضيع الأخرى ذات الصلة على المستوى المناسب. "القطع" نفسها أصغر، لكن "الأجزاء الفنية" أكبر. تخيل أن فريق الخدمات الصغيرة لديك مطالب بكتابة خدمة فنية صغيرة لتسجيل الدخول إلى نظام قاعدة البيانات، شيء من هذا القبيل:
@Controller
class LoginController {
    // ...
    @PostMapping("/login")
    public boolean login(String username, String password) {
        User user = userDao.findByUserName(username);
        if (user == null) {
            // обработка варианта с несуществующим пользователем
            return false;
        }
        if (!user.getPassword().equals(hashed(password))) {
            // обработка неверного пароля
            return false;
        }
        // 'Ю-ху, залогинorсь!';
        // установите cookies, делайте, что угодно
        return true;
    }
}
الآن قد يقرر فريقك (وربما يقنع رجال الأعمال) أن هذا الأمر بسيط للغاية وممل، فبدلاً من كتابة خدمة تسجيل دخول، من الأفضل كتابة خدمة UserStateChanged الصغيرة المفيدة حقًا دون أي آثار تجارية حقيقية وملموسة. وبما أن بعض الأشخاص يتعاملون حاليًا مع Java مثل الديناصورات، فلنكتب خدمة UserStateChanged الصغيرة بلغة Erlang العصرية. ودعنا نحاول استخدام الأشجار ذات اللون الأحمر والأسود في مكان ما، لأن Steve Yegge كتب أنه يتعين عليك معرفتها من الداخل إلى الخارج حتى تتمكن من التقديم إلى Google. من منظور التكامل والصيانة والتصميم الشامل، يعد هذا أمرًا سيئًا مثل كتابة طبقات من أكواد السباغيتي داخل قطعة واحدة متراصة. مثال مصطنع وعادي؟ هذا صحيح. ومع ذلك، يمكن أن يحدث هذا في الواقع.

قطع أقل - فهم أقل

ثم يطرح السؤال بطبيعة الحال حول فهم النظام ككل وعملياته وتدفقات العمل، ولكن في نفس الوقت أنت كمطور مسؤول فقط عن العمل على الخدمة الصغيرة المعزولة [95:login-101:updateUserProfile]. إنه ينسجم مع الفقرة السابقة، ولكن اعتمادًا على مؤسستك ومستوى الثقة والتواصل، يمكن أن يؤدي ذلك إلى الكثير من الارتباك والتجاهل وإلقاء اللوم في حالة حدوث عطل عرضي في سلسلة الخدمات الصغيرة. وليس هناك من يتحمل المسؤولية الكاملة عما حدث. وهذه ليست مسألة خيانة الأمانة على الإطلاق. في الواقع، من الصعب جدًا ربط الأجزاء المختلفة وفهم مكانها في الصورة العامة للمشروع.

الاتصالات والخدمة

يختلف مستوى الاتصال والخدمة بشكل كبير حسب حجم الشركة. ومع ذلك، فإن العلاقة العامة واضحة: كلما زاد عددها، زادت المشكلة.
  • من يدير الخدمة الصغيرة رقم 47؟
  • هل قاموا للتو بنشر إصدار جديد غير متوافق من الخدمة المصغرة؟ أين تم توثيق ذلك؟
  • من الذي يجب أن أتحدث معه لطلب ميزة جديدة؟
  • من سيدعم تلك الخدمة الصغيرة في Erlang، بعد أن ترك الشركة الشخص الوحيد الذي يعرف هذه اللغة؟
  • لا تعمل جميع فرق الخدمات الصغيرة لدينا بلغات برمجة مختلفة فحسب، بل تعمل أيضًا في مناطق زمنية مختلفة! كيف ننسق كل هذا بشكل صحيح؟
دليل لخدمات جافا الصغيرة.  الجزء 3: أسئلة عامة - 6النقطة الأساسية هي أنه، كما هو الحال مع DevOps، فإن النهج الكامل للخدمات الصغيرة في شركة كبيرة، وربما حتى دولية، يأتي مع مجموعة من مشكلات الاتصال الإضافية. ويجب على الشركة الاستعداد بجدية لذلك.

الاستنتاجات

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

خدمات صغيرة أم متراصة؟

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

تولد الخدمات الصغيرة تعقيدًا إضافيًا

ضع في اعتبارك أنه كلما زاد عدد الخدمات الصغيرة لديك وقلّت قوة DevOps لديك (لا، لا يتم احتساب تشغيل بعض البرامج النصية Ansible أو النشر إلى Heroku!) حتى مجرد القراءة حتى نهاية القسم المخصص للأسئلة العامة حول خدمات Java الصغيرة في هذا الدليل يعد مهمة شاقة للغاية. فكر مليًا في تنفيذ حلول لجميع مشاكل البنية التحتية هذه وستدرك فجأة أن الأمر لم يعد يتعلق ببرمجة الأعمال (ما تحصل على أموال مقابل القيام به) بل يتعلق بإصلاح المزيد من التكنولوجيا على المزيد من التكنولوجيا. لخص شيفا براساد ريدي الأمر بشكل مثالي في مدونته : "ليس لديك أي فكرة عن مدى فظاعة الأمر عندما يقضي الفريق 70% من الوقت في صراع مع هذه البنية التحتية الحديثة ولا يتبقى سوى 30% من الوقت للقيام بمنطق العمل الفعلي. " شيفا براساد ريدي

هل يستحق إنشاء خدمات Java الصغيرة؟

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

سيناريو

تخيل أن لديك وحدة Java متراصة تعمل بمفردها على أصغر خادم مخصص من Hetzner . وينطبق الشيء نفسه على خادم قاعدة البيانات الخاصة بك، فهو يعمل أيضًا على جهاز Hetzner مماثل . ولنفترض أيضًا أن وحدة Java الخاصة بك يمكنها التعامل مع سير العمل، مثل تسجيل المستخدم، وأنك لا تقوم بإنشاء مئات من استعلامات قاعدة البيانات لكل سير عمل، ولكن عددًا أكثر معقولية (<10).

سؤال

ما عدد اتصالات قاعدة البيانات التي يجب أن يفتحها Java monolith (تجمع الاتصال) على خادم قاعدة البيانات الخاصة بك؟ لماذا هذا؟ ما هو عدد المستخدمين النشطين المتزامنين الذين تعتقد أن بإمكانهم توسيع نطاقهم (تقريبًا)؟

إجابة

اترك إجابتك على هذه الأسئلة في قسم التعليقات. وإنني أتطلع إلى جميع الإجابات. دليل لخدمات جافا الصغيرة.  الجزء 3: أسئلة عامة - 8الآن اتخذ قرارك. إذا قرأت حتى النهاية، فنحن ممتنون جدًا لك!
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION