Архитектурные основы

4 мин чтения

Монолит: когда одна система выгоднее микросервисов

Монолит не обязан быть техническим долгом. Разбираемся, когда общая система экономит время и деньги, где появляются ограничения и стоит ли переходить на микросервисы.

Монолит часто предлагают заменить микросервисами ещё до того, как кто-нибудь сформулировал, какую именно проблему должна решить замена. Звучит знакомо: система выросла, релизы стали сложнее — значит, пора её разделить. Но иногда разделение лишь превращает одну проблему в десяток новых.

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

Одно здание с несколькими связанными помещениями: аналогия монолитного приложения, где разные функции работают внутри общей системы
Монолит похож на здание, в котором разные отделы пользуются общими коммуникациями. Вместе работать удобно, но реконструкция одного этажа может затронуть соседей. Это объясняющая аналогия, а не схема программной системы.

Одна система — не обязательно одна большая путаница

Представим интернет-магазин. Каталог, корзина, заказы и оплата могут быть частями одного приложения. Команда собирает и развёртывает его как единое целое. Это и есть монолитная архитектура в упрощённом виде.

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

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

Почему на старте это нередко лучший выбор

Когда продукт ещё меняется, границы будущих функций не всегда очевидны. Сегодня оформление заказа выглядит одним образом, через месяц бизнес проверяет другую модель. В монолите такую перестройку часто проще сделать одной командой и одним релизом.

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

Для руководителя здесь вполне практичная экономика: сколько времени команда тратит на продукт, а сколько — на эксплуатацию самой архитектуры? Вторые расходы редко показывают на презентациях с красивыми схемами.

Где начинается реальная цена монолита

Допустим, одна команда меняет скидки, другая — оплату, третья — личный кабинет. Если все изменения попадают в один релиз, появляются общие проверки и необходимость договариваться о моменте поставки. Чем больше участников, тем дороже координация.

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

Есть и технические ограничения. Если тяжёлый расчёт потребляет все ресурсы общего процесса, он может влиять на остальные функции. В типичном монолите нельзя столь же свободно масштабировать отдельную часть, как отдельный сервис. При этом всё приложение иногда можно масштабировать несколькими экземплярами — утверждение «монолит не масштабируется» просто неверно.

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

Микросервисы — не бесплатная независимость

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

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

Именно поэтому вопрос «почему мы до сих пор не на микросервисах?» не слишком полезен. Лучше спросить: какая независимость нужна нам настолько, что мы готовы за неё постоянно платить?

Что я бы проверил до разделения системы

Сначала посмотрел бы на реальные задержки. Релизы тормозят из-за общей сборки? Из-за ручного тестирования? Команды постоянно правят одни и те же файлы? Или решения неделями проходят согласование? У каждой причины свой способ лечения.

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

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

Не пора ли всё-таки менять архитектуру?

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

Но это повод исследовать варианты, а не приказ немедленно распилить приложение. Иногда подходит модульный монолит, иногда — выделение одного проблемного компонента, иногда — полноценная сервисная архитектура.

Монолит не нужно защищать из принципа. Его нужно сохранять, пока общая система обходится дешевле той независимости, которую обещает разделение. Архитектура должна помогать менять бизнес, а не демонстрировать зрелость технического отдела.