Для того щоб краще зрозуміти цей шаблон, давайте розглянемо приклади з практики електронної комерції, як-от Amazon та Flipkart.
Типовий сценарій: користувач додає товар у кошик і потім оформлює замовлення, оплачуючи його. Кількість товару на складі зменшується, і після отримання оплати, товар передається партнеру з доставки.
Покупки на сайтах електронної комерції
Розглянемо, як цей сценарій працює в бекенді:
- Монолітна архітектура
У монолітній архітектурі всі ці функціональності — як оформлення замовлення, оплата, оновлення інвентарю та призначення партнера з доставки — реалізовані в одному сервісі. Це дозволяє легко керувати правилами ACID для транзакцій.
Ми можемо розпочати одну транзакцію і зробити все одночасно, наприклад, оновити таблицю замовлень, викликати сторонній сервіс для обробки платежу, оновити таблицю інвентарю та вибрати партнера для доставки.
Усе це означає, що якщо щось піде не так, всі зміни будуть скасовані, оскільки все виконано в межах однієї транзакції.
- Мікросервісна архітектура
У мікросервісах всі функції розподіляються на кілька окремих мікросервісів, таких як сервіс замовлень, окремий сервіс для платежів, інвентаризації та доставки.
Проблема з мікросервісами
Кожен сервіс має власну базу даних, тому транзакції обмежуються лише тим сервісом, який їх створює. Якщо щось піде не так в іншому сервісі, зміни, зроблені в конкретному сервісі, будуть скасовані, а не в інших сервісах.
Якщо замовлення оформлено і сервіс замовлень створює записи в таблиці замовлень, сервіс платежів успішно завершує платіж, але сервіс партнера з доставки не може призначити партнера, то замовлення оформлено, платіж здійснено, але доставка не відбудеться, оскільки партнер з доставки не був призначений/відбувся збій.
Рішення: Шаблон Saga
Цю проблему можна вирішити та зберегти характеристики ACID в розподілених транзакціях, використовуючи шаблон проектування Saga.
Шаблон Saga відслідковує порядок локальних транзакцій у кожній базі даних і створює події для переходу до наступного кроку процесу сервісу. Що ж відбувається, якщо один з сервісів у ланцюгу зазнає помилки? Зміни, зроблені в попередніх послідовностях або сервісах, скасовуються за допомогою помилкової/компенсуючої події.
Ми можемо використати один із двох підходів для впровадження шаблону Saga:
I. Підхід Оркестратора:
У цьому підході один з сервісів у ланцюгу виступає в ролі оркестратора і має повний контроль над відправкою подій іншим сервісам.
Припустимо, що сервіс замовлень виконує роль оркестратора, розглянемо описаний вище сценарій.
Тепер, як показано на діаграмі, коли користувач оформлює замовлення, подія платежу відправляється до сервісу оплати для завершення процесу. Після цього інші події, показані на діаграмі, будуть надіслані для завершення процесу.
Припустимо, що сервіс інвентарю зазнає збоїв, як показано на діаграмі, і не зможе змінити кількість товару. У такому разі сервіс інвентарю створить подію помилки, щоб скасувати зміни, внесені в сервіс платежів та замовлень.
Переваги:
- Сервіс Оркестратор дозволяє централізовано контролювати процес, що допомагає в налагодженні та трасуванні, а також забезпечує належне управління помилками.
Обмеження:
- Тісна зв'язка з оркестраторським сервісом може призвести до єдиної точки відмови.
II.
Підхід хореографії
У цьому підході немає централізованої частини або сервісу, який налаштовує ланцюг подій.
У хореографії, як показано на малюнку, кожен сервіс надсилає подію з одного сервісу до наступного, щоб завершити задачу.
Отже, коли сервіс замовлень завершує дію, він надсилає подію до сервісу оплати. Сервіс оплати потім надсилає подію до сервісу інвентарю і так далі.
Переваги:
- Масштабованість: Кожен сервіс є незалежним, тому немає залежності від одного сервісу, що робить систему більш масштабованою для обробки зростаючого навантаження.
Обмеження:
- Ускладнення налагодження та моніторингу запитів порівняно з іншими підходами.
- Якщо відповідальність за події не буде правильно розподілена, можуть виникнути циклічні залежності.
Перекладено з: Microservices Patterns: Saga Pattern With Example