Який правильний спосіб синхронізувати дані через мікросервіси?


19

Я відносно новий в архітектурі мікросервісів. У нас є веб-додаток середнього розміру, і я зважую плюси і мінуси розбиття його на мікросервіси замість монолітної системи, яку ми зараз рухаємо вперед.

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

Однак, що, якщо Bзнижується / не вдається і через деякий час, повертається знову. За цей час роботи Aопублікував ще два повідомлення. Як Bзнати, як оновити свою локальну копію Aінформації?

Зрозуміло, якщо Bце єдиний споживач Aчерги, то він може почати читати, як тільки повернеться в Інтернет, але що робити, якщо є інші споживачі цієї черги, і ці повідомлення споживаються?

Як конкретніший приклад, якщо Usersслужба оновлена ​​електронною адресою, коли Billingмікросервіс не працює, якщо Billingмікросервіс знову повертається, як дізнатися, що оновлення оновлено?

Коли мікросервіси повертаються, чи робить це трансляцію із записом "Ей, я резервну копію, дайте мені всю вашу поточну інформацію?"

Взагалі, які найкращі галузеві практики синхронізації даних?


1
Щоб уникнути цього, коли це можливо.
Теластин

1
Чому Ordersпотрібно щось знати Users?
kdgregory

Це просто приклад. Замініть їх на все, що завгодно, що має сенс.
Благородні

маршрутизація вентилятора вирішить вашу проблему "споживається чужою проблемою". але насправді незрозуміло, чого ви намагаєтесь досягти.
Еван

@Ewan Я оновив свій початковий пост, щоб краще пояснити, що я намагаюся запитати.
благородний шлях

Відповіді:


5

Я б оскаржив всю вашу ідею "передачі даних до всіх інших мікросервісів".

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


Я думаю, що ця відповідь є абсолютно правильною. Це усуває багато питань, пов’язаних із синхронізацією. Насправді я зараз переглядаю код, у якого є такі проблеми, оскільки різні служби зберігають копії інформації та мають такі проблеми з синхронізацією.
DaveG

2
Дякую за вашу відповідь. То чому ж тоді виникає потреба у моделі pub / sub та черзі на повідомлення? Якщо ми намагаємося "перетягнути" замість "натискання" даних, ми переживаємо про затримку служби.
благородний шлях

AFAIK, вашій службі не потрібно негайно реагувати, якщо щось змінюється (як у пабі / підрозділі), але періодично потрібні дані. Тоді я б просто потягнув його. Якщо ви турбуєтесь про затримку, ви можете кешувати дані, але це знову ж таки є ціною невідомості, чи дані оновлені. Якщо ваші файли великі, ви також можете запитати, чи щось зміниться, перш ніж щось знову витягнути.
Дж. Фабіан Мейєр

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

@dukethrash Потім зробіть їх доступними.
Дж. Фабіан Мейєр

5

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

Події-джерела

Ідея тут полягає в тому, щоб представляти перехід стану кожної програми у формі незмінної події. Потім події зберігаються у журналі або формі журналу у міру їх виникнення (також їх називають "сховищем подій"). Їх також можна запитувати і зберігати нескінченно, маючи на меті представити, як стан програми в цілому розвивався з часом.

Що допомагає досягти цього, це те, що якщо мікросервіс знижується, а інші події, пов'язані з ним, публікуються, а події споживаються, скажімо, іншими екземплярами цієї мікросервісу, коли ця мікросервіс повертається назад, вона може звернутися до цього, event storeщоб отримати все події, які він пропустив протягом періоду, коли він знизився.

Apache Kafka як брокер подій

Розглянемо використання Apache Kafka, який може зберігати та відправляти тисячі подій в секунду та має вбудовані механізми реплікації та відмовостійкості. У ньому зберігається постійний запас подій, які можна зберігати на диску нескінченно і споживати в будь-який час (але не видаляти) з теми (нарядною чергою Кафки).

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

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

Саги

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

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


Я досі не розумію, чому ви хочете побудувати таку складну структуру. Зазвичай набагато простіше, якщо кожна служба просто зберігає власні дані та надає їх іншим службам на запит.
Дж. Фабіан Мейєр

^ Але це зменшить доступність системи. Складна конструкція може бути гарантована, якщо потрібна висока стійкість.
Авмохан

1

Навіть якщо я спізнююсь, я б поставив свої аргументи на два центи, тому що я вважаю, що це важливий момент, коли ви хочете оцінити дизайн архітектури мікросервісів, керованих подіями. Кожна мікросервіс точно знає, які саме події впливають на її стан, і здатна їх чекати. Коли мікросервіс недоступний, повинен бути компонент, який зберігає повідомлення, необхідні від невдалої мікросервісу, поки вона не зможе їх "споживати". Насправді це модель «виробник / споживач», а не «опублікувати / підписатись». Брокери повідомлень (наприклад, Kafka, RabbitMQ, ActiveMQ тощо), як правило, найкращий спосіб досягти такої поведінки (якщо ви не реалізуєте щось інше, наприклад, пошук подій), забезпечуючи стійкі черги та механізм ack / nack.

Тепер мікросервіс знає, що повідомлення в кінцевому рахунку доставляється, але його недостатньо: який спосіб очікувати доставки одного повідомлення? чи може він керувати доставкою декількох копій одного і того ж повідомлення про подію? Це питання доставки семантично (принаймні один раз, рівно один раз)

Заключна думка (и):

  1. Коли ви додаєте до своєї архітектури мікросервіс, який потребує споживання подій від інших, ви повинні зробити першу синхронізацію

  2. Навіть брокер може вийти з ладу, в цьому випадку повідомлення втрачаються

в обох сценаріях було б корисно мати прості механізми для повторного зволоження стану мікрообслуговування. Це може бути API REST або сценарій, який надсилає повідомлення, але найголовніше - мати засоби для виконання певного завдання з обслуговування


0

Ви можете замінити звичайну чергу подій на модель видавця / підписника, де Aслужба публікує нове повідомлення теми T і Bтипу мікросервісів, які підписалися б на ту саму тему.

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


0

Якщо повідомлення надсилається повідомленням про те, що щось змінилося, B може споживати це повідомлення і копіювати локальну копію інформації A і використовувати це для того, щоб робити все, що потрібно зробити B.

Якщо ви хотіли, щоб B мав доступ до внутрішніх даних A, вам було б краще просто надати їй доступ до внутрішніх баз даних A.

Однак ви не повинні цього робити, вся суть архітектури, орієнтованої на сервіс, полягає в тому, що служба B не може бачити внутрішній стан служби A і обмежена для запитів через API REST (і навпаки).

У вашому випадку ви можете мати службу даних користувачів, яка несе відповідальність за збереження всіх даних користувачів. Інші сервіси, які хочуть використовувати ці дані, запитують їх лише тоді, коли вони потребують, і не зберігають локальну копію (що btw. Дуже корисно, якщо ви думаєте про відповідність GDPR). Служба даних користувачів може підтримувати прості CRUD-операції, такі як "Створити нового користувача" або "Змінити ім'я для user_id 23", або він може виконати складніші операції. "Знайдіть усіх стандартних користувачів з днем ​​народження в найближчі 2 тижні та надайте їм статус пробної премії ". Тепер, коли вашій службі виставлення рахунків потрібно надіслати електронний лист користувачу 42, він запитає службу даних користувачів "Яка адреса електронної пошти для user_id 42", використовуватиме її внутрішні дані з усією платіжною інформацією для оброблення електронної пошти, а потім може передати електронну пошту електронна адреса та тіло на поштовому сервері.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.