АрхитектураМикросервисы и интеграцииАрхитектор программных систем

Команда разделила систему на микросервисы по техническим слоям. Какой главный дефект такой декомпозиции нуж...

Команда разделила систему на микросервисы по техническим слоям. Какой главный дефект такой декомпозиции нужно выявить?

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

Главный дефект — границы сервисов проведены по техническим функциям, а не по бизнес-возможностям и ответственности за данные. Такая декомпозиция обычно создаёт высокую связанность: одна бизнес-операция начинает проходить через несколько сервисов и требует координации между ними.

Исторический контекст

Идея выделять сервисы по бизнес-возможностям связана с практикой ограниченных контекстов и развитием предметно-ориентированного проектирования. Она появилась как ответ на проблему больших систем, где единая модель данных и общие технические модули связывали между собой несвязанные части предметной области.

Разделение по техническим слоям удобно внутри монолита: валидация, хранение и уведомления могут быть отдельными модулями. При распределении по сети такая структура часто превращает внутренние вызовы в межсервисные зависимости с задержками, отказами и сложностями согласованности.

Постановка проблемы

При техническом разделении сервисы редко владеют завершённой бизнес-возможностью. Например, обработка одной операции может потребовать последовательных вызовов сервисов валидации, хранения и уведомлений.

В результате изменение бизнес-правила затрагивает несколько команд и контрактов. Возникают сетевые цепочки, необходимость распределённых транзакций или компенсаций, а отказ второстепенного технического сервиса может сделать недоступной основную бизнес-операцию.

Подробное решение

Границу сервиса следует проводить вокруг бизнес-возможности, связанного набора инвариантов и данных, владельцем которых является этот сервис. Внутри границы могут находиться валидация, хранение, публикация событий и другие технические детали.

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

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

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

Ситуация из практики

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

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

Выбрали второй вариант. Сервис платежей стал владельцем финансового состояния и его инвариантов, а сервис уведомлений — независимым потребителем события. В результате отказ уведомлений перестал блокировать подтверждение платежа, хотя доставка уведомления стала асинхронной и потребовала обработки повторов.

Что кандидаты часто упускают

  1. Означает ли правильная граница, что сервис должен владеть всеми данными, необходимыми бизнес-процессу?

Нет. Сервис должен владеть данными, за которые он отвечает и чьи инварианты поддерживает. Для чтения чужих данных можно использовать API, локальную копию или проекцию, но запись в чужое хранилище размывает ответственность.

  1. Всегда ли технически выделенный сервис является архитектурной ошибкой?

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

  1. Как отличить допустимый межсервисный вызов от признака неправильной границы?

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