لطالما كانت بنية الخدمات المصغرة المعيار الفعلي في تطوير الأنظمة الكبيرة والمعقدة. له عدد من المزايا: إنه تقسيم صارم إلى وحدات ، وضعف الاتصال ، ومقاومة الفشل ، والخروج التدريجي للإنتاج ، وإصدار مستقل للمكونات.
صحيح ، في كثير من الأحيان ، عند الحديث عن بنية الخدمات الصغيرة ، يتم ذكر بنية الواجهة الخلفية فقط ، ولا تزال الواجهة الأمامية كما هي ، متجانسة. اتضح أننا قدمنا دعمًا رائعًا ، وسحبتنا الجبهة للخلف.
اليوم ، سأخبرك كيف قمنا بواجهة الخدمة الصغيرة في حل SaaS الخاص بنا وما هي المشاكل التي واجهناها.
العدد
في البداية ، بدا التطور في شركتنا كما يلي: هناك العديد من الفرق المشاركة في تطوير الخدمات الدقيقة ، كل منها ينشر API الخاص به. وهناك فريق منفصل يقوم بتطوير SPA للمستخدم النهائي ، وذلك باستخدام API للخدمات الصغيرة المختلفة. باستخدام هذا النهج ، يعمل كل شيء: يعرف مطورو الخدمات المصغرة كل شيء عن تنفيذها ، ويعرف مطورو SPA جميع تعقيدات تفاعلات المستخدم. ولكن كانت هناك مشكلة: الآن يجب أن تعرف كل واجهة أمامية جميع تعقيدات جميع الخدمات الصغيرة. هناك المزيد والمزيد من الخدمات الدقيقة ، وهناك المزيد والمزيد من مقدمي الخدمات الأمامية - وبدأت Agile تنهار ، كما يظهر التخصص داخل الفريق ، أي اختفاء التبادلية والعالمية.
لذلك وصلنا إلى المرحلة التالية - التطوير المعياري. تم تقسيم فريق الواجهة إلى أوامر فرعية. كان كل منهم مسؤولا عن جزء من التطبيق. لقد أصبح أفضل بكثير ، ولكن مع مرور الوقت ، استنفد هذا النهج نفسه لعدة أسباب.
- جميع الوحدات غير متجانسة ، مع تفاصيلها الخاصة. لكل وحدة ، التكنولوجيا الخاصة بها هي الأنسب. في الوقت نفسه ، يعد اختيار التكنولوجيا مهمة صعبة في ظروف SPA.
- نظرًا لأن تطبيق SPA (وفي العالم الحديث هذا يعني تجميع في حزمة واحدة أو على الأقل تجميع) ، يمكن فقط إصدار التطبيق بالكامل في نفس الوقت. يتزايد خطر كل تسليم.
- إن إدارة التبعية تصبح أكثر صعوبة. تحتاج الوحدات المختلفة إلى إصدارات تبعية مختلفة (ربما محددة). شخص ما ليس مستعدًا للتبديل إلى واجهة برمجة تطبيقات التبعية المحدثة ، ولا يمكن لشخص ما إنشاء ميزة بسبب خطأ في فرع التبعية القديم.
- نظرًا للنقطة الثانية ، يجب مزامنة دورة التحرير لجميع الوحدات. الجميع ينتظرون المتقاعسين.
قطع الواجهة
كانت هناك لحظة تراكم للكتلة الحرجة ، وقرروا تقسيم الواجهة الأمامية إلى ... خدمات دقيقة في الواجهة الأمامية. دعنا نحدد ما هي الخدمات الدقيقة الأمامية:
- جزء معزول تمامًا من واجهة المستخدم ، لا يعتمد بأي شكل من الأشكال على الآخرين ؛ عزلة جذرية وضعت حرفيا كتطبيق مستقل ؛
- كل خدمة أمامية صغيرة مسؤولة عن مجموعة معينة من وظائف الأعمال من البداية إلى النهاية ، أي أنها تعمل بكامل طاقتها في حد ذاتها ؛
- يمكن كتابتها على أي تقنية.
لكننا ذهبنا أبعد من ذلك وقدمنا مستوى آخر من الانقسام.
مفهوم الشظية
نسمي جزءًا عبارة عن حزمة تتكون من
js + css +
. في الواقع ، هذا جزء مستقل من واجهة المستخدم ، والذي يجب أن يتوافق مع مجموعة من قواعد التطوير بحيث يمكن استخدامه في SPA عام. على سبيل المثال ، يجب أن تكون جميع الأنماط محددة قدر الإمكان للجزء. لا ينبغي بذل أي محاولة للتفاعل مباشرة مع الأجزاء الأخرى. يجب أن يكون لديك طريقة خاصة يمكنك من خلالها تمرير عنصر DOM حيث يجب رسم الجزء.
بفضل الواصف ، يمكننا حفظ المعلومات حول جميع الأجزاء المسجلة في البيئة ، ومن ثم الوصول إليها عن طريق المعرّف.
يسمح لك هذا النهج بوضع تطبيقين مكتوبين على أطر عمل مختلفة في صفحة واحدة. كما أنه يجعل من الممكن كتابة رمز عالمي يسمح لك بتحميل الأجزاء الضرورية ديناميكيًا على الصفحة ، وتهيئتها وإدارة دورة الحياة. بالنسبة لمعظم الأطر الحديثة ، يكفي اتباع "قواعد النظافة" لجعل ذلك ممكنًا.
في الحالات التي لا تتاح فيها الفرصة للجزء "للتعايش" مع الآخرين في نفس الصفحة ، هناك نص برمجي احتياطي نرسم فيه الجزء في iframe (حل المشاكل ذات الصلة خارج نطاق هذه المقالة).
كل ما يحتاجه المطور الذي يريد استخدام مقتطف حالي على الصفحة هو:
- قم بتوصيل البرنامج النصي لمنصة الخدمات المصغرة بالصفحة.
<script src="//{URL to static cache service}/api/v1/mui-platform/muiPlatform.js"></script>
- اتصل بطريقة إضافة جزء إلى الصفحة.
window.MUI.createFragment(
أيضا ، للتواصل بين الأجزاء ، هناك حافلة مبنية على
rxjs
و
rxjs
. هو مكتوب على NativeJS. بالإضافة إلى ذلك ، يأتي SDK مع أغلفة لأطر مختلفة تساعد على استخدام هذا الناقل بشكل أصلي. مثال لـ Angular 6 هو طريقة مساعدة تُرجع
rxjs/Observable
:
import {fromEvent} from "@netcracker/mui-platform/angular2-factory/modules/shared/utils/event-utils" fromEvent("<event-name>"); fromEvent(EventClassType);
بالإضافة إلى ذلك ، توفر المنصة مجموعة من الخدمات التي غالبًا ما تستخدمها أجزاء مختلفة وهي أساسية في بنيتنا التحتية. هذه خدمات مثل الأقلمة / التدويل ، خدمة التفويض ، العمل مع ملفات تعريف الارتباط بين النطاقات ، التخزين المحلي وأكثر من ذلك بكثير. لاستخدامها ، توفر SDK أيضًا أغلفة لأطر مختلفة.
الجمع بين الواجهة الأمامية
على سبيل المثال ، يمكننا أن نفكر في هذا النهج في منطقة إدارة SPA (فهو يجمع بين الإعدادات الممكنة المختلفة من الخدمات الصغيرة المختلفة). يمكننا أن نجعل محتويات كل إشارة مرجعية كجزء منفصل ، والتي سيتم تسليمها وتطويرها بشكل منفصل من قبل كل خدمة مايكرو. بفضل هذا ، يمكننا إنشاء "رأس" بسيط يعرض الخدمة المصغرة المقابلة عند النقر على إشارة مرجعية.

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

الخدمات المشتركة
في بنية الخدمات المصغرة ، تظهر الخدمات المركزية حتمًا ، وهي البيانات التي يحتاج إليها الجميع. على سبيل المثال ، خدمة الترجمة التي تخزن الترجمات. إذا بدأت كل خدمة صغيرة بشكل فردي في الصعود لهذه البيانات إلى الخادم ، فإننا نحصل فقط على مجموعة من الطلبات أثناء التهيئة.
لحل هذه المشكلة ، قمنا بتطوير تطبيقات خدمات NativeJS التي توفر الوصول إلى هذه البيانات. هذا جعل من الممكن عدم تقديم طلبات غير ضرورية وبيانات ذاكرة التخزين المؤقت. في بعض الحالات ، حتى إخراج مثل هذه البيانات إلى صفحة بتنسيق HTML مقدمًا للتخلص تمامًا من الطلبات.
بالإضافة إلى ذلك ، تم تطوير الأغلفة على خدماتنا لأطر مختلفة لجعل استخدامها طبيعيًا جدًا (DI ، واجهة ثابتة).
إيجابيات الخدمات الدقيقة الأمامية
أهم شيء نحصل عليه من تقسيم كتلة متجانسة إلى أجزاء هو القدرة على اختيار التقنيات لكل فريق على حدة وإدارة التبعية الشفافة. ولكنه أيضًا يعطي ما يلي:
- مناطق المسؤولية المقسمة بوضوح شديد ؛
- إصدار مستقل: قد يكون لكل جزء دورة إطلاق خاصة به ؛
- زيادة استقرار الحل ككل ، لأن إصدار الأجزاء الفردية لا يؤثر على الآخرين ؛
- القدرة على التراجع عن الميزات بسهولة ، وطرحها للجمهور جزئيًا ؛
- يتم وضع الجزء بسهولة في رأس كل مطور ، مما يؤدي إلى حقيقة
التبادل بين أعضاء الفريق ؛ بالإضافة إلى ذلك ، يمكن لكل واجهة أمامية أن تفهم بشكل أفضل جميع تعقيدات التفاعل مع الواجهة الخلفية المقابلة.
الحل مع الواجهة الأمامية microseris يبدو جيدًا. في الواقع ، الآن يمكن لكل جزء (خدمة صغيرة) أن يقرر بنفسه كيفية النشر: ما إذا كنت بحاجة فقط إلى nginx لتوزيع الإحصائيات ، أو برنامج وسيط كامل لتجميع الطلبات لدعم أو دعم مواقع الويب ، أو بعض التفاصيل الأخرى في شكل بروتوكول نقل بيانات ثنائي داخل http. بالإضافة إلى ذلك ، يمكن للأجزاء اختيار طرق التجميع الخاصة بها ، وطرق التحسين ، والمزيد.
سلبيات الخدمات الدقيقة الأمامية
لا يمكنك أبدًا الاستغناء عن الذبابة في المرهم.
- لا يمكن ضمان التفاعل بين الشظايا بطرق أنبوب قياسية (DI ، على سبيل المثال).
- ماذا تفعل مع التبعيات المشتركة؟ بعد كل شيء ، سيزداد حجم التطبيق بسرعة فائقة ، إذا لم يتم إخراجها من الأجزاء.
- على أي حال ، يجب أن يكون واحد فقط مسؤولاً عن التوجيه في التطبيق النهائي.
- ماذا تفعل إذا كان يتعذر الوصول إلى إحدى الأجزاء / لا يمكن رسمها.
- من غير الواضح ما يجب فعله بحقيقة أن الخدمات الدقيقة المختلفة يمكن أن تكون في مجالات مختلفة.
الخلاصة
أثبتت تجربتنا مع هذا النهج قابليتها للبقاء. زادت سرعة إخراج الميزات في الإنتاج بشكل ملحوظ. تم تقليل عدد التبعيات الضمنية بين أجزاء الواجهة إلى صفر تقريبًا. حصلنا على واجهة مستخدم متسقة. يمكنك اختبار الميزات بأمان دون إشراك عدد كبير من الأشخاص.
لسوء الحظ ، في مقال واحد ، من الصعب جدًا تغطية مجموعة كاملة من المشاكل والحلول التي يمكن العثور عليها في طريقة تكرار مثل هذه البنية. ولكن بالنسبة لنا ، فإن الإيجابيات تفوق السلبيات بشكل واضح. إذا أبدى هابر اهتمامًا بالكشف عن تفاصيل تنفيذ هذا النهج ، فسنكتب تكملة!