В этом посте я расскажу о том, как мы используем DDD в Augury и наши уникальные бизнес-требования для создания руководства по архитектуре микросервисов, сосредоточившись на трех общих паттернах. Мы используем это руководство и определения, чтобы решить, когда создавать новый микросервис и как распределить нашу доменную логику по этим сервисам. Если вы не читали предыдущую статью и вам интересно, с чего все началось, ссылка прилагается.
Определения DDD
Ограниченный контекст (BC) — это совокупность взаимосвязанных областей\ бизнес-требований в нашем продукте. По мере развития нашего продукта рождается все больше BC. В DDD, BC содержит один или более агрегатов (Aggregates).
![](https://habrastorage.org/getpro/habr/upload_files/d91/fdf/727/d91fdf7274c87a10a0ccd785869138fc.png)
Агрегат (Aggregate) — это кластер ассоциированных объектов, которые мы рассматриваем как единое целое при изменении данных. Также часто называемый как бизнес-модель.
Агрегат содержит следующие члены:
![](https://habrastorage.org/getpro/habr/upload_files/ff8/519/682/ff85196820c0801a16d2fc287c8fdccd.png)
Entity (Сущность) — объект, фундаментально определяемый не его атрибутами, а принципом последовательности и идентичности, например, компонент внутри машины.
Value Object (Объект-значение) — объект, который описывает некоторую характеристику или атрибут, но не несет в себе концепции идентичности. В большинстве случаев это просто некоторые поля, вложенные в сущность. Например, поле имени.
Aggregate Root (Корень агрегата) — это единственная определенная сущность, содержащаяся в агрегате.
Поскольку мы видим возможные типы агрегатов в системе, то можем свести их к двум:
(Simple aggregate) Простой агрегат — его корневая сущность создается с помощью какой-либо команды
Complex Aggregate (Сложный агрегат) — его корневая сущность создается\обновляется через события домена, одиночные или множественные, от разных агрегатов. Это приводит к тому, что его основная сущность должна знать больше о других доменах для выполнения своих бизнес-требований.
![](https://habrastorage.org/getpro/habr/upload_files/e43/c18/ba6/e43c18ba60c64db1595483bfde6102d1.png)
Практические архитектурные паттерны
В этой теме мы рассмотрим три паттерна:
Aggregate Microservice (Агрегат Микросервиса) — микросервис, инкапсулирующий агрегат.
Complex aggregate Microservice (Сложного агрегат Микросервиса) — микросервис, инкапсулирующий сложный агрегат.
Bounded context Microservice (Ограниченный контекст в Микросервисе) — микросервис, инкапсулирующий ограниченный контекст.
Вы можете удивиться, почему мы решили представить в нашей системе все три варианта. Изучая DDD и то, как различные компании превращают теоретические разработки в практические компоненты, можно найти несколько аргументов. Одним из них является гранулярность нашей системы. То есть, какой самый маленький независимый технический компонент у нас есть? Как мы видели, у нас есть два варианта: агрегат и ограниченный контекст в микросервисе.
Давайте рассмотрим наши потребности в рамках компании 一
Соответствие продукта рынку — наш основной продукт достиг соответствия рынку, это означает, что у нас есть (в этих областях) согласованный ограниченный контекст, интерфейсы и агрегаты.
Рост — Augury увеличила число клиентов и разработчиков. Нам нужно поддерживать рост и структуру команды, которая сопровождает эти изменения.
Agile-мышление — хотя наш основной продукт реализован в PMF у нас все еще есть области внутри него или другие продукты, в которых мы чувствуем себя менее уверенно, и они требуют более гибкой среды.
Давайте подумаем о некоторых плюсах и минусах каждого подхода 一
Агрегаты микросервиса:
За: Динамично, так как это самое маленькое представление, которое мы можем отобразить в нашей системе и продукте. Мы всегда можем "перемещать" его из сквада в сквад по мере "созревания" нашего продукта и доработок при моделировании.
Против: Мы рискуем создать “большой ком грязи” [система, в которой отсутствует понятная архитектура]. Предположим, мы неправильно выполним моделирование и установим связи между сервисами некорректно. Все зависимости останутся прежними, но теперь у нас будет еще и распределенная система, что только добавит сложности.
Ограниченный контекст в микросервисе:
За: Меньше сложности, меньше межсервисного взаимодействия, меньше болтовни. Поскольку агрегаты одного и того же ограниченного контекста общаются больше, поэтому они будут делать то же самое в таком же микросервисе.
Против: Мы рискуем создать код и, возможно, модели, сильно зависящие друг от друга. Кроме того, если потребуется разбить ограниченный контекст на два сквада или два ограниченных контекста, то для обеспечения командного права владения каждым техническим компонентом потребуется серьезный рефакторинг.
Решение 一
Мы приняли решение об оптимизации для роста, чтобы быть динамичными, поэтому решили моделировать наши услуги с гранулярностью агрегата микросервиса. Мы предлагаем смягчение риска сложности и “большого комка грязи” путем 一
Добавления архитектурных руководств
Архитекторы участвуют в каждом DR из своей области для консультаций.
Мы создаем высокоуровневое архитектурное видение, которое инкапсулирует агрегаты, ограниченные контексты (сервисы представления, сквозные и оркестратор) и паттерны коммуникации, помогающие избежать подобного.
Ограниченный контекст в микросервисах будет использоваться в основном для юзкейсов продуктовых областей, которые не соответствуют требованиям рынка, это означает, что агрегаты неизвестны и уровень неопределенности высок.
When -> Then (Когда -> Тогда) для создания нового агрегата микросервиса:
Когда в нашей системе имеется бизнес-юнит, имеющий четко определенное и специфическое состояние и идентичность, который требует согласованности транзакций внутри него -> Мы создадим специфический агрегат сервиса.
Когда мы добавляем новый бизнес-юнит как часть MVP -> Мы выберем создание конкретного агрегата сервиса. Это позволит легко удалить его в будущем.
Когда у нового бизнес-юнита в нашей системе есть команды (CRUD) операций -> Рассмотрим его как агрегат с новым агрегатом сервиса.
Когда новому бизнес-юниту нужно будет использовать даже существующий домен -> Считайте это новым агрегатом (поскольку он разделен продюсером).
Когда -> Тогда чтобы оставаться в том же агрегате сервиса:
Когда один агрегат должен обновить другой агрегат и требует согласованности транзакций -> Внимание спойлер, у нас есть архитектурная тема под названием "потоки управления". Это тема №6, и мы до нее доберемся.
Когда нам нужна возможность полного отката -> Мы выберем создание конкретного агрегата сервиса.
Когда -> Тогда, чтобы изменить агрегат микросервиса на сложный агрегат сервиса:
Когда нам нужно изменить состояние агрегатов в зависимости от изменения другого, т.е. при использовании события домена -> Мы выберем переход от обычного агрегата микросервиса к сложному.
Когда нам нужно сохранять данные для оптимизации производительности → Мы рассмотрим переход от агрегата микросервиса к сложному.
Когда у нас нет достаточных знаний/уверенности в своих силах, нам необходимо постоянство -> Мы дважды подумаем, прежде чем сделать наш агрегат сложным.
Когда -> Тогда разбить монолит/агрегат на несколько:
Когда у нас есть агрегат, который в настоящее время размещен в монолите -> Мы выберем создание отдельного агрегата сервиса.
Когда нам не требуется транзакционная согласованность -> Рассмотрим возможность создания другого агрегата микросервиса, так как он, скорее всего, будет несвязанным.
Когда добавляются новые префиксы для эндпоинтов в сервисе -> Рассмотрим возможность создания нового агрегата микросервиса.
Когда поле не связано с агрегатом, но необходимо для некоторой оптимизации -> Рассмотрите возможность создания нового агрегата с минимальными данными из исходного агрегата.
Когда -> Тогда создать микросервис ограниченного контекста:
Когда есть слишком много неизвестных относительно конечной структуры агрегата или агрегатов (т.е. ограниченный контекст) -> Мы выберем создание микросервиса расширенного размера, чтобы обучаться по ходу дела. В будущем мы можем разбить его на несколько агрегатов микросервисов.
Подведем итоги
Агрегат микросервиса — один из самых распространенных паттернов в нашей системе. Мы выбрали его в качестве нашего уровня гранулярности, чтобы обеспечить рост в областях, достигших соответствия продукта рынку.
Ограниченный контекст в микросервисе используется нечасто, потому что он представляет новые области продуктов. Этот паттерн появился в качестве ответа на потребность, когда в компании мы еще не достигли соответствия продукта требованиям рынка.
Основной риск, который возникает при выборе низкой гранулярности, — это превращение в "большой ком грязи". Мы снижаем этот риск, давая четкие указания и рекомендации. (Я знаю, что есть и другие риски, такие как сложность, накладные расходы на развертывание и тому подобное, но мы не чувствуем этих проблем, и у нас есть отличные инструменты, которые помогают нам справиться с данной ситуацией).
У нас есть еще несколько архитектурных тем 一
Представления микросервиса — материализованные представления и все такое
Сквозные сервисы — интеграции, инфраструктура и инструменты в нашей системе.
Коммуникационные каналы — как сервисы взаимодействуют.
Потоки управления — оркестрация, хореография и другие интересные вещи.
Приглашаем всех желающих на открытое занятие «Прошлое, настоящее и будущее роли Enterprise-Architect».
На открытом уроке будет возможность обсудить роль архитектора предприятия: кем были, кем стали и кем предоложительно могут стать в обозримом будущем. Поговорим о необходимых компетенциях агента изменений и базовых знаниях для успешной работы. Увидим, где начинается архитектурный подход и куда нужно стремиться в профессиональном развитии.
Урок пройдет в рамках онлайн-курса "Enterprise Architect". Записаться на урок можно по ссылке.