Что такое паттерн Strangler Fig?
Strangler Fig (душитель) — это паттерн постепенной миграции от монолита к микросервисам. Вместо рискованного «Big Bang» переписывания, новая функциональность реализуется в микросервисах, а существующая постепенно перемещается из монолита.
Аналогия из жизни: название происходит от тропического фикуса-душителя, который обвивает другое дерево и постепенно замещает его. Монолит — это старое дерево, микросервисы — новые побеги.
Этапы миграции
Пример
Этап 1: Монолит обрабатывает все запросы
┌──────────┐
│ Клиенты │──► Монолит
└──────────┘
Этап 2: Фасад перенаправляет часть запросов
┌──────────┐ ┌─────────┐ ┌──────────────┐
│ Клиенты │──► │ Gateway │──► │ Монолит │ (старые функции)
└──────────┘ └────┬────┘ └──────────────┘
└──────► Микросервис A (мигрированные)
Этап 3: Большинство функций мигрировано
┌──────────┐ ┌─────────┐ ┌──────────────┐
│ Клиенты │──► │ Gateway │──► │ Монолит │ (минимум)
└──────────┘ └────┬────┘ └──────────────┘
├──────► Микросервис A
├──────► Микросервис B
└──────► Микросервис C
Этап 4: Монолит полностью заменён
Реализация через Spring Cloud Gateway
spring:
cloud:
gateway:
routes:
# Новый функционал — микросервис
- id: new-payments
uri: lb://payment-service
predicates:
- Path=/api/v2/payments/**
# Старый функционал — пока в монолите
- id: legacy-reports
uri: http://monolith:8080
predicates:
- Path=/api/reports/**
# Постепенная миграция: сначала 10% трафика на новый сервис
- id: canary-customers
uri: lb://customer-service
predicates:
- Path=/api/customers/**
- Weight=new, 10
- id: legacy-customers
uri: http://monolith:8080
predicates:
- Path=/api/customers/**
- Weight=legacy, 90
Стратегии выделения микросервисов из монолита
- Новая функциональность — всё новое пишем как микросервис.
- По бизнес-домену — выделяем наиболее изолированные модули.
- По частоте изменений — выделяем то, что часто меняется.
- По требованиям к масштабированию — выделяем «горячие» модули.
Anti-Corruption Layer
Anti-Corruption Layer — слой-адаптер между микросервисом и монолитом, который транслирует модели и предотвращает загрязнение новой чистой модели старыми структурами.
Пример Anti-Corruption Layer
@Service
public class LegacyCustomerAdapter implements CustomerProvider {
private final LegacyMonolithClient monolithClient;
@Override
public Customer getCustomer(Long id) {
// Получаем данные из монолита в его формате
LegacyCustomerDto legacy = monolithClient.fetchCustomer(id);
// Преобразуем в нашу чистую доменную модель
return Customer.builder()
.id(legacy.getCustId()) // custId → id
.fullName(legacy.getFio()) // fio → fullName
.email(legacy.getElectronicMail()) // electronicMail → email
.build();
}
}
На собеседовании: ключевой посыл — постепенность и безопасность миграции. Упомяните API Gateway как фасад и Anti-Corruption Layer для защиты модели. Частая ошибка — забыть про ACL и допустить «утечку» старых абстракций в новые сервисы.