Мікропослуги: як обробляти відносини із зовнішніми ключами


85

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

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

Приклад: Я розробляю функцію доставки (мікросервіс 1) для продуктів, а певні товари доставляються лише до певних місць, як зазначено в таблиці товарів, доступних лише для мікросервісів продуктів (mircoservice 2).

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

Відповіді:


71

Можна використовувати спільну базу даних для декількох мікросервісів. Ви можете знайти схеми управління даними мікросервісів за цим посиланням: http://microservices.io/patterns/data/database-per-service.html . До речі, це дуже корисний блог для архітектури мікропослуг.

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

У вашому прикладі служба доставки може дублювати місця доставки та інформацію про товар. Служба продуктів керує продуктами та місцями. Потім необхідні дані копіюються в базу даних служби доставки з асинхронними повідомленнями (наприклад, ви можете використовувати rabbit mq або apache kafka). Служба доставки не змінює дані про товар та місцезнаходження, але використовує дані, коли виконує свою роботу. Якщо частина даних про товар, яка використовується службою доставки, часто змінюється, дублювання даних за допомогою асинхронних повідомлень буде дуже дорогим. У цьому випадку вам слід здійснювати API-дзвінки між Продуктом та Службою доставки. Служба доставки просить Службу продуктів перевірити, чи можна доставити товар у певне місце чи ні. Служба доставки запитує послугу «Продукти» з ідентифікатором (ім’я, ідентифікатор тощо) товару та місцезнаходження. Ці ідентифікатори можна взяти у кінцевого користувача або спільно використовувати їх між мікросервісами. Оскільки бази даних мікросервісів тут різні, ми не можемо визначити зовнішні ключі між даними цих мікросервісів.

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


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

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

1
Насправді чудова відповідь!
TS

2
Але, ви зберігаєте зовнішній ключ? Приклад: Кожна публікація в блозі матиме багато коментарів. Моноліт матиме таблицю коментарів із зовнішнім ключем до публікації в блозі. Однак у мікросервісі ми матимемо дві послуги. Послуга 1: Опублікувати мікросервіс із цими полями таблиці (PostID, ім’я, вміст) Послуга 2: Коментувати мікросервіс із цими полями таблиці (CommentID, PostID, Cpmment) Питання полягає в тому, чи потрібен нам „PostID” у службі 2 (коментарі Microservice)? Думаю, відповідь так, оскільки нам потрібно знати, який коментар належить до якої публікації. Чи правильно розумію моє розуміння?
rakesh mehra

1
Як розділити систему на мікросервіси - це зовсім інша історія, але якщо ви вирішили створити 2 мікросервіси, такі як публікація та коментар, вам потрібен ідентифікатор публікації мікросервісу коментарів, оскільки кожен коментар належить до публікації. Однак це не означає, що вам потрібно визначати FK між цими таблицями. FK - це лише обмеження у світі RDBMS, яке допомагає забезпечити цілісність та узгодженість даних. Якщо ви зберігаєте дані цих мікросервісів на окремих схемах, ви не можете визначити FK або навіть можете зберігати дані на nosql db (що має сенс для мікросервісу коментарів), де FK не застосовується.
Ali Sağlam

24

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

Інший момент полягає в тому, що лише один компонент у вашій системі володіє даними (для операцій зі зміною стану), інші компоненти можуть ЧИТАТИ, але НЕ ПИСАТИ, вони можуть мати копії даних або ви можете поділитися моделлю подання, яку вони можуть використовувати для отримання останнього стану об'єкта.

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

Подивіться на доповідь Уді Дахан у NDC Осло, щоб отримати докладнішу інформацію

Сподіваюся, це допомагає


2
Посилання на розмову Уді Дахан дуже цікаве
Коменкау,

3

перше рішення: Склад API

 Implement a query by defining an API Composer, which invoking the
 services that own the data and performs an in-memory join of the
 results

введіть тут опис зображення

друге рішення: CQRS

Define a view database, which is a read-only replica that is designed to support that 
query. The application keeps the replica up to data by subscribing to Domain events 
published by the service that own the data.

введіть тут опис зображення


1

Оновлення цієї відповіді до 2020 року полягає у використанні інструменту зміни даних, як Debezium. Debezium контролюватиме таблиці вашої бази даних на наявність змін та передаватиме їх у Kafka / Pulsar (інші канали), а ваші абоненти зможуть потім фіксувати зміни та синхронізувати їх.

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