Мікросервіси

pic

Протягом останнього десятиліття архітектура мікросервісів (Microservices Architecture) набрала значної популярності та була прийнята багатьма компаніями. Деякі великі технологічні компанії, такі як Netflix і Uber, активно використовують мікросервісну архітектуру. Однак багато команд приймають її через модні тенденції і впроваджують без належного обдумування. У цій статті я розповім, на що варто звернути увагу перед використанням мікросервісів. Але перед тим давайте спершу обговоримо монолітну архітектуру.

Монолітна архітектура

Один з традиційних підходів, що спадає на думку при розробці додатків, — це використання монолітної архітектури, і цей підхід вважається простішим у порівнянні з мікросервісами. Наприклад, у 3-рівневому додатку ми маємо фронтенд, бекенд і базу даних. Бізнес-логіка реалізується на стороні бекенду. Початкові архітектурні рішення значно впливають на те, як буде розвиватися наш додаток. Залежно від масштабу проєкту ми можемо вибирати такі архітектури, як MVC (Model-View-Controller), Clean Architecture, DDD (Domain-Driven Design), Hexagonal Architecture тощо.

У сьогоднішньому швидкоплинному ринку бізнеси швидко адаптуються, щоб задовольнити потреби своїх клієнтів. Коли ми вводимо нові функції, наш монолітний додаток стає більшим і більшим. Якщо наша архітектура стає не підтримуваною, ми можемо опинитися в ситуації, коли це просто "велика грудка бруду". Як тільки монолітна архітектура стає неорганізованою, команди стикаються з труднощами при додаванні нових функцій, а завдання починають вимагати більше зусиль. Також учасники команди можуть відчувати постійний страх змінювати щось, побоюючись, що це може порушити роботу додатку. Щоб вирішити ці проблеми, команди можуть ввести архітектурні зміни або навіть переписати весь додаток у деяких випадках.

Варто зазначити, що рішення про використання мікросервісів не завжди є наслідком проблем з обслуговуванням. Наприклад, команди можуть впроваджувати мікросервіси через організаційні вимоги, потреби в масштабуванні або інші фактори, специфічні для проєкту. Однак важливо розуміти всі плюси та мінуси мікросервісів, оскільки жодне рішення не є панацеєю.

Мікросервіси

Мікросервіси — це маленькі сервіси, які працюють разом для досягнення бізнес-цілей. Поняття "маленький" є відносним і залежить від багатьох факторів, таких як розмір проєкту, організаційна структура та інше. Як пише Сем Ньюмен у своїй книзі "Будування мікросервісів" (Building Microservices), як тільки частина коду не здається занадто великою, це, ймовірно, і є малим. Так що ж робить сервіс хорошим? Хороший сервіс легко масштабувати, замінити, розгорнути незалежно від інших сервісів і він стійкий до каскадних збоїв, коли щось ламається. Тепер давайте детальніше розглянемо характеристики хорошого сервісу.

Масштабованість

Уявіть, що ви працюєте над додатком, який пропонує спеціальні пропозиції під час подій, таких як Чорна п'ятниця. Завдяки мікросервісам ви можете масштабувати ваш сервіс оформлення замовлення незалежно, щоб обробляти піки трафіку. В протилежність, у монолітному додатку приплив клієнтів може перевантажити всю систему, що призведе до її сповільнення.

Ізольоване розгортання

Великий монолітний додаток завжди вимагає певних міркувань перед розгортанням змін на виробництво. Це тому, що навіть невеликі зміни вимагають повторного розгортання всього додатку. Це може уповільнити релізи та створити постійний страх змінювати щось, оскільки весь додаток необхідно перезавантажити. Натомість, з незалежно розгортаються сервісами зміни можна випускати швидко, не впливаючи на інші частини системи. Це дозволяє організаціям надавати командам можливість працювати автономно в деяких межах.

Замінність

Маленькі сервіси легше замінити, оскільки вартість їх переписування набагато менша, ніж переписування великого монолітного додатку. Така гнучкість дозволяє командам вибирати різні технології залежно від потреб.

Загалом, хороші мікросервіси мають багато якісних характеристик, і справа в тому, щоб знайти правильний баланс. Однак реалізувати їх належним чином часто складніше, ніж здається.
Вони вводять багато складнощів, які команда повинна управляти, і часто ці складнощі неможливо ефективно контролювати через пріоритети бізнесу. Крім того, мікросервіси можуть бути неправильно впроваджені через обмежений досвід команди та інші фактори.

Компроміси

Існує багато компромісів, які потрібно враховувати при впровадженні мікросервісів. Важливо зазначити, що рішення вибираються на основі таких факторів, як розмір проєкту, його масштаб, організаційна структура та інше. Тепер давайте розглянемо ключові фактори, які визначають успіх мікросервісів.

  • Зв'язок / Згуртованість
  • Обмежені контексти
  • Інтеграція
  • Транзакційні межі / Агрегація даних
  • Спільні бібліотеки
  • Комунікація між сервісами
  • Мікро / Макро архітектура

Зв'язок і згуртованість

Зв'язок (Coupling) визначає ступінь залежності між різними сервісами, а згуртованість (Cohesion) вказує на те, як тісно пов'язані та об'єднані компоненти всередині одного сервісу. Ефективність наших мікросервісів, зрештою, зводиться до цих двох основних принципів. Ідеально, ми прагнемо мати сервіси, які є слабо пов'язаними та високо згуртованими, щоб досягти бажаних якостей. Отже, як реалізувати такі сервіси? Спершу потрібно визначити бізнес-обмеження і створити сервіси, які відображають ці межі.

Обмежений контекст

В DDD (Domain-Driven Design) ми знайомі з поняттям обмежених контекстів (Bounded Contexts). Обмежений контекст — це область, де окремі бізнес-моделі можуть розвиватися незалежно. Якщо ми неправильно визначимо обмежені контексти, ми ризикуємо створити сервіси, які будуть протилежними тому, що ми хочемо. Наприклад, погано визначені обмежені контексти можуть призвести до сильно пов'язаних сервісів, які не можуть бути розгорнуті незалежно, або з організаційної точки зору команди можуть втратити свою автономію. Як правильно визначити обмежені контексти? Щоб коректно визначити обмежені контексти, потрібно мати глибоке розуміння предметної області. Наприклад, якщо ви працюєте над системою підтримки клієнтів, глибоке розуміння цієї області важливе для визначення обмежених контекстів. Саме тому часто краще починати з монолітного підходу, поки не з’явиться чітке уявлення про обмежені контексти, якщо у вас немає вже глибоких знань про предметну область та її підобласті. Коли ви здобудете ці знання, можна буде розділити ваш монолітний додаток на грубі сервіси. Пам’ятайте, що передчасне подрібнення не дасть вам побачити всю картину.

Інтеграція

Існує багато способів і технологій, за допомогою яких можна налагодити комунікацію між сервісами. Важливо мати чітко визначені принципи та правила, щоб уникнути хаосу в інтеграції. Існують два популярні мережеві моделі, які використовуються в мікросервісах: запит/відповідь (як синхронний, так і асинхронний) і подієво-орієнтований підхід (event-driven), причому багато технологій побудовано на цих моделях. Вибір технології комунікації безпосередньо впливає на зв'язок між нашими сервісами. Припустимо, ви вибрали синхронну модель запит/відповідь (за допомогою REST API). Ви можете зіткнутися з деякими проблемами, наприклад, що відбувається, якщо сервіс нижнього рівня недоступний або якщо відповідь приходить пізніше, ніж очікувалось. Отже, ваш сервіс певною мірою буде залежати від сервісів нижнього рівня. Натомість, подієво-орієнтований підхід дає більше гнучкості в тому, як сервіси нижнього рівня реагують на зміни, оскільки це не є основною турботою вашого сервісу. Незалежно від вашого вибору, загальні проблеми, такі як зворотна сумісність даних, оркестрація та інші, все одно існують. Саме тому рекомендується встановити принципи, що обмежують використання технологій інтеграції, щоб допомогти уникнути хаосу в інтеграції.

Транзакційні межі / Агрегація даних

У монолітних додатках транзакції зазвичай не є проблемою. Наприклад, ми можемо використовувати багато баз даних, які відповідають вимогам ACID, для атомарного виконання кількох запитів через транзакції. Однак у розподіленій системі з сутностями, що розподілені по різних вузлах, це стає проблемою. Крім того, ми більше не можемо використовувати об'єднання (joins).
Нам потрібно придумати альтернативні рішення для вирішення цих проблем. Наприклад, якщо сервіс нижнього рівня (downstream service) виявляється недоступним, поки сервіс верхнього рівня (upstream service) виконує транзакцію в своїй базі даних, необхідно застосовувати механізми повторних спроб. Альтернативно, ми можемо використовувати механізм двофазної фіксації (Two-Phase Commit), але для цього необхідно зрозуміти його наслідки до застосування. Інший приклад — це звітність про дані, яка потребує збору даних з кількох джерел. Є кілька рішень з різними компромісами, таких як агрегація через виклики сервісів, використання data pump або застосування подієво-орієнтованого data pump. В кінцевому підсумку, потрібно визначити, яке рішення найкраще підходить для вашого конкретного випадку.

Спільні бібліотеки (Shared Libraries)

Іноді неминуче потрібно виконувати однакові завдання в кількох сервісах. Однак необхідно бути обережним при використанні або створенні спільних бібліотек. Це може призвести до втрати незалежності при розгортанні, що є небажаним результатом. Іноді вартість використання спільної бібліотеки вища, ніж вартість її дублювання. Зазвичай краще уникати надмірного використання спільних бібліотек.

Рішення щодо мікро/макро архітектури

Важливо приймати рішення щодо як мікро, так і макро архітектури. Компоненти повинні бути розміщені на відповідному рівні мікро або макро архітектури на основі кількох факторів. Наприклад, слід враховувати кваліфікацію команди, і рішення не повинні демотивувати учасників команди. Наприклад, мови програмування та фреймворки можна розглядати як частину мікро архітектури, оскільки ми можемо вибрати відповідні технології для кожного сервісу або визначити подієво-орієнтований асинхронний механізм комунікації як рішення макро архітектури, якому повинні слідувати всі сервіси. Інші приклади включають налаштування, моніторинг, аналіз журналів тощо. Ці рішення приймаються на основі різних факторів і можуть відрізнятися від команди до команди.

Висновок

Підсумовуючи, архітектура мікросервісів не є універсальним рішенням для всіх випадків. Хоча вона пропонує багато переваг, вона також вносить складність і витрати, які повинні бути ретельно враховані. Важливо оцінити переваги та недоліки кожного рішення стосовно конкретних потреб вашого випадку, щоб визначити, чи є це правильним вибором. Крім того, створення сервісів з якісними атрибутами, про які ми говорили вище, вимагає від вашої команди достатнього рівня знань.

Перекладено з: Microservices

Leave a Reply

Your email address will not be published. Required fields are marked *