Перейти к основному содержимому

Паттерны перехода от монолита к микросервисам

Разработчику Архитектору Аналитику
С чего начать план

Сначала — метрика успеха и карта монолита, затем выбор паттерна под конкретный шаг. Strangler Fig разобран отдельно; здесь — обзор четырёх переходных паттернов и их сочетание.


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

Ниже — четыре распространённых паттерна, которые стоит учитывать при планировании миграции.

ПаттернГлавная задачаТипичный момент в плане
Strangler FigПостепенно перенаправлять трафик с монолита на новые сервисыВыделение первого bounded context
Parallel RunСравнить ответы монолита и нового сервиса до переключения пользователейПеред cutover критичного API
Decorating CollaboratorДобавить новую логику рядом со старым сценарием без правок ядра монолитаНовая сквозная проверка (склад, антифрод)
Change Data Capture (CDC)Реплицировать изменения БД монолита в сервисы и витриныРазделение данных, read-модели, аналитика

Паттерны дополняют друг друга: Strangler переключает маршрут, Parallel Run снижает риск ошибки в новом коде, Decorating Collaborator вводит смежный сервис до полного выноса домена, CDC держит копии данных в согласованном состоянии.


Strangler Fig

Идея. Перед монолитом ставят прокси или API Gateway. Сначала весь трафик идёт в монолит. По мере готовности отдельных возможностей шлюз направляет часть запросов (например, чтение каталога или оформление подписки) в новый сервис. Монолит «сужается», пока от него не останется минимальное ядро или он полностью отключается.

Как это выглядит на схеме потока

  1. Клиент → Proxy/Gateway.
  2. Записи и сценарии, ещё не вынесенные, → монолит (Feature B, Feature C).
  3. Вынесенная возможность (Feature A) → Service A с собственным контрактом и, по возможности, своей БД.
  4. Правила маршрутизации расширяют по одному use case за релиз.

Когда применять

  • Есть понятные границы по URL, заголовкам или типу операции.
  • Бизнес должен работать без длительного простоя.
  • Команда готова поддерживать два контура параллельно ограниченное время.

Риски

  • Общая БД с монолитом сохраняет скрытую связанность.
  • Долгое сосуществование двух реализаций одной функции без удаления старого кода.

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


Parallel Run

Идея. Один входящий запрос дублируют: копия уходит в монолит (источник истины для пользователя), параллельно — в новый сервис с клонированной логикой. Ответ клиенту по-прежнему отдаёт монолит (или шлюз, настроенный на старый путь). Результаты обеих веток складывают и сравнивают в фоне — diff, метрики расхождений, алерты.

Тот же приём называют shadow traffic или dark launch: новый сервис «учится» на продакшен-нагрузке без влияния на UX.

Когда применять

  • Критичные расчёты (цена, налоги, лимиты, скоринг).
  • Сложная legacy-логика, которую трудно покрыть только unit-тестами.
  • Нужно доказать эквивалентность перед переключением маршрута в Strangler.

Что заложить в реализацию

  • Идемпотентность и одинаковые входные данные в обе ветки (включая заголовки контекста).
  • Сравнение с допустимой погрешностью (даты, округление float, порядок полей в JSON).
  • Объём — дублирование удваивает нагрузку; часто начинают с доли трафика (sampling) или с read-only операций.
  • PII — логи сравнения без лишних персональных данных.

Сигнал к cutover

  • Стабильно низкий процент расхождений на репрезентативной выборке.
  • Понятная классификация оставшихся отличий (известные баги legacy vs дефекты нового сервиса).

Decorating Collaborator

Идея. Запрос к монолиту проходит через прокси, который не меняет основной ответ, но дополняет цепочку вызовов. Классический пример: Place Order идёт в монолит, а прокси синхронно или асинхронно вызывает новый Inventory Service (Check Inventory) до или после основного сценария.

Монолит остаётся владельцем транзакции «как раньше»; новый сервис подключается как коллаборатор на периметре.

Когда применять

  • В монолит трудно вносить изменения (долгий цикл релиза, чужой вендор).
  • Нужна новая сквозная возможность (проверка остатков, гео, лимиты) до полного выноса заказов.
  • Достаточно side-effect или предварительной валидации с понятным fallback.

Варианты поведения прокси

ПоведениеЭффект
Синхронная проверка до монолитаМожно отклонить заказ до записи в legacy
Синхронный вызов после монолитаОбогащение ответа данными нового сервиса
Асинхронный вызовСлабее связанность, сложнее согласованность с ответом пользователю

Риски

  • Двойная бизнес-логика (в монолите и в сервисе) до завершения миграции.
  • Рост задержки при синхронных цепочках.
  • Неочевидные отказы: падение Inventory Service должно иметь явную политику (fail-open vs fail-closed).

Дальнейший шаг — вынести весь сценарий в сервис и переключить маршрут по Strangler Fig.


Change Data Capture (CDC)

Идея. Изменения в БД монолита (INSERT / UPDATE / DELETE) фиксируются на уровне журнала транзакций (WAL, binlog) или эквивалента. Процесс CDC (часто Debezium, Maxwell, коннекторы Kafka Connect) превращает строки в поток событий и доставляет их целевым системам — микросервису, кэшу, хранилищу аналитики.

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

Когда применять

  • Новому сервису нужна своя БД, но источник правды пока в монолите.
  • Строят read-модель, поисковый индекс, витрину отчётности.
  • Нужна eventual consistency между legacy и MSA без массовой dual-write в коде.

Цепочка (упрощённо)

  1. Транзакция в БД монолита.
  2. Запись в redo / binlog.
  3. CDC-коннектор читает лог, публикует события (I / U / D).
  4. Потребители обновляют локальные хранилища (идемпотентно).

Практические требования

  • Понимание схемы и эволюции таблиц (миграции ломают коннектор, если не versioning).
  • Порядок событий по ключу партиции (например, order_id).
  • Мониторинг лага репликации и отставания consumer'ов.

Связь с событийной архитектурой — 2127.md; инструменты и примеры в продакшене — реактивная коммуникация и CDC.


Как сочетать паттерны

Типичная последовательность для одного bounded context:

  1. CDC — поднять read-копию или проекцию в БД нового сервиса.
  2. Parallel Run — прогнать трафик через обе реализации, сравнить ответы.
  3. Strangler Fig — переключить чтение, затем запись на новый сервис.
  4. Decorating Collaborator — на соседних сценариях, где полный вынос ещё рано.

Для зелёного поля без legacy часто достаточно Strangler + собственная БД. CDC и Parallel Run наиболее ценны при тяжёлом монолите и жёстких требованиях к корректности.


Чеклист перед следующим шагом миграции

  • Зафиксирована метрика «до/после» (104.md).
  • Для выносимой функции выбран основной паттерн и запасной (fallback, откат маршрута).
  • Есть трассировка сквозь gateway, монолит и новый сервис.
  • Для Parallel Run определены порог расхождений и владелец разбора diff.
  • Для CDC измеряется lag и есть runbook при остановке коннектора.
  • После cutover запланировано удаление мёртвого кода в монолите (2125.md).

См. также


См. также

Другие статьи этого же раздела в боковом меню (как на странице "О разделе").