Доменно-ориентированная микросервисная архитектура ценна тем, что ставит бизнес-границы выше сетевых схем и диаграмм вызовов.
Для реального проектирования глава помогает увидеть, как домены, слои, контракты шлюза домена, точки расширения и ответственность команд начинают работать вместе только тогда, когда организационная структура не спорит с архитектурой.
Для интервью и инженерных разборов она полезна тем, что помогает обсуждать DOMA через организационную связанность, узкие места у команд общей платформы и цену координации на большом масштабе.
Практическая польза главы
Практика проектирования
Связывайте доменные границы, слои зависимостей и зоны ответственности команд.
Качество решений
Согласовывайте контракты шлюза домена, точки расширения и платформенные API.
Аргументация на интервью
Показывайте, как архитектура и устройство организации вместе влияют на скорость поставки изменений.
Анализ отказов
Контролируйте риск организационной связанности и узкие места у команд общей платформы.
Источник
Uber Engineering, 2020
Оригинальная статья Adam Gluck о редизайне архитектуры Uber и переходе к DOMA.
Когда сервисов становятся тысячи, «больше микросервисов» перестаёт быть ответом: связи между ними растут быстрее, чем команды успевают их отслеживать. DOMA — — это ответ Uber на такой масштаб: проектировать не россыпь изолированных сервисов, а доменные коллекции сервисов со строгими контрактами, слоями зависимостей и точками расширения, чтобы система оставалась управляемой.
По духу подход переносит идеи DDD и архитектурной модульности на масштаб тысяч инженеров и тысяч сервисов — там, где цена неуправляемой связности измеряется уже не часами, а кварталами.
Эволюция архитектуры Uber
Монолитная архитектура
У Uber было два крупных сервиса. Пока команда росла от десятков к сотням инженеров, монолит держался; дальше начали расти риски доступности, сложность деплоев и стоимость каждого изменения.
- Падение крупного компонента задевало большую часть продукта — риск доступности концентрировался в одной точке.
- Одно изменение могло затронуть слишком много продукта сразу: релизы становились опасными.
- Слабое разделение ответственности между .
- Изменения в бизнес-логике внедрялись медленно.
Переход к микросервисам
Ставка на надёжность, ответственность команд и скорость разработки сначала сработала. Но на масштабе тысяч инженеров выигрыш развернулся в свою противоположность: система стала напоминать — с сетевыми задержками монолита, но без его простоты отладки.
- Зависимостей между сервисами стало столько, что схему связей уже никто не держал в голове.
- Причину инцидента приходилось трассировать через десятки команд — расследование растягивалось.
- Границы ответственности и модели данных размывались, и спор «чей это сервис» возникал на каждом шаге.
- Когнитивная нагрузка на разработчика росла: чтобы что-то поменять, надо было понимать слишком многое.
DOMA (Domain-Oriented Microservice Architecture)
Uber перестал смотреть на систему как на тысячи отдельных сервисов и переосмыслил её как одно большое распределённое приложение, к которому применимы привычные архитектурные принципы: , слои, контракты и расширяемость.
- Единицей дизайна становится домен, а не отдельный сервис — решения принимаются крупнее.
- Зависимости становятся управляемыми через .
- Внешние интеграции идут через .
- Кросс-доменные интеграции проходят через , а не через прямую связность.
Принципы DOMA
Дизайн вокруг доменов, а не отдельных сервисов
Единица проектирования здесь — , которая закрывает доменную задачу целиком, а не один сервис. Так достаётся одной команде, и планировать изменения проще: понятно, кого спрашивать.
Домены группируются в слои
Сервис верхнего слоя может зависеть только от нижнего, и никогда наоборот. Это не даёт появиться циклам и удерживает в границах слоя: изменение внизу не расползается вверх по всей системе.
У домена есть явный входной контракт
Снаружи в домен ведёт ровно одна дверь — . Он держит внешний стабильным, поэтому внутреннюю реализацию можно переписывать, не предупреждая потребителей.
Прямых кросс-доменных зависимостей нет
Между доменами нет ни общего кода, ни общей модели данных — иначе домены снова срастаются в монолит. Особые сценарии интеграции проходят через контролируемые .
Слои DOMA в Uber
| Слой | Назначение | Примеры |
|---|---|---|
| Инфраструктурный слой | Базовые , нужные любой инженерной организации: хранение, сеть, наблюдаемость и инфраструктурная идентификация. | API хранения, сетевые примитивы, инфраструктурная идентификация, инструменты среды выполнения |
| Бизнес-слой | Общие бизнес-возможности Uber, не привязанные к одному вроде Rides, Eats или Freight. | Платёжные политики, сигналы антифрода, пользовательские профили |
| Продуктовый слой | Логика конкретной , но без привязки к одному клиентскому приложению. | Жизненный цикл заказа поездки, правила диспетчеризации, логика доступности водителей |
| Слой представления | Функциональность, привязанная к пользовательским интерфейсам: мобильному приложению или вебу. | Сценарии экранов заказа, координация действий из интерфейса, правила UX для конкретного приложения |
| Пограничный слой | Безопасная экспозиция API наружу и адаптация под особенности клиентских приложений. | Пограничные шлюзы, политики авторизации, композиция API, адаптация запросов |
Базовое правило: сервисы верхнего слоя зависят только от сервисов нижележащих слоев.
Контракты
Паттерны межсервисной коммуникации
Шлюз домена и точки расширения держатся на контрактах между командами: размыт контракт — размыта и граница домена.
Шлюз домена и точки расширения
Расширение логики через плагины
Сервисы внутри домена выставляют . Дополнительную доменную проверку подключают через плагин, а не форком базовой логики — иначе её пришлось бы поддерживать в нескольких копиях.
Расширение модели данных через необязательные поля
Когда домену нужны свои атрибуты, их добавляют как к базовой модели. Это даёт расширение без прямой связи доменов на уровне , которую потом не отвязать.
Локальные точки расширения команд
Команда вправе завести собственные точки расширения внутри своего домена — при условии, что контракт и жизненный цикл остаются под её контролем. Свобода не означает потерю границ.
Здесь и проявляется практический смысл шлюза домена: пока внешний контракт стабилен, команда переносит и переписывает внутренние сервисы, и потребители этого не замечают. Свобода менять реализацию покупается дисциплиной контракта.
Что получилось на выходе
- Вместо 2200 сервисов как плоского списка — примерно 70 доменов как управляемых единиц; на этом уровне систему уже можно держать в голове.
- Зависимости стали предсказуемыми: слоистая архитектура и строгое не дают связям расти в любую сторону.
- Стабильные контракты шлюза домена развязали релизы: домены мигрируют и выкатываются независимо, не дожидаясь соседей.
- Разработчику нужно понимать меньше, а причину инцидента видно быстрее — обе цены масштаба пошли вниз.
Когда выбирать монолит, микросервисы и DOMA
| Размер организации | Базовый выбор | Почему |
|---|---|---|
| Стартап | Монолит или | Главное — проверить рынок дёшево и быстро; операционная сложность сервисной архитектуры здесь только мешает. |
| Средняя компания | Классические микросервисы | Несколько команд уже мешают друг другу в одном кодовом базе — нужна независимая поставка и изоляция технологических рисков по подсистемам. |
| Крупная организация | DOMA-подход | Тысячи инженеров уже не помещаются в плоскую сетку сервисов: нужны доменные границы, масштабируемое и системная связанность, которую кто-то целенаправленно удерживает в рамках. |
Типичные ошибки при внедрении DOMA
Назвать доменом случайный набор сервисов без явной бизнес-границы и модели ответственности — ярлык поменялся, а связность осталась прежней.
Шлюз домена как тонкая прослойка без контракта, и соглашения об уровне сервиса (SLA): такой шлюз ничего не стабилизирует и ломает потребителей при первом же изменении.
Сохранить или между доменами и назвать это DOMA — на схеме границы есть, в данных их нет.
Нарисовать слои на бумаге, но нарушать правило зависимостей: верхний слой обращается к сервисам того же или верхнего слоя. Тогда слои существуют только в документации.
Источники
Связанные главы
- Зачем нужны микросервисы и интеграция - Контекст для выбора сервисных границ и интеграционных подходов до внедрения доменно-ориентированной модели.
- Стратегии декомпозиции - Как выделять ограниченные контексты и поэтапно снижать связность, не теряя управляемость по дороге — то, с чего начинается любой переход к доменам.
- Learning Domain-Driven Design (short summary) - DDD-основа для формирования доменов, ответственности команд и контрактов, на которых строится DOMA.
- Паттерны межсервисной коммуникации - Подходы к синхронному и асинхронному взаимодействию, которые стабилизируют контракты шлюза домена и кросс-доменные интеграции.
- Обнаружение сервисов (service discovery) - Инфраструктурный слой обнаружения сервисов для масштабируемого взаимодействия доменных компонентов.
- Monolith to Microservices (short summary) - Пошаговый план перехода от монолита к сервисной архитектуре с контролем рисков и связности.
- Uber/Lyft - Компания, на чьём масштабе доменная декомпозиция и архитектурное управление перестают быть теорией и становятся условием выживания системы.
