В компании все микросервисы обязаны обмениваться через единую каноническую модель данных. Какой главный архитектурный риск создаёт такой подход?
Главный риск — появление распределённого общего контракта, от которого начинают зависеть все сервисы. Изменение модели требует согласования множества команд, а различия в бизнес-смыслах сглаживаются искусственно или превращаются в многочисленные необязательные поля.
Каноническая модель может уменьшить число преобразований между системами, но ценой становится более сильная временная и организационная связанность. Для независимого развития микросервисов обычно лучше использовать локальные контракты и явное преобразование моделей на границах.
В интеграционных решениях EAI и SOA каноническая модель данных применялась для уменьшения количества парных преобразований. Без неё при наличии множества систем каждой системе потенциально требовались отдельные адаптеры к каждой другой системе.
Единый формат обещал упростить обмен: каждый участник преобразует свои данные в общую модель и обратно. Однако в микросервисной архитектуре важна не только техническая экономия преобразований, но и автономия команд, независимое владение моделями и возможность менять границы сервиса без глобальной координации.
Разные сервисы могут использовать одинаковое слово с разным смыслом. Например, клиент для продаж может означать покупателя, для риска — сторону кредитного обязательства, а для доставки — получателя заказа.
Каноническая модель вынуждает помещать эти смыслы в одну структуру. В результате появляются поля «на всякий случай», неоднозначные значения и правила, которые невозможно корректно интерпретировать всем потребителям.
Главное последствие — изменение общего контракта становится потенциально глобальным изменением. Даже если новое поле нужно только одному сервису, остальные участники должны учитывать его появление, совместимость и жизненный цикл.
Не следует автоматически считать каноническую модель ошибкой. Она оправдана, если существует действительно общий, стабильный смысл данных, много независимых интеграций и отдельная команда может управлять общим контрактом, его версиями и правилами совместимости.
Для микросервисов предпочтительнее подход локальных контрактов:
Такой подход увеличивает число преобразований и может привести к дублированию некоторых данных. Это осознанная плата за слабую связанность: дублирование представления обычно менее опасно, чем общее владение бизнес-моделью.
Важно отделять техническую унификацию от унификации смысла. Общие правила кодировки, идентификаторов, времени или трассировки могут быть полезны, но они не означают, что все бизнес-сущности должны иметь одну общую структуру.
Если общая модель уже существует, её следует ограничивать стабильным подмножеством и управлять изменениями как отдельным контрактом. Нельзя добавлять в неё каждую особенность конкретного сервиса: иначе она постепенно превращается в «модель всего предприятия» и становится узким местом.
Предположим, сервис заказов, сервис доставки и сервис возвратов обязаны использовать единую модель Customer. Команда доставки добавляет в неё адрес последней доставки, команда возвратов — платёжные реквизиты, а команда заказов меняет значение статуса клиента. Формально структура остаётся общей, но каждый потребитель начинает зависеть от чужих полей и трактовок.
Рассматривались два варианта. Сохранение единой модели уменьшало количество адаптеров, но требовало общего согласования изменений и сохраняло неоднозначность. Полностью парные интеграции давали автономию, однако увеличивали число преобразований и стоимость поддержки.
Выбранным решением стали локальные контракты: сервис заказов публиковал сведения о покупателе, сервис доставки — данные, необходимые для доставки, а сервис возвратов — собственное представление плательщика. На границах были добавлены явные преобразования и проверки обязательных полей.
Плюсом стало то, что изменение модели доставки перестало требовать обновления сервиса заказов. Минусом стали дополнительные адаптеры и необходимость договориться о семантике действительно общих идентификаторов, но эта сложность осталась локализованной и стала видимой.
1. Дополнительный вопрос: разве дублирование данных в локальных контрактах не нарушает принцип единственного источника истины?
Нет, если различать владение данными и их копии для интеграции. Источник истины должен быть один для конкретного бизнес-факта, но его производные представления могут храниться в других сервисах.
Например, сервис клиентов владеет юридическими данными клиента, а сервис доставки может хранить копию имени и адреса, необходимую для выполнения доставки. Такая копия должна обновляться по определённому контракту и не должна становиться самостоятельным владельцем исходного факта без явного архитектурного решения.
2. Дополнительный вопрос: когда общий контракт всё же лучше локальных контрактов?
Он уместен, когда предметная семантика действительно общая и стабильная, а выгода от единообразия выше цены координации. Примерами могут быть технические метаданные интеграции или узкий справочник, которым управляет одна ответственная сторона.
Нужно оценивать не количество полей, а стоимость изменений. Если модель меняется редко, имеет ясного владельца и не содержит смешанных бизнес-смыслов, общий контракт может быть практичным. Если же разные команды постоянно расширяют его под собственные задачи, это признак чрезмерной централизации.
3. Дополнительный вопрос: чем каноническая модель отличается от общего стандарта формата сообщений?
Общий формат задаёт технические правила обмена: например, структуру метаданных, идентификатор корреляции или представление времени. Каноническая бизнес-модель задаёт ещё и смысл предметных данных, поэтому она сильнее влияет на границы сервисов.
Организация может стандартизировать технический конверт сообщения, не заставляя все сервисы использовать одну модель заказа, клиента или платежа. Такое разделение позволяет совместить общие требования к интеграционной инфраструктуре с автономными бизнес-моделями сервисов.