3.2

Смотреть на английском

3.2 Архитектурные стили и паттерны

Обзор и мотивация

Архитектурный стиль это широкая повторно используемая форма организации системы: как она разлагается, как части общаются и где проходят границы. Выбор стиля одно из самых значимых (и самых непонятых) решений, которые принимает большая организация. Слишком часто выбор следует моде («все делают микросервисы») вместо реальных ограничений команды, предметной области и эксплуатационной реальности. В итоге получается одна из двух неразберих: распределённая система, которой организация не может управлять, или запутанный монолит, который никто не может безопасно менять. Ни то ни другое не вина стиля. Оба происходят от несоответствия стиля ситуации.

Для больших команд разработчиков стили важны прежде всего из-за закона Конвея: структура системы склонна отражать структуру коммуникаций организации, которая её строит. Поэтому архитектурный стиль ещё и решение об организационном устройстве. Разбиение системы на сервисы на деле решение о разбиении команд, владения и ответственности за дежурства. Корпорации с сотнями инженеров могут позволить себе (и часто нуждаются в) мелкозернистых сервисах с независимым развёртыванием, потому что эта независимость и есть то, как многие команды выпускают, не блокируя друг друга. Навяжите тот же шаблон одной небольшой команде, и она унаследует весь эксплуатационный налог без организационной выгоды.

Государственная и корпоративная среда добавляют ещё ограничений: долгие сроки жизни систем, строгий контроль изменений, циклы закупок, интеграцию с укоренившимися системами записи и проверяемость. Они отдают предпочтение стилям, держащим границы явными, а зависимости легко проверяемыми. Эта глава обозревает основные стили: от монолита до микросервисов, событийно-ориентированные архитектуры с CQRS и событийным хранением, паттерны сервисной сетки и шлюзов, бессерверные вычисления и внутренние дисциплины гексагональной и чистой архитектуры. Что важнее, она помогает определять, когда каждый подходит.

См. также: главу 2.2 (принципы проектирования программ, включая предметно-ориентированное проектирование), главу 3.1 (основы архитектуры) и главу 3.3 (распределённые системы).

Ключевые принципы

  • Стиль следует силам, а не моде. Выбирайте по размеру команды, сложности предметной области, нагрузке и эксплуатационной зрелости, никогда потому, что технология популярна.
  • Настоящий враг сцепление, а не число развёртываемых единиц. Хорошо модуляризованный монолит побеждает распределённый большой шар грязи.
  • Распределённость это цена, которую вы платите за независимость. Разбивайте, только когда ценность независимого развёртывания, масштабирования или изоляции отказов превышает стоимость сетевых вызовов, частичного отказа и согласованности данных между сервисами.
  • Границы должны следовать предметной области бизнеса. Выравнивайте сервисы и модули с ограниченными контекстами (каждый самодостаточная модель предметной области с явной границей), а не с техническими слоями.
  • Проектируйте внутренность хорошо независимо от внешнего. Гексагональное/чистое слоирование держит бизнес-логику независимой от фреймворков и инфраструктуры в любом стиле.
  • Закон Конвея неизбежен, поэтому используйте его. Проектируйте границы команд и архитектуру вместе.
  • Начинайте проще, чем думаете, что нужно. Из хорошего модульного монолита можно выделить сервисы; свернуть обратно преждевременный хаос микросервисов гораздо труднее.

Рекомендации

По умолчанию выбирайте модульный монолит; разбивайте на основании свидетельств

Начинайте большинство систем как единую развёртываемую единицу с сильными внутренними границами модулей: ясные интерфейсы, никакого залезания в данные другого модуля и обеспечиваемые правила зависимостей. Вы получаете простые транзакции, лёгкий рефакторинг и одну вещь для развёртывания и наблюдения. Выделяйте модуль в отдельный сервис, только когда есть конкретная причина: часть, которая должна масштабироваться отдельно, команда, которой нужно развёртывать в собственном ритме, домен отказа, который нужно изолировать, или технологическое требование, отличающееся от остального. Когда разбиваете, разбивайте по линиям ограниченных контекстов, чтобы каждый сервис владел своими данными и предоставлял стабильный контракт.

Знайте, когда микросервисы оправдывают себя

Микросервисы дают независимую развёртываемость, независимое масштабирование, изоляцию отказов и свободу смешивать технологии. Взамен они требуют зрелого CI/CD (непрерывной интеграции и непрерывной поставки), автоматизированной инфраструктуры, распределённой трассировки, обнаружения сервисов и культуры дежурств. Спросите себя честно: может ли ваша организация надёжно эксплуатировать десятки независимо развёрнутых сервисов в эксплуатации? Если платформы и эксплуатационной зрелости нет, микросервисы лишь умножают ваши режимы отказа, не принося выгод. Многие организации преуспевают с горсткой крупнозернистых сервисов, выровненных по основным областям, а не с роем крошечных.

Используйте событийно-ориентированную архитектуру там, где окупаются развязка и асинхронность

Событийно-ориентированная архитектура позволяет производителям порождать факты, не зная, кто их потребляет. Это покупает слабое сцепление, буфер для всплесков нагрузки и лёгкий способ добавлять новых потребителей. Используйте её там, где рабочие процессы естественно асинхронны и реактивны. CQRS (Command Query Responsibility Segregation) отделяет модель записи от одной или нескольких моделей чтения, что помогает, когда нагрузки или формы чтения и записи резко различаются. Событийное хранение хранит состояние как журнал событий только для добавления, а не как текущее состояние, давая идеальный след аудита и путешествие во времени. Это мощно для финансов и государства, где «как мы пришли к этому значению?» юридический вопрос, но добавляет реальную сложность в версионировании событий, перестройке проекций и рассуждении о согласованности в конечном счёте. Обращайтесь к ним намеренно, а не по умолчанию.

Применяйте шаблоны шлюза, BFF и сетки для управления многими сервисами

API-шлюз даёт внешним клиентам единую точку входа, обрабатывая аутентификацию, ограничение частоты, маршрутизацию и терминирование TLS (Transport Layer Security). Backend-for-Frontend (BFF) даёт каждому типу клиента (веб, мобильный, партнёрский API) собственный подогнанный слой агрегации, так что вы избегаете раздутого универсального API. Сервисная сетка переносит сквозные заботы (взаимный TLS, повторы, тайм-ауты, переключение трафика и телеметрию) в инфраструктурный слой sidecar, чтобы командам приложений не приходилось реализовывать их заново. Добавляйте сетку, только когда число сервисов делает обработку этих забот по сервису неуправляемой. Для нескольких сервисов сетка тяжелее в эксплуатации, чем стоит.

Честно взвешивайте бессерверные вычисления

Функция как услуга и управляемые бессерверные платформы снимают с вас управление серверами, масштабируются до нуля и тарифицируются по использованию, что отлично для всплесковых, событийно-ориентированных или малобазовых нагрузок и для малых команд. Компромиссы реальны: задержка холодного старта, пределы времени выполнения и ресурсов, более трудное локальное тестирование, возможная привязка к поставщику и стоимость, способная превысить выделенную инфраструктуру при устойчиво высоком объёме. Используйте бессерверные вычисления там, где их экономика и эксплуатационная простота явно побеждают. Не загоняйте в них устойчивые высокопроизводительные основные системы из энтузиазма.

Держите бизнес-логику чистой внутри каждого сервиса

Каким бы ни был внешний стиль, держите внутренность чистой с помощью гексагональной (порты и адаптеры) или чистой архитектуры: бизнес-правила в центре, зависящие только от абстракций; фреймворки, базы данных и обмен сообщениями на краях как заменяемые адаптеры. Это держит вашу ценную логику предметной области тестируемой без инфраструктуры и переносимой через технологические изменения, решающее преимущество для долгоживущих государственных и корпоративных систем, переживающих несколько поколений фреймворков.

Компромиссы: плюсы и минусы

СтильЛучше всего, когдаПлюсыМинусы
Модульный монолитБольшинство систем, особенно ранниеПростая эксплуатация, лёгкие транзакции и рефакторингЕдиная единица развёртывания; масштабируется как одно; риск эрозии
МикросервисыМного команд, высокий масштаб, зрелая платформаНезависимое развёртывание/масштабирование, изоляция отказовРаспределённая сложность, согласованность данных, высокая стоимость эксплуатации
Событийно-ориентированный / CQRS / событийное хранениеАсинхронные рабочие процессы, нужды аудита, расходящиеся чтение/записьСлабое сцепление, проверяемость, масштабируемое чтениеСогласованность в конечном счёте, версионирование событий, труднее отладка
Бессерверные вычисленияВсплесковая или малобазовая событийная работаНет управления серверами, масштаб до нуля, оплата по использованиюХолодные старты, пределы, привязка, стоимость при высокой устойчивой нагрузке

Повторяющаяся тема: вы покупаете гибкость и независимость ценой эксплуатационной и когнитивной сложности. Распределённые и событийно-ориентированные стили отказываются от простоты единого стека вызовов и единой транзакции в обмен на способность масштабироваться, развёртываться и отказывать независимо. Этот размен окупается в масштабе и со зрелой платформой. Без неё он губителен. Внутренние дисциплины (гексагональная/чистая) почти всегда стоят затрат, потому что стоят мало и сохраняют ваши варианты открытыми для смены стилей позже.

Вопросы для обсуждения с командой

  1. Прежде чем выделить следующий сервис, разделите ли вы команду, которая им владеет, и у кого есть власть это сделать? Закон Конвея означает, что граница сервиса на деле граница команды, поэтому разбиение, не поддержанное оргсхемой, порождает распределённый монолит: две развёртываемые единицы, один релизный поезд, общее дежурство. В большой корпорации власть перестраивать команды обычно находится выше инженерии, у линий подчинения, финансов и кадров, поэтому архитектура и организационное проектирование должны решаться вместе. Принесите в обсуждение свидетельства: есть ли у предлагаемого сервиса команда, способная владеть им от начала до конца, укомплектовать собственное дежурство и развёртывать в своём ритме? Если ответ «нет», либо профинансируйте команду, либо оставьте возможность модулем в монолите. Разбиение кода без разбиения владения покупает все издержки распределённости и ни одной независимости.

  2. Можете ли вы сегодня развёртывать каждый из ваших сервисов независимо или они втайне выходят в связке? Распределённый монолит наихудший исход в этой главе: вы платите за сетевые вызовы, частичный отказ и согласованность данных между сервисами, но всё равно не можете выпустить один без других. Выдающие признаки: общая база данных, общая библиотека, вынуждающая к согласованным обновлениям, и интеграционные тесты, которые должны прогоняться на всём хозяйстве вместе. Для большой команды это тихо ограничивает пропускную способность, потому что каждая команда стоит в очереди за одним релизом, хотя диаграмма показывает независимость. Возьмите одно недавнее изменение и сосчитайте, сколько сервисов пришлось развернуть вместе для безопасности; если число больше единицы для изменения, затронувшего одну возможность, ваши границы неверны. Исправление обычно в том, чтобы дать каждому сервису собственные данные и стабильный версионируемый контракт, а не добавлять больше сервисов.

  3. Какие из ваших существующих разбиений на сервисы перестали окупаться и вернули бы вы их обратно в одно целое? Самая продвинутая привычка этой главы воспринимать решения о стиле как обратимые: выделять, когда появляется драйвер, и вновь сливать, когда драйвер исчезает. Большинство организаций только разбивают, поэтому наносервисы и болтливые сервисы сущностей накапливаются, пока оркестровка и сетевые накладные расходы не затмят работу, которую делает каждый сервис. Ищите сервисы, всегда развёртываемые вместе, существующие из-за таблицы базы данных, а не бизнес-возможности, или те, чьи сетевые переходы теперь доминируют в задержке запроса. В корпоративных и государственных хозяйствах, где штат и бюджеты под пристальным вниманием, слияние двух тонких сервисов обратно в один крупнозернистый законный, сберегающий деньги шаг, а не признание неудачи. Поставьте переукрупнение на стол так же открыто, как выделение, и решайте оба на тех же свидетельствах.

  4. Поддерживают ли ваша платформа и зрелость дежурств действительно предлагаемый стиль и можете ли вы назвать конкретные пробелы, прежде чем взять обязательство? Микросервисы, сетки и событийно-ориентированные магистрали приносят выгоды только поверх зрелого CI/CD, распределённой трассировки, обнаружения сервисов и культуры дежурств, способной рассуждать о частичном отказе. Большая организация склонна определять целевой стиль на архитектурном форуме и обнаруживать недостающую платформу позже, когда десятки сервисов уже в эксплуатации и каждый инцидент диагностируется часами. Сопоставьте привлекательность независимого развёртывания и масштабирования с трезвым вопросом, кто эксплуатирует это в три часа ночи: то же разбиение, освобождающее команды выпускать параллельно, умножает режимы отказа, которые каждая команда должна понимать. Принесите в обсуждение честную опись: текущую частоту развёртываний, среднее время восстановления, есть ли у вас трассировка через границы сервисов и сколько сервисов одна команда может реалистично эксплуатировать. В корпоративной и государственной среде добавьте сроки закупок и найма для недостающих платформенных возможностей, потому что стиль, предполагающий сетку и платформенную команду, которые вы не профинансировали, это план эксплуатации неподдерживаемого хозяйства.

  5. Для каких частей предметной области полный след аудита на основе событийного хранения юридическая необходимость, а не удобство, и кто уполномочен решать? Событийное хранение и CQRS покупают идеальную восстанавливаемую историю и модели чтения, масштабируемые сами по себе, но стоят версионирования событий, перестроек проекций и рассуждения о согласованности в конечном счёте на всю жизнь системы. Применённая к области, которой след аудита никогда не был нужен, эта сложность чистый налог; отказ от неё в области, где «как мы пришли к этому значению?» юридический вопрос, провал соответствия. Противоположные соображения это проверяемость и масштабируемость запросов с одной стороны и трудность отладки и когнитивная нагрузка разработчиков с другой, поэтому решение принадлежит людям, понимающим и регуляторное обязательство, и эксплуатационное бремя, а не тому, кто больше всех увлечён шаблоном. Принесите конкретные юридические или контрактные требования к хранению и восстановлению, ожидаемый объём событий и честную оценку работы по версионированию и проекциям. В финансах, налогах и государстве, где восстановление решения годы спустя может быть обязанностью по закону, назовите ответственного владельца, подписывающего, что данный ограниченный контекст требует или не требует неизменяемого журнала событий.

  6. Как вы не дадите модульному монолиту эродировать, чтобы последующее выделение оставалось дешёвым, и что будет обеспечивать границы? Весь аргумент в пользу начала с модульного монолита опирается на обещание, что чистые внутренние границы делают позднее выделение сервисов доступным, однако эти границы тихо распадаются в момент, когда срок искушает один модуль залезть в данные другого. Для большой команды со многими участниками добрые намерения и одно ревью кода не удержат линию; без обеспечивающего механизма монолит тихо становится большим шаром грязи, которого стиль должен был избежать. Взвесьте трение обеспечиваемых правил зависимостей и интерфейсов модулей против стоимости обнаружения годы спустя, что ни одна граница не реальна и каждое выделение означает расплетение общего состояния. Принесите свидетельства: обеспечиваются ли границы модулей инструментами сборки, статическим анализом или структурой пакетов или это просто документированные соглашения, которые игнорировали последние шесть слияний? В долгоживущих корпоративных и государственных системах, обязанных пережить строгий контроль изменений и несколько поколений фреймворков, воспринимайте обеспечение границ как проверяемый контроль, чтобы возможность распределиться позже была той, что вы действительно сохранили, а не той, которой, как вы предполагаете, всё ещё владеете.

Взгляд по секторам

Стартап. По умолчанию выбирайте единый модульный монолит и сопротивляйтесь тяге микросервисов, потому что ваш самый дефицитный ресурс инженерное внимание, а рой сервисов это эксплуатационный налог, который вы не можете себе позволить до соответствия продукта рынку. Держите чистые границы модулей, чтобы выделить позже, и обращайтесь к бессерверным вычислениям там, где масштаб до нуля и оплата по использованию подходят вашей всплесковой малобазовой нагрузке. Выделяйте ровно одну вещь, только когда появляется конкретный драйвер, например всплесковый отправитель уведомлений, и не раньше.

Малый бизнес. Без платформенной команды и при ограниченном бюджете предпочитайте монолит или горстку крупных сервисов на управляемой платформе и покупайте хостинговую инфраструктуру, а не стройте сетки, трассировку и обнаружение сервисов сами. Рассматривайте бессерверные вычисления и управляемые базы данных как способ вообще не эксплуатировать серверы и остерегайтесь распределённого проекта, эксплуатационное бремя которого некому нести. Правильная архитектура та, которую один-два человека действительно могут развернуть, наблюдать и восстанавливать.

Крупная организация. Настоящая проблема многие команды и закон Конвея: выравнивайте крупнозернистые сервисы по ограниченным контекстам и владению команд и вкладывайтесь намеренно в платформу (CI/CD, трассировка, сетка и обнаружение сервисов), делающую распределённость безопасной. Стандартизируйте шаблоны шлюза, BFF и внутренней чистой архитектуры, чтобы группы перестали изобретать их заново, и управляйте выделением и переукрупнением как основанными на свидетельствах решениями портфеля, а не локальным предпочтением. Закладывайте эксплуатационную стоимость каждого разбиения явно, потому что в вашем масштабе провал распределённого монолита дорог и медленно расплетается.

Государственный сектор. Долгие сроки жизни систем, строгий контроль изменений, циклы закупок и проверяемость определяют выбор: предпочитайте стили с явными, проверяемыми границами и долговечными контрактами, переживающими поставщиков и поколения фреймворков. Событийное хранение оправдывает свою сложность там, где восстановление решения, касающегося гражданина, обязанность по закону, поэтому используйте его намеренно для основных главных книг и держите чистую архитектуру внутри каждого сервиса, чтобы изолировать правила, меняющиеся с каждым бюджетом. Воспринимайте переносимость и выход из проприетарных бессерверных или поставщицких платформ как требования закупок, а не запоздалые мысли.

Примеры

Стартап. Стартап из четырёх человек, строящий продукт для планирования, чувствует давление начать с микросервисов, потому что конкурент написал о них в блоге, но сопротивляется. Они выпускают единый модульный монолит с чёткими внутренними границами (планирование, биллинг, уведомления) как отдельные модули в одной развёртываемой единице, так что один инженер может запустить всё локально, а релиз это один пуш. Когда продукт находит отклик, в собственный сервис выделяется только отправитель уведомлений, рассылающий на почту и SMS при всплесковой нагрузке. Они не наследуют ничего из эксплуатационного налога дюжины сервисов, пока ещё ищут соответствие продукта рынку.

Крупная организация. Крупная компания электронной коммерции начинает как модульный монолит. По мере роста трафика и умножения команд она выделяет самые нагруженные и независимее всего развивающиеся области (каталог, корзина, оформление заказа и поиск) в отдельные сервисы, каждый из которых владеет своими данными. Оформление заказа порождает события, которые потребляют склад, исполнение и аналитика через событийную магистраль, так что новые потребители (обнаружение мошенничества, лояльность) могут подключаться, не трогая оформление. API-шлюз обрабатывает аутентификацию и ограничение частоты, а BFF подгоняет нагрузки для мобильных. Остальные области с меньшим трафиком остаются в монолите, что избегает ненужной фрагментации.

Государственный сектор. Налоговое управление строит платформу оценки на событийном хранении для основной главной книги, потому что каждое изменение обязательств налогоплательщика должно быть восстановимо и юридически проверяемо годами. Команды (подать декларацию, применить платёж, выдать корректировку) порождают неизменяемые события, а модели чтения проецируют текущие балансы для сотрудников и граждан. CQRS позволяет публичной стороне запросов масштабироваться отдельно на пик сезона подачи, не подвергая риску сторону записи. Внутри каждый сервис следует чистой архитектуре, так что правила оценки, меняющиеся с каждым бюджетом, остаются изолированными от технологии персистентности и обмена сообщениями.

Бизнес-обоснование: мотивы, ROI и TCO

Деньги, стоящие за выбором стиля, огромны, потому что решение дорого обращать. Примите микросервисы слишком рано, и вы раздуете совокупную стоимость владения через построение платформы, дублирование инфраструктуры, распределённую отладку и более тяжёлое эксплуатационное бремя: затраты, остающиеся с вами на всю жизнь системы. Откажитесь разбивать действительно перегруженный монолит, и вы ограничите пропускную способность поставки: команды стоят в очереди за общим релизом, а каждое изменение подвергает риску всю систему. Разговор об ROI на деле о соответствии эксплуатационных расходов организационной потребности.

Обосновывайте руководству в терминах пропускной способности и риска, а не технологии. Независимая развёртываемость означает, что больше команд выпускают параллельно и более короткие сроки выполнения: измеримая бизнес-скорость. Изоляция отказов означает меньше полных сбоев и меньший радиус поражения: измеримая доступность и репутационная защита. Но будьте столь же честны о вложениях в платформу, которых требует каждый стиль: сетка, трассировка и зрелость CI/CD предпосылки, а не необязательные дополнения, и их стоимость принадлежит TCO. Для многих организаций самый дешёвый путь это хорошо модуляризованный монолит сейчас с чистыми внутренними границами, делающими позднее выделение дешёвым. Это покупает вам возможность распределиться, не платя за неё до того, как она понадобится.

Антипаттерны и ловушки

  • Распределённый монолит. Сервисы, которые нужно развёртывать вместе и которые делят базу данных: все издержки распределённости и никакой независимости.
  • Наносервисы. Сервисы настолько мелкозернистые, что оркестровка и сетевые накладные расходы затмевают работу, которую они делают.
  • Микросервисы без платформы. Разбиение до появления CI/CD, трассировки и зрелости дежурств; режимы отказа умножаются.
  • Сервисы сущностей. Разбиение по таблице базы данных («сервис пользователей», «сервис заказов») вместо бизнес-возможности, вынуждающее болтливые межсервисные вызовы для каждой операции.
  • Событийное хранение везде. Применение к областям, которым не нужен след аудита, с уплатой налога сложности без выгоды.
  • Шлюз как монолит. Помещение бизнес-логики в API-шлюз, воссоздающее центральное узкое место.
  • Ядро, сцепленное с фреймворком. Бизнес-логика, запутанная с веб-фреймворком или фреймворком ORM (объектно-реляционного отображения), из-за чего больно и тестировать, и менять технологию.

Модель зрелости

  • Уровень 1: Начальный. Стиль выбирается по моде или случайно. У вас один запутанный монолит или случайный распределённый хаос, границы следуют техническим слоям или истории, а не предметной области, и разбиения происходят реактивно, когда что-то ломается.
  • Уровень 2: Развитие. Некоторые команды проводят намеренные границы модулей внутри монолита или поднимают несколько крупных сервисов, и некоторые сквозные заботы обрабатываются последовательно. Практика неравномерна: одна группа выравнивает сервисы по ограниченным контекстам, а другая по-прежнему разбивает по таблицам базы данных, и выделение остаётся стихийным.
  • Уровень 3: Стандартизация. Документированный подход соблюдается по организации: сервисы выровнены по ограниченным контекстам и владеют своими данными, шаблоны шлюза и BFF применяются где уместно, внутренняя чистая или гексагональная слоистость стандарт, а каждое разбиение требует заявленного драйвера. Границы модулей обеспечиваются инструментами, а не только соглашением.
  • Уровень 4: Управление. Решения о стиле измеряются и контролируются относительно базовых значений. Вы отслеживаете частоту развёртываний и время выполнения по сервису, среднее время восстановления, сколько сервисов должны развёртываться вместе для типичного изменения и задержку сетевых переходов и сравниваете стоимость каждого разбиения с независимостью, которую оно должно было купить. Свидетельства, а не предпочтение, определяют, переживёт ли граница, а дрейф к распределённому монолиту ловится метриками, а не сбоем.
  • Уровень 5: Оркестрация. Архитектура интегрирована с организационным проектированием и непрерывно адаптируется. Зрелая платформа (CI/CD, трассировка и сетка, где оправдано) делает дешёвыми и распределённость, и переукрупнение, команды регулярно выделяют, когда появляется драйвер, и сливают сервисы обратно, когда он исчезает, а выбор стилей перебалансируется по мере смещения топологии команд, нагрузки и картины рисков по всему хозяйству.

Идеи для обсуждения

  1. Где в вашей системе монолит на самом деле сила, а где подлинное узкое место?
  2. Какой конкретный драйвер оправдал бы выделение вашего следующего сервиса и можете ли вы назвать его до построения?
  3. Есть ли в вашей организации эксплуатационная зрелость, которой требуют микросервисы? Чего не хватает?
  4. Для каких частей вашей предметной области полный след аудита на основе событийного хранения юридическая или бизнес-необходимость, а для каких приятное дополнение?
  5. Насколько хорошо ваши нынешние границы сервисов отражают границы ваших команд и помогает или вредит это выравнивание?
  6. Если бы вам пришлось сменить веб-фреймворк или базу данных в следующем году, какую часть бизнес-логики пришлось бы переписать?

Главные выводы

  • Выбирайте архитектурный стиль по реальным силам (размер команды, предметная область, нагрузка, эксплуатационная зрелость), а не по моде.
  • Модульный монолит правильное умолчание для большинства систем; выделяйте сервисы только с конкретным драйвером и по линиям ограниченных контекстов.
  • Микросервисы меняют эксплуатационную и когнитивную сложность на независимое развёртывание, масштабирование и изоляцию отказов; им нужна зрелая платформа.
  • Событийно-ориентированный стиль, CQRS и событийное хранение дают развязку и проверяемость ценой согласованности в конечном счёте и сложности версионирования; принимайте намеренно.
  • Шлюзы, BFF и сетки укрощают хозяйства из многих сервисов, но добавляют вес; вводите их, когда этого требует масштаб, а не раньше.
  • Применяйте гексагональную/чистую архитектуру внутри каждого сервиса, чтобы ценная бизнес-логика оставалась тестируемой и долговечной сквозь смену технологий.

Источники и дополнительное чтение

  • Sam Newman, Building Microservices and Monolith to Microservices
  • Chris Richardson, Microservices Patterns
  • Eric Evans, Domain-Driven Design
  • Vaughn Vernon, Implementing Domain-Driven Design
  • Robert C. Martin, Clean Architecture
  • Alistair Cockburn, “Hexagonal Architecture (Ports and Adapters)”
  • Gregor Hohpe and Bobby Woolf, Enterprise Integration Patterns
  • Martin Fowler, Patterns of Enterprise Application Architecture (and articles on CQRS and Event Sourcing)
  • Matthew Skelton and Manuel Pais, Team Topologies