Когда наш старший разработчик сказал фразу «а давай мы всё это разобьём на микросервисы», я честно испугалась. Мы тянули монолитный бэкенд на PHP и MySQL уже четыре года, и всё работало — если, конечно, не считать те вечные деплои, когда каждый новый фичу требовал часа простоя и молитвы к серверным богам. Но к тому моменту команда выросла до двенадцати человек, и каждый хотел менять свой кусок кода, не наступая на уши другим. Мы решили, что без миграции мы утонем в собственной индустрии.
Первым шагом мы провели инвентаризацию всего монолита: какие модули есть, как они зависят друг от друга, где общие таблицы, где общие функции. Оказалось, что примерно треть кода — это утилиты и общие помощники, которые тянутся везде как паутина. Мы решили не выдёргивать их сразу, а сначала выделить явные бизнес-домены: заказы, пользователи, платежи, уведомления. Именно вокруг этих доменов мы потом построили первые четыре микросервиса на Go и gRPC.
Ключевой момент, который спас нас от простоя, — это паттерн Strangler Fig. Мы не отключали старый монолит, а постепенно перенаправляли трафик на новые сервисы через API-шлюз. Сначала шли внутренние тесты, потом процент трафика 5, 10, 50, 100. Если что-то шло не так, мы за секунды возвращали трафик обратно. Мониторинг и алерты на каждом шаге были обязательными — мы поставили Grafana и Prometheus, чтобы видеть каждую метрику в реальном времени.
Самым болезненным моментом оказались общие данные в базе. Один сервис читал из таблицы users, другой писал в orders, а третий обновлял notifications — всё в одной транзакции. Чтобы это развязать, мы ввели событийную шину на базе Kafka. Сервис пользователей публиковал событие UserCreated, а сервисы заказов и уведомлений подписывались и работали независимо. Да, на первый взгляд это усложняет архитектуру, но вы только попробуйте откатить транзакцию, когда три команды работают параллельно и у каждого свой цикл деплоя.
Ещё один совет, который мне кажется важным: не пытайтесь мигрировать всё за раз. У нас был чёткий план на восемь месяцев с промежуточными результатами каждые два месяца. Каждый новый микросервис мы сопровождали до полного стабильного запуска, а только потом браться за следующий. Да, это дольше, чем хотелось бы, но зато мы не сжигали команду на firefighting и не получали негатив от бизнеса за простои.
Когда мы наконец отключили старый монолит, команда вздохнула с облегчением. Деплой стал занимать минуты вместо часов, мы могли масштабировать сервисы независимо, а время разработки фич сократилось примерно на 30%. Да,运维ные расходы выросли, и мы пришлось нанять ещё одного DevOps-инженера, но это оправданная цена за гибкость и скорость. Если вы сейчас в похожей ситуации и думаете «может, потом», — мой совет: начните хотя бы с инвентаризации и выделения доменов сегодня. Полноценная миграция — это марафон, но каждый шаг делает вашу систему здоровее.
А вы сталкивались с мигацией с монолита на микросервисы? Какой самый неожиданный подводный камень вы нашли, и что помогло его обойти?
Первым шагом мы провели инвентаризацию всего монолита: какие модули есть, как они зависят друг от друга, где общие таблицы, где общие функции. Оказалось, что примерно треть кода — это утилиты и общие помощники, которые тянутся везде как паутина. Мы решили не выдёргивать их сразу, а сначала выделить явные бизнес-домены: заказы, пользователи, платежи, уведомления. Именно вокруг этих доменов мы потом построили первые четыре микросервиса на Go и gRPC.
Ключевой момент, который спас нас от простоя, — это паттерн Strangler Fig. Мы не отключали старый монолит, а постепенно перенаправляли трафик на новые сервисы через API-шлюз. Сначала шли внутренние тесты, потом процент трафика 5, 10, 50, 100. Если что-то шло не так, мы за секунды возвращали трафик обратно. Мониторинг и алерты на каждом шаге были обязательными — мы поставили Grafana и Prometheus, чтобы видеть каждую метрику в реальном времени.
Самым болезненным моментом оказались общие данные в базе. Один сервис читал из таблицы users, другой писал в orders, а третий обновлял notifications — всё в одной транзакции. Чтобы это развязать, мы ввели событийную шину на базе Kafka. Сервис пользователей публиковал событие UserCreated, а сервисы заказов и уведомлений подписывались и работали независимо. Да, на первый взгляд это усложняет архитектуру, но вы только попробуйте откатить транзакцию, когда три команды работают параллельно и у каждого свой цикл деплоя.
Ещё один совет, который мне кажется важным: не пытайтесь мигрировать всё за раз. У нас был чёткий план на восемь месяцев с промежуточными результатами каждые два месяца. Каждый новый микросервис мы сопровождали до полного стабильного запуска, а только потом браться за следующий. Да, это дольше, чем хотелось бы, но зато мы не сжигали команду на firefighting и не получали негатив от бизнеса за простои.
Когда мы наконец отключили старый монолит, команда вздохнула с облегчением. Деплой стал занимать минуты вместо часов, мы могли масштабировать сервисы независимо, а время разработки фич сократилось примерно на 30%. Да,运维ные расходы выросли, и мы пришлось нанять ещё одного DevOps-инженера, но это оправданная цена за гибкость и скорость. Если вы сейчас в похожей ситуации и думаете «может, потом», — мой совет: начните хотя бы с инвентаризации и выделения доменов сегодня. Полноценная миграция — это марафон, но каждый шаг делает вашу систему здоровее.
А вы сталкивались с мигацией с монолита на микросервисы? Какой самый неожиданный подводный камень вы нашли, и что помогло его обойти?