Ось конспект 20-го ювілейного випуску FWD Talks, присвяченого сервісній та мікросервісній архітектурі.
1. Тема та контекст
Формат: Подкаст FWD Talks, 20-й ювілейний випуск.
Спікери:
- Ведучий — модерує дискусію.
- Ігор Дрезд — досвідчений архітектор, основний фокус на інженерній культурі та інфраструктурі.
- Йожеф Гіса — інженер, доповнює Ігоря прикладами з практики, зокрема щодо автоматизації та AI.
Тема: Глибоке занурення в сервісну (Service-Oriented Architecture, SOA) та мікросервісну архітектури. Обговорюються історичний контекст, критерії розділення, проблеми взаємодії, інфраструктурні виклики та сучасні підходи до їх вирішення.
2. Ключові тези
-
Різниця між сервісом і мікросервісом: Спікери проводять чітку межу. Сервіс — це повноцінний модуль, який реалізує роботу з цілою доменною моделлю (наприклад, товар, замовлення) і має складну бізнес-логіку, яку розробляли місяцями. Мікросервіс — це дрібний, вузькоспеціалізований компонент, який виконує лише одну конкретну функцію (наприклад, завантаження файлу на S3, чат-бот-проксі). Ключова ідея: мікросервіс має бути настільки простим, щоб його можна було переписати за один день.
-
Коли варто розбивати систему на сервіси? Головне правило — це має бути комфортно для організації. Не можна ділити систему заради "краси". Слід враховувати кількість команд, їхню зрілість, процеси DevOps та наявність інфраструктури. Якщо команда не готова до overhead'у (моніторинг, CI/CD, деплой, мережеві проблеми), то розбиття принесе лише біль і сповільнить розробку. Ігор цитує Мартіна Фаулера та Сема Ньюмена: "Не розбивайте систему доти, доки вона не стане занадто складною для управління", "Моноліт має бути дефолтним вибором".
-
Фундамент — це ключ до успіху мікросервісів: Хаотичне створення мікросервісів без підготовки призводить до того, що створення навіть простого сервісу займає цілий спринт. Спікери наголошують, що спочатку потрібно побудувати фундамент: шаблонізувати все (скелетони сервісів, CI/CD, Helm-чарти, бібліотеки, моніторинг). Їхня команда має окрему "Foundation" команду, яка робить так, щоб розробник міг створити новий сервіс за лічені хвилини, не замислюючись про інфраструктуру.
-
Взаємодія сервісів і патерн Circuit Breaker: Сервіси завжди падають — це аксіома. Ключова проблема — це каскадне падіння, коли один повільний сервіс "кладе" весь ланцюжок. Для запобігання цьому обов'язково потрібен Circuit Breaker. Суть: якщо сервіс починає помилятися (наприклад, 3 рази поспіль видає 500), "вимикач" розмикається, і всі наступні запити одразу повертають помилку, не навантажуючи проблемний сервіс. Через деякий час він пропускає один тестовий запит — якщо він успішний, ланцюг відновлюється. Це дає можливість сервісу "вижити" під навантаженням.
3. Технічні деталі
-
Спільні бібліотеки (Shared Libraries):
- Проблема: Коли в сервісах дублюється код (error handling, серіалізація, валідація). Це призводить до проблем із backward compatibility при оновленні бібліотеки в сотнях сервісів.
- Рішення Ігоря (компанія Дрезда): Публічні бібліотеки (на GitHub:
sly/tech). Їх розвиває форум (гільдія) розробників однієї мови (наприклад, PHP). Форуми мають капітана та менторів, які визначають пріоритети. Оновлення бібліотек у 500 сервісах автоматизовано за допомогою AI-агентів, які самі створюють MR, оновлюють залежності та запускають тести.
-
SDK (Service Development Kit) для взаємодії:
- Замість того, щоб ходити напряму в API іншого сервісу, кожен сервіс публікує SDK. Цей SDK включає:
- Інтерфейс з методами та моделями.
- Реальну імплементацію (HTTP-клієнт, який ходить через Internal API Gateway).
- STB/Mock-сервіс (заглушку), який повертає тестові дані без реальних мережевих викликів. Це критично для написання надійних тестів. Якщо інтерфейс змінюється, тести з моками одразу падають, сигналізуючи про проблему.
- Замість того, щоб ходити напряму в API іншого сервісу, кожен сервіс публікує SDK. Цей SDK включає:
-
Internal API Gateway:
- Уся внутрішня комунікація між сервісами йде через єдиний Internal API Gateway. Він виконує роль проксі, маршрутизатора і, найголовніше, реалізує Circuit Breaker та Retry логіку в одному місці. Це дозволяє централізовано моніторити трафік між сервісами. Він доступний лише всередині кластера Kubernetes.
-
Компенсаційні flow (Compensating Transactions):
- Критичні бізнес-сценарії повинні мати "план Б". Приклад: якщо сервіс цін недоступний під час оформлення замовлення, система може взяти ціну, яку користувач бачив на фронтенді (навіть якщо вона застаріла), щоб не втратити клієнта. Якщо Order Service впав, замовлення створюється з тимчасовим ID, а після відновлення все синхронізується.
4. Практичні поради
- Починайте з моноліту. Не будуйте мікросервіси одразу. Чекайте, поки моноліт не почне реально заважати (проблеми з розгортанням, тестуванням, залежностями між командами).
- Діліть за доменною моделлю, а не за процесами. Якщо ви створите сервіс "Процес закупівлі", а потім з'явиться схожий "Процес списання", ви отримаєте дублювання логіки. Краще виділити доменні контексти (Товар, Ціна, Склад) і "протягнути" через них процес.
- Інвестуйте в фундамент. Перш ніж починати активно дробити систему, створіть єдиний шаблон для сервісів (скелетон), автоматизований CI/CD з Quality Gates (покриття тестами 60-90%), стандартизований моніторинг та алерти. Це має бути "як сервіс" для розробників.
- Обов'язково використовуйте Circuit Breaker та нормальні тайм-аути. Це врятує вашу архітектуру від каскадних падінь. Пам'ятайте, що сервіси будуть падати, і до цього треба бути готовим.
- Проєктуйте компенсаційні дії. Для кожного критичного сценарію подумайте: "Що ми робитимемо, якщо цей сервіс зараз недоступний?".
- Проводьте Chaos Engineering. Хоча б на стейджингу. Запустіть "обезьянку", яка буде випадково "вбивати" ваші сервіси, щоб перевірити, чи спрацюють ваші захисні механізми (Circuit Breaker, retry, fallback).
- Категоризуйте сервіси за пріоритетом. Базові сервіси (Ціни, Платежі) не мають залежати від другорядних (Рейтинг, Відгуки).
5. Дискусійні моменти
-
Монорепозиторій vs Полірепозиторій: Ведучий та Ігор обговорюють цю вічну дилему. Йожеф скаржиться на "простирадла" з кнопок деплою у фронтовому монорепозиторії. Ігор зазначає, що монорепозиторій гарний для швидкого оновлення спільних бібліотек, але полірепозиторій дає кращу ізоляцію. Обидва сходяться на тому, що немає ідеального рішення, і вибір залежить від зрілості команди та інструментів.
-
"Чи варто створювати мікросервіс для підпису URL на S3?" Йожеф наводить приклад, коли замість простої Lambda-функції вони створили повноцінний мікросервіс з двома подами. Це викликало критику, але він аргументує це тим, що вже за 3 місяці навколо цього з'явиться складна бізнес-логіка обробки файлів. Тобто, іноді варто "закласти" мікросервіс заздалегідь, маючи чітке бачення його еволюції, щоб уникнути потім "запіхування" логіки в неправильне місце.
-
Відповідальність за розвиток інфраструктури: Ігор розповідає про модель "форумів" (гільдій), де самі розробники (а не окрема DevOps команда) пропонують і реалізують ініціативи з покращення бібліотек та інфраструктури. Це вирішує проблему балансу між новим фічами для бізнесу та технічним боргом, але потребує зрілої культури та підтримки від менеджменту.