Микросервисы против монолита: когда разделение оправдано
Почему переход на микросервисную архитектуру не является автоматически правильным решением и как определить, готова ли к этому ваша команда.
Микросервисы - одна из самых активно обсуждаемых архитектурных тем последних лет. Netflix, Amazon, Uber - компании, которые приводят в пример, когда говорят о преимуществах этого подхода. И всё чаще я слышу от руководителей: "Нам нужно перейти на микросервисы".
Мой первый вопрос в таких случаях - почему. Не потому что микросервисы плохо работают. А потому что это решение с реальной ценой, и эту цену легко недооценить.
В чём реальная проблема, которую они решают
Микросервисная архитектура возникла как ответ на конкретную проблему крупных компаний: когда над одной системой работают сотни разработчиков, монолитный код становится узким местом. Разные команды мешают друг другу при деплое, сборка занимает часы, один баг в одном модуле останавливает весь релиз.
Это реальная проблема. Но она актуальна при определённом масштабе.
Если у вас три разработчика и один монолитный сервис, проблема не в архитектуре. Если у вас двадцать разработчиков и хорошо структурированный код - возможно, тоже. Переход на микросервисы "потому что так делают большие" - это копирование решения без копирования контекста, в котором оно появилось.
Что вы получаете вместе с микросервисами
Вместе с независимым деплоем отдельных сервисов и возможностью масштабировать их по отдельности вы получаете:
- сложную сетевую топологию, которую нужно поддерживать и отлаживать;
- необходимость в оркестрации - Kubernetes и вся сопутствующая инфраструктура;
- распределённые транзакции и всю связанную с ними сложность;
- умножение задач мониторинга и логирования: вместо одного приложения - десятки сервисов;
- новые типы сбоев: сетевые задержки между сервисами, partial failure, cascade failures.
Каждый из этих пунктов - не абстрактная сложность, а реальная операционная нагрузка на команду. Netflix и Amazon держат эту нагрузку, потому что у них тысячи инженеров и специализированные команды под инфраструктуру.
Когда разделение оправдано
Разделение на сервисы имеет смысл в нескольких ситуациях:
Когда разные части системы имеют принципиально разные требования к масштабированию. Если обработка изображений потребляет в тысячи раз больше ресурсов, чем работа с пользовательскими профилями, - это кандидат на выделение.
Когда разные части системы разрабатываются независимыми командами с разными скоростями релизов. Здесь разделение снимает организационные трения.
Когда нужно использовать разные технологические стеки для разных задач, и смешивать их в одном процессе невозможно или дорого.
Что не является достаточным основанием: желание "делать как Netflix", мода, предположение что это автоматически сделает систему масштабируемой.
Более честный вопрос
Прежде чем говорить о микросервисах, я рекомендую ответить на более приземлённые вопросы:
- Какова реальная проблема, которую мы решаем - медленные деплои, координация команд, масштабирование под нагрузкой?
- Есть ли у нас команда с опытом эксплуатации распределённых систем?
- Есть ли у нас зрелая практика мониторинга и наблюдаемости (observability)?
- Насколько хорошо выделены границы между частями нашей системы - можем ли мы разделить их чисто?
- Готовы ли мы к тому, что первые полгода после перехода команда будет разбираться с инфраструктурой больше, чем с продуктом?
Хороший монолит с чистыми модульными границами часто лучше, чем плохо разрезанные микросервисы. Правильный вопрос - не "монолит или микросервисы", а "какая архитектура соответствует нашему масштабу и нашей команде сейчас".