Как распилить монолит и заменить его микросервисами

Введение

Представим, что вы работаете в небольшой компании, занимающейся, например, ритейлом. Вы – руководитель IT-отдела. Компания у вас небольшая, человек, скажем 30, IT-персонала: десяток разработчиков, архитектор, парочка DevOps-специалистов, QA-инженеров, менеджеры, аналитики, специалисты поддержки.

У вас все идет хорошо – бизнес растет, задачи закрываются, багов немного, но и те, что есть – некритичные и не приводят к простою и потере денег и клиентов. Точнее, шло хорошо, потому что в определенный момент вы стали замечать, как время time-to-market стало увеличиваться, релизы растягиваться, количество багов тоже расти. Последней каплей было, когда однажды, в летнюю ночь с субботы на воскресенье, вас разбудило не пение птиц, а звонок дежурного разработчика с теми самыми словами, которые не хочет слышать никто и никогда – база лежит, рабочих бэкапов за последний месяц нет.

Понимая, что утро сегодня начинается не с кофе, вы, вскакивая с постели, даете инструкции разработчику, где взять бэкапы и что делать с отсутствующими данными, а в голове все крутится мысль – “Я же говорил! Говорил, что нужно тестировать бэкапы”. Но как тестировать бэкап, когда его размер уже перевалил за 4 терабайта? Бухгалтерия ни за что не одобрит расширение в 2 (а, может быть, и в 3) раза затрат на инфраструктуру. Возможно, получится пробить увеличение бюджета теперь, когда есть козырь в рукаве. Не стоит экономить на том, что спасет бизнес.

“Пу-пу-пу-пу” – вырвалось у вас на автомате. “Мяяяяяу” – вырвалось у кота. Ведь если двуногий встал с кровати, это означает одно – пришло время есть. Накормив кота, починив сервер вместе с ведущим разработчиком на пару, оценив потери от простоя длинною в 6 часов, и, наконец-то, сварив себе кофе, вы решили: “Пора что-то менять”. Эти выходные вы проведете в тяжких думах о судьбе IT-инфраструктуры и процессов в вашей компании.

Разделяй и властвуй

Первое, что вы сделали в понедельник с утра – запланировали встречу на 3 часа с архитектором. В ходе разговора все аргументы сводились к тому, что система слишком большая для того, чтобы эффективно ее развивать и поддерживать. Монолитная кодовая база, очень высокая связанность внутри компонентов, гигантский унаследованный нигде не использующийся функционал. Кажется, вы знали далеко не все о своей системе.

В итоге вы решаете распилить все на микросервисы и начать работать командами по 2-3 разработчика. К тому же, вы обнаружили, что верхнеуровневых у вас получается 4 подсистемы – биллинг/платежи, клиентская, веб-фронт, аналитическая. Эти подсистемы, ко всему прочему, еще и отражают все стороны вашего бизнеса. Будет очень просто вести общение с бизнес-подразделениями и разграничивать ответственность. Потому что сейчас все отвечают за всё, то есть никто не отвечает за что-то конкретное.

Итак, первый шаг сделан – определены зоны ответственности и будущие подсистемы.

Далее, вы решили начать реализацию с подсистемы биллинга и платежей. Но с чего конкретно начать? Желающих стать ответственными за биллинг вы нашли, теперь необходимо решить главную проблему – как выделить из кодовой базы новый компонент.

Первым шагом вы решили внутри существующей кодовой базы выделить отдельный пакет, куда собрать все необходимые для подсистемы классы. К счастью, к этому моменту архитектор подготовил набор метрик, которые вы встроили в процесс CI/CD – эти метрики будут измерять связность компонентов кода в новом пакете при каждой сборке и уведомлять письмом на почту, если связанность внутри пакета падает, а снаружи растет.

Получилось очень хорошо – вы обнаружили несколько явных подсистем, которые в будущем можно выделить в отдельные микросервисы, но не сейчас. Сейчас предстоит самое важное и интересное.

Адаптируй и властвуй

Отлично, спустя 2 недели активных работ и нескольких релизов, вы выделили отдельный пакет внутри существующей кодовой базы, изолировали связи с ним в адаптерах и теперь настала пора сделать ctrl+c, ctrl+v, а именно – создать инфраструктуру для отдельного сервиса биллинга – репозиторий, CI/CD, отдельная виртуальная машина в отдельном ЦОД.

Вы уже выбрали транспорт для замены пакета в монолитном приложении, описали адаптеры, пришло время переносить код.

На этом этапе самое важное – сделать как можно более наблюдаемой интеграцию с новым сервисом, чтобы в любой момент времени вы, в идеале взглянув на дашборд, могли сказать, что происходит с вашим сервисом.
Вы также предусмотрели плавный переход с возможностью быстрого переключения к предыдущей версии. Согласитесь, ведь не очень приятно узнать, что вы допустили критическую ошибку, не позволяющую обслуживать клиентов, уже после релиза и на исправление у вас уйдет несколько часов или, что еще хуже, дней.

Вы – молодец, ведь за столь короткий срок проделали вместе с командой огромный объем работы. Можно и в отпуск сходить, но перед этим…

Мигрируй и властвуй

Осталась последняя деталь – миграция данных.

Вы можете оставить общую бд, как было ранее в монолите, но в этом случае вы лишаетесь выгоды микросервисов, а именно – независимости, отказоустойчивости и простоты эксплуатации отдельно взятого микросервиса.

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

Путей и возможностей для миграции великое множество – вы можете выбрать любой, наиболее подходящий под вашу инфраструктуру и особенности. Например, вы можете настроить репликацию и в какой-то момент сделать реплику мастер инстансом базы данных и переключить на нее ваш микросервис, а из старой мастер базы данных удалить таблицы.

Если вам требуется более сложная репликация с изменением структуры базы данных (например, вам необходимо поменять схему базы данных, в которую будет сохранять данные ваше приложение, реализующее бизнес правила), то можно рассмотреть вариант написания своими силами приложения-репликатора, которое будет в режиме реального времени (например, с помощью change data capture) копировать изменения из одной базы данных в другую, в пути видоизменяя данные как вам требуется.

Главные критерии в этом процессе – наблюдаемость и обратная совместимость.

Заключение

Итак, вы прошли путь по выделению части монолита в микросервис и можете с гордостью ехать на конференцию чтобы рассказать о своем опыте, а я позволю себе подытожить ваш опыт в виде ключевых этапов миграции:

  1. Выделить доменную зону и назначить ответственную команду за развитие доменной зоны.
  2. Разработать и внедрить метрики качества прохождения каждого этапа миграции (желательно встроить в процесс CI/CD).
  3. Изолировать в доменную зону в исходном коде монолита.
  4. Разработать адаптеры к доменной зоне.
  5. Вынести изолированный код в отдельный модуль.
  6. Мигрировать данные.
  7. Повторить для всех доменных зон монолита.

А чтобы ваш путь был менее тернистым и длился минимально возможное время - приходите к нам в softwarecats.dev. Мы собрали за вас все грабли, прошлись по всем багам, пролили немало горьких слез и теперь обладаем широкой экспертизой в области проектирования и миграций с монолитов на микросервисы и обратно (как Бильбо Бэггинс).

Если вы чувствуете, что вам предстоит такой процесс, приходите к нам – будем рады помочь! Вы всегда можете с нами связаться
через почту: client@softwarecats.dev
телеграм @alex_zarubin

И мы договоримся с вами об онлайн-встрече, чтобы подробнее обсудить ваш проект и вашу проблему.
Александр Романюк
Team lead java dev