Прежде чем резать монолит на части, важно понять: зачем вообще нужны микросервисы? Это не серебряная пуля и не модный тренд ради тренда. не только решает конкретные проблемы, но и создаёт новые. Понимание плюсов и минусов — ключевой навык архитектора.
Netflix — один из пионеров микросервисной архитектуры. В 2008 году у них произошёл крупный сбой базы данных, который остановил отправку DVD на 3 дня. После этого они начали миграцию в облако и декомпозицию монолита. Сегодня у Netflix более 700 микросервисов, каждый из которых может деплоиться независимо несколько раз в день.
Amazon пришёл к микросервисам ещё раньше. В 2002 году Джефф Безос разослал знаменитый "API Mandate" — все команды должны общаться только через API, никакого прямого доступа к базам данных других команд. Это привело к концепции "Two-Pizza Teams" — команда должна быть достаточно маленькой, чтобы её можно было накормить двумя пиццами (6-10 человек). Каждая такая команда владеет одним или несколькими сервисами.
Spotify использует модель "Squads, Tribes, Chapters, Guilds" — автономные команды (squads), каждая из которых владеет частью продукта и может деплоить независимо. Это позволило им масштабироваться до сотен разработчиков без потери скорости.
1. Независимый деплой
В монолите изменение одной строки кода требует пересборки и деплоя всего приложения. Если релизный цикл — раз в неделю, ваше изменение ждёт своей очереди. В микросервисной архитектуре каждый сервис деплоится отдельно. Команда auth-service может выкатить новую фичу, не дожидаясь команды books-service.
2. Масштабирование по частям
Представьте: 90% нагрузки приходится на чтение каталога книг, а регистрация пользователей — редкая операция. В монолите вы масштабируете всё приложение целиком. В микросервисах можно запустить 10 копий books-service и только 2 копии auth-service, экономя ресурсы.
3. Изоляция сбоев
Баг в коде рецензий не должен ронять аутентификацию. В монолите один баг может убить весь сервис. В микросервисах падение books-service оставляет auth-service работающим — пользователи могут логиниться, хотя книги временно недоступны.
4. Технологическая гибкость
Разные задачи требуют разных инструментов. Сервис машинного обучения можно написать на Python, высоконагруженный API — на Go, а legacy-интеграцию — на Java. Каждая команда выбирает лучший инструмент для своей задачи.
Часто главные причины перехода на микросервисы — организационные, а не технические.
1. Закон Конвея
"Организации проектируют системы, которые копируют структуру коммуникаций в этих организациях."
Если у вас одна команда — монолит работает отлично. Если у вас 10 команд, работающих над одним монолитом — начинаются проблемы: конфликты при слиянии кода, очередь на деплой, непонятно кто за что отвечает. Микросервисы позволяют структурировать систему так же, как структурирована организация.
2. Автономные команды
Команда владеет сервисом от идеи до продакшена: пишет код, тестирует, деплоит, мониторит, чинит в 3 часа ночи. Это называется "You build it, you run it" (построил — сам и поддерживаешь). Такая ответственность мотивирует писать качественный код, полностью протестированный и готовый к работе.
3. Параллельная разработка
В монолите 5 команд работают в одном репозитории — merge-конфликты, сломанные тесты от чужого кода, ожидание код-ревью. В микросервисах каждая команда работает в своём репозитории. Единственная точка интеграции — API контракт.
4. Чёткие границы ответственности
"Кто отвечает за логику расчёта рейтинга?" В монолите ответ может быть неочевиден — код размазан по нескольким местам. В микросервисах ответ простой: команда books-service.
Микросервисы — это не бесплатное удовольствие. Они решают одни проблемы, но создают другие.
1. Сетевая сложность
Вместо вызова функции userService.GetUser(id) — HTTP-запрос через сеть. Сеть ненадёжна: запросы могут теряться, таймаутиться, приходить не в том порядке. Нужны повторные отправки запросов, , таймауты.
Circuit breaker (автоматический выключатель) — это паттерн, который временно блокирует запросы к неработающему сервису. Если сервис не отвечает несколько раз подряд, circuit breaker "размыкается" и сразу возвращает ошибку без попытки запроса. Это защищает от каскадных сбоев: если один сервис упал, остальные не тратят ресурсы на бесполезные запросы. Через некоторое время circuit breaker пробует "замкнуть" цепь снова — возможно, сервис уже восстановился.
2. Распределённые транзакции
В монолите: BEGIN; UPDATE users...; UPDATE books...; COMMIT; — атомарно. В микросервисах users и books в разных базах — нельзя сделать одну транзакцию. Нужны паттерны типа , конечная согласованность данных (), механизмы отмены транзакции.
3. Операционная нагрузка
Один монолит — один сервис для мониторинга, один лог-файл, один деплой. 20 микросервисов — 20 сервисов, 20 источников логов, 20 деплоев. Нужны: централизованный сбор логов, отслеживание запросов между сервисами (), автоматическое обнаружение сервисов (), оркестрация контейнеров (Kubernetes).
4. Debugging сложнее
Запрос пользователя проходит через 5 сервисов. Где ошибка? Нужен распределенная трассировка (Jaeger, Zipkin), сквозные идентификаторы запросов, централизованные логи. Без этой инфраструктуры поиск ошибок в системе превращается в кошмар.
5. Дублирование и консистентность
Каждый сервис может иметь свою копию данных о пользователе. Как синхронизировать? Что если данные разошлись? Eventual consistency — сложная концепция для понимания и реализации.
Микросервисы — не для всех. Признаки того, что вам лучше остаться с монолитом:
Маленькая команда (< 5-7 человек)
Накладные расходы на микросервисы не окупаются. Одна команда может эффективно работать в одном репозитории без конфликтов.
Ранняя стадия продукта
Вы ещё не понимаете домен, границы будут меняться. Разрезать монолит на неправильные части — хуже, чем не разрезать вообще. Как говорит Martin Fowler: "Monolith first".
Нет DevOps культуры и инфраструктуры
Микросервисы требуют: CI/CD пайплайны, container orchestration (Kubernetes), централизованное логирование, мониторинг, service mesh. Если у вас ручной деплой по SSH — сначала постройте инфраструктуру.
Сильная связанность данных
Если большинство операций требуют JOIN между таблицами разных доменов — разделение будет болезненным. Микросервисы работают лучше, когда домены относительно изолированы.
В этом курсе мы делаем декомпозицию не потому, что наш монолит "перерос" — это учебный проект. Мы делаем это, чтобы:
В реальной коммерческой разработке решение о декомпозиции принимается на основе конкретных проблем: команда выросла и не может эффективно работать в одном репозитории, нужно масштабировать отдельные части системы, требуется изоляция сбоев для критичных сервисов.
Зачем: Зафиксировать архитектурное решение в README до написания кода — чтобы иметь ориентир при декомпозиции и документацию для команды.
Что делаем:
Создайте файл README.md в корне проекта. Опишите в нём:
auth-service — регистрация, авторизация, управление пользователямиbooks-service — каталог книг, рецензииЭтот README будет обновляться по мере развития проекта.
Примерная структура README:
# Bookshelf — Microservices
## Почему микросервисы?
Монолит стал узким местом: ...
## Архитектура
- **auth-service** (порт 8081) — регистрация, авторизация, управление пользователями
- **books-service** (порт 8082) — каталог книг, рецензии
Каждый сервис имеет свою базу данных (Database per Service).
## Компоненты системы
| Компонент | Назначение |
|-----------|-----------|
| auth-service | Аутентификация и пользователи |
| books-service | Книги и рецензии |
| auth-postgres | БД для auth-service |
| books-postgres | БД для books-service |
| frontend | React-приложение |
README.md существует в корне проекта и содержит описание архитектуры: два сервиса (auth-service и books-service)README.md описаны причины декомпозиции монолита на микросервисыREADME.md перечислены компоненты системы: auth-service, books-service, auth-postgres, books-postgres