Владение данными в каждой микрослужбе
Совет
Это содержимое является фрагментом из электронной книги, архитектуры микрослужб .NET для контейнерных приложений .NET, доступных в документации .NET или в виде бесплатного скачиваемого PDF-файла, который можно читать в автономном режиме.
Важное правило архитектуры микрослужб состоит в том, что каждая микрослужба должна быть владельцем своих данных и логики предметной области. Так же как полнофункциональное приложение является владельцем своих логики и данных, так и каждая микрослужба должна быть владельцем своей логики и данных в рамках автономного жизненного цикла, причем развертывание производится независимо для каждой микрослужбы.
Это означает, что концептуальная модель предметной области будет различаться для разных подсистем и микрослужб. Для примера можно взять корпоративное приложение, в котором каждая из подсистем управления отношениями с клиентами (CRM), финансовых транзакций и поддержки клиентов обращается к уникальным атрибутам и данным сущностей и использует собственный ограниченный контекст.
Аналогичный принцип принят в проблемно-ориентированном проектировании (DDD), в котором каждый ограниченный контекст либо автономная подсистема или служба должны быть владельцем своей модели предметной области (состоящей из данных и логики или поведения). Каждый ограниченный контекст DDD сопоставлен с одной бизнес-микрослужбой (одной или несколькими службами). Более подробно о шаблоне ограниченного контекста мы поговорим в следующем разделе.
С другой стороны, традиционный подход (на основе единых данных), применяемый во многих приложениях, предполагает наличие одной централизованной базы данных или небольшого количества баз данных. Часто это нормализованная база данных SQL, которая используется для всего приложения и всех его внутренних подсистем, как показано на рис. 4-7.
Рис. 4-7. Сравнение владения данными: единая база данных и микрослужбы
В традиционном подходе имеется отдельная база данных, совместно используемая всеми службами, как правило, в многоуровневой архитектуре. В подходе с использованием микрослужб каждая микрослужба владеет собственной моделью или данными. Подход на основе централизованной базы данных изначально выглядит более простым и позволяющим повторно использовать сущности в разных подсистемах для обеспечения согласованности. Но в действительности вы в итоге получаете огромные таблицы, обслуживающие множество разных подсистем и содержащие атрибуты и столбцы, которые в большинстве случаев не нужны. Это все равно что пытаться использовать одну и ту же карту для небольшого пешего похода, суточной поездки на автомобиле и изучения географии.
Монолитное приложение, обычно с одной реляционной базой данных, имеет два важных преимущества: транзакции, обладающие свойствами атомарности, согласованности, изолированности и долговечности, и язык SQL. Оба этих преимущества распространяются на все таблицы и данные, связанные с приложением. Такой подход позволяет легко писать запросы, объединяющие данные из нескольких таблиц.
Но при переходе на архитектуру микрослужб получать доступ к данным становится сложнее. Даже при использовании транзакций ACID в микрослужбах или ограниченном контексте важно учитывать, что данные, принадлежащие каждой микрослужбе, являются частными для этой микрослужбы и должны быть доступны только синхронно через соответствующие конечные точки API (gRPC, SOAP и т. д.) или асинхронно через систему обмена сообщениями (AMQP и т. д.).
Инкапсуляция данных делает микрослужбы слабосвязанными, благодаря чему они могут изменяться независимо друг от друга. Если бы несколько служб обращались к одним и тем же данным, изменения схемы требовали бы согласованного изменения всех служб. При этом автономность жизненного цикла микрослужб нарушалась бы. Однако распределенные структуры данных означают невозможность выполнения транзакции, обладающей свойствами атомарности, согласованности, изолированности и долговечности, в рамках нескольких микрослужб. Из этого, в свою очередь, следует, что если бизнес-процесс охватывает несколько микрослужб, необходимо обеспечивать итоговую согласованность. Это гораздо сложнее в реализации, чем простые соединения SQL, поскольку невозможно создать ограничения целостности или использовать распределенные транзакции между отдельными базами данных, как мы объясним позднее. Аналогичным образом многие другие возможности реляционных баз данных недоступны в рамках нескольких микрослужб.
Если разбираться дальше, микрослужбы часто используют базы данных разных типов. Современные приложения хранят и обрабатывают разнообразные типы данных, и реляционная база данных — не всегда лучший выбор. В некоторых ситуациях база данных NoSQL, например Azure CosmosDB или MongoDB, может иметь более удобную модель данных и обеспечивать более высокую производительность и масштабируемость по сравнению с базой данных SQL, например SQL Server или базой данных SQL Azure. В других случаях реляционная база данных по-прежнему является оптимальным решением. По этой причине в приложениях на основе микрослужб часто используется сочетание баз данных SQL и NoSQL. Такой подход иногда называют разнородным хранением данных.
Секционированная архитектура разнородного хранения данных имеет много преимуществ. К ним относятся слабая связь между службами, более высокая производительность и масштабируемость, снижение затрат и лучшая управляемость. Однако может возникнуть ряд проблем с распределенным управлением данными, которые рассмотрены в разделе Определение границ модели предметной области далее в этой главе.
Связь между микрослужбами и шаблоном ограниченного контекста
Концепция микрослужбы является производной от шаблона ограниченного контекста в проблемно-ориентированном проектировании (DDD). В DDD большие модели разделяются на несколько ограниченных контекстов с явно определенными границами между ними. Каждый ограниченный контекст должен иметь собственную модель и базу данных, так же как каждая микрослужба является владельцем связанных с ней данных. Кроме того, каждый ограниченный контекст обычно имеет собственный единый язык, упрощающий взаимодействие между разработчиками ПО и экспертами в предметных областях.
Термины единого языка (в основном это сущности предметной области) могут иметь разные имена в разных ограниченных контекстах, даже если разные сущности предметной области имеют одинаковый уникальный идентификатор (по которому сущность считывается из хранилища). Например, в ограниченном контексте профиля пользователя сущность предметной области "Пользователь" может иметь тот же идентификатор, что и сущность предметной области "Покупатель" в ограниченном контексте размещения заказов.
Таким образом, микрослужба похожа на ограниченный контекст, но она также определена как распределенная служба. Она создается как отдельный процесс для каждого ограниченного контекста и должна использовать упомянутые ранее распределенные протоколы, такие как HTTP/HTTPS, WebSockets или AMQP. В свою очередь, шаблон ограниченного контекста не указывает, является ли ограниченный контекст распределенной службой или просто логической границей (например, подсистемой общего назначения) в пределах монолитного приложения.
Важно отметить, что сначала желательно определить службу для каждого ограниченного контекста. Однако проектирование необязательно ограничивать этим. Иногда следует спроектировать ограниченный контекст или бизнес-микрослужбу, которые состоят из нескольких физических служб. Но, в конечном счете, оба шаблона (ограниченный контекст и микрослужба) тесно связны друг с другом.
В DDD преимущества микрослужб реализуются путем определения реальных границ в форме распределенных микрослужб. Однако в ограниченном контексте также могут требоваться такие возможности, как отсутствие общей модели для микрослужб.
Дополнительные ресурсы
Крис Ричардсон (Chris Richardson). Шаблон: база данных для каждой службы
https://microservices.io/patterns/data/database-per-service.htmlМартин Фоулер (Martin Fowler). BoundedContext
https://martinfowler.com/bliki/BoundedContext.htmlМартин Фоулер (Martin Fowler). PolyglotPersistence
https://martinfowler.com/bliki/PolyglotPersistence.htmlАльберто Брандолини (Alberto Brandolini). Стратегическое предметно-ориентированное проектирование с сопоставлением контекста
https://www.infoq.com/articles/ddd-contextmapping