#microservices #domain-driven-design
Вопрос:
В сценарии, когда нам может потребоваться некоторое чтение, для которого требуются данные в разных ограниченных контекстах (другими словами, будь то из нескольких микросервисов или модулей модульного монолита), как это реализовать?
Пара, о которой я могу думать, это:
- ничего не делайте и предоставьте клиенту возможность скомпилировать нужное ему представление, вызвав несколько служб и объединив необходимые ему данные
- создайте отдельный модуль, который будет получать данные от каждого микросервиса/модуля, компилировать модель чтения и предоставлять ее клиенту
- имейте отдельный модуль с материализованным представлением, который обновляется каждый раз, когда изменяются соответствующие данные (различными микросервисами).
Есть ли какой-то «наилучший» способ сделать это? И если да, то почему?
Ответ №1:
Очень скоро я столкнусь с подобным сценарием. Мои мысли об этом:
1 и 2, по сути, являются одним и тем же подходом. В частности, «клиент», будь то конечный клиент (1) или ваш отдельный модуль (2), который выполняет несколько вызовов, будет вызывать несколько модулей, чтобы получить соответствующие данные из каждого перед компиляцией в единое представление, как требуется.
Я вижу три потенциальные архитектуры:
- У вас нет глобальной базы данных, и каждый модуль использует одну и ту же модель данных для записи и чтения.
- У вас нет глобальной базы данных, и каждый модуль имеет отдельную базу данных для записи и чтения (используя внутренние события для синхронизации модели чтения, когда команды вносят изменения в модель записи).
- У вас есть глобальная база данных, которая обрабатывает события интеграции из различных модулей для компиляции глобальной базы данных чтения.
Для моего решения я бы стремился достичь числа 3. Затем можно реализовать отдельный модуль глобальных запросов для возврата результатов из глобальной базы данных и оставить модули в покое. Это позволило бы модулю свободно записывать базы данных, чтобы оптимально реагировать на команды без одновременного попадания сложных считываний в базу данных.
Номер 2 сохранит оптимальные базы данных для записи модуля, но потребует нескольких запросов к различным базам данных для чтения модуля для компиляции единого представления для клиента.
Номер 1 является наименее благоприятным, поскольку он попадет в одну и ту же базу данных, которая используется для записи в каждом модуле, а также потребует уровня для компиляции нескольких запросов из разных модулей в глобальное представление.
Мой план нападения на это будет поэтапным:
Во-первых, создайте «слой сортировки», который предоставляет запросы для возврата глобальных представлений для клиента. Я бы воздержался от того, чтобы конечный клиент выполнял композицию, так как любые изменения в архитектуре вашего модуля затем попадут непосредственно на клиента, а не на ваш «уровень сортировки». Уровень сортировки может защитить конечного клиента от таких изменений.
Изначально у меня есть архитектура 1. Таким образом, мой уровень сортировки действительно будет работать с теми же базами данных, что и модули, используемые для записи. Но это быстро происходит.
Однако, установив этот уровень сортировки, я смогу затем оптимизировать свое базовое решение, не влияя на клиентские интерфейсы. К тому времени у меня должно быть четкое представление о том, как будет выглядеть глобальная схема данных, поэтому я непосредственно изменю свою архитектуру на номер 3. Проблема с попыткой архитектуры 3 во время разработки заключается в том, что я могу себе представить, что поддержание изменений в модулях и соответствующие потенциальные изменения в глобальной модели данных слишком сильно замедлили бы процесс.
Архитектура 2 немного проще в разработке, так как на модель чтения повлияют только изменения в локальном модуле.
В зависимости от вашей чувствительности к чтению и записи в одной и той же базе данных для модуля во время разработки и первоначального выпуска, архитектура 2 может стать для вас подходящей ступенькой.
Что касается меня, я с удовольствием начну с начального выпуска (небольшой объем клиентов), используя одну и ту же базу данных модулей для чтения и записи, скрытую за интерфейсом в моем слое сортировки, поэтому я могу сразу перейти к архитектуре 3, прежде чем появятся новые клиенты.
Как я обнаружил с помощью DDD, правильный подход обычно зависит от того, какой …
Не ответ как таковой, но, возможно, эти мысли помогут вам принять собственное решение.
Комментарии:
1. спасибо вам за то, что вы так подробно рассказали о своем процессе планирования. я очень благодарен, так как это очень помогает. /в моем конкретном случае я буду рассматривать постепенное приближение к сценарию 3, но достигну ли я его когда-нибудь, будет зависеть от использования. я планирую начать с модульного монолита, где у каждого модуля есть своя собственная база данных с cqr, но нет отдельной базы данных для чтения. затем мы посмотрим, возникнет ли необходимость в полномасштабном разделении (вариант 3).
2. Одним из недостатков этого подхода (не соглашаясь с ним, просто указывая на него) является то, что общим оправданием высоких первоначальных затрат на выбор архитектуры микросервисов является явное незнание того, как может выглядеть глобальная архитектура промежуточного или конечного состояния. Таким образом, я мог бы рассмотреть возможность использования варианта 3 в качестве «региональной» службы сортировки, которая собирает и организует информацию, связанную с известными, но понимает, что со временем будет развиваться больше регионов, и планирует такие возможности.