Содержание

Микросервисы: границы, данные и коммуникация

Микросервисы - это не "много маленьких папок" и не "монолит, разрезанный на десять процессов". Это архитектурный подход, где независимые сервисы имеют свои границы ответственности, данные, контракт и цикл релиза.

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

Поэтому микросервисы нужно выбирать осознанно.

Когда микросервисы оправданы

Микросервисы могут быть полезны, когда:

  • разные части продукта развиваются независимо;
  • есть несколько команд;
  • нагрузка на компоненты сильно отличается;
  • нужны разные циклы релизов;
  • часть системы требует отдельного масштабирования;
  • монолит стал трудно менять из-за организационных границ.

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

Граница сервиса

Сервис должен отвечать за понятную бизнес-область:

  • auth-service - пользователи, пароли, токены, сессии;
  • books-service - книги, отзывы, поиск;
  • notification-service - email, push, Telegram-уведомления;
  • billing-service - платежи, счета, подписки.

Плохие границы:

  • utils-service;
  • database-service;
  • common-service;
  • validation-service.

Такие названия обычно означают, что граница проведена технически, а не по смыслу продукта.

Хороший сервис можно описать одним предложением: "этот сервис отвечает за ...". Если предложение распадается на пять несвязанных частей, граница слабая.

Database per service

Один из ключевых принципов: сервис владеет своими данными. Другие сервисы не читают его таблицы напрямую.

Плохо:

books-service -> auth.users table

Лучше:

books-service -> auth-service API

Почему это важно? Если books-service напрямую читает таблицу пользователей, auth-service уже не может свободно менять схему. База становится скрытым публичным API.

На практике иногда несколько сервисов физически живут в одной СУБД, но у каждого должна быть своя схема или набор таблиц, за которые он отвечает.

API Gateway

API Gateway принимает внешние запросы и направляет их во внутренние сервисы.

Он может делать:

  • маршрутизацию;
  • проверку access token;
  • rate limiting;
  • request id;
  • базовое логирование;
  • простую агрегацию ответов.

Пример:

frontend -> gateway -> auth-service -> books-service -> billing-service

Gateway не должен превращаться в огромный сервис с бизнес-логикой всего продукта. Если вся логика оказалась в gateway, микросервисы стали тонкими wrappers вокруг данных.

BFF

BFF означает Backend for Frontend. Это backend, заточенный под конкретный клиент: web, mobile, admin panel.

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

web app -> web-bff -> internal services mobile -> mobile-bff -> internal services

BFF полезен, когда клиенты реально отличаются. Если различий нет, отдельный BFF может быть лишней сложностью.

Синхронная коммуникация

HTTP или gRPC подходят, когда клиенту нужен ответ прямо сейчас:

frontend -> gateway -> books-service

Плюсы:

  • просто понять;
  • легко вызвать;
  • ответ приходит сразу;
  • удобно для query-запросов.

Минусы:

  • зависимость от доступности другого сервиса;
  • каскадные сбои;
  • рост latency;
  • необходимость таймаутов и retry.

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

Асинхронная коммуникация

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

orders-service -> OrderCreated event -> notification-service

Плюсы:

  • сервисы слабее связаны;
  • нагрузку можно сглаживать;
  • временная недоступность получателя не всегда ломает основной сценарий;
  • можно добавить нового обработчика события без изменения отправителя.

Минусы:

  • сложнее отлаживать;
  • появляются повторные доставки;
  • результат не мгновенный;
  • нужна идемпотентность;
  • нужен dead-letter или другой механизм для плохих сообщений.

События

Событие описывает факт, который уже произошел:

BookCreated OrderPaid UserRegistered

Плохо:

CreateBook SendEmail

Это уже команды, а не события.

Событие обычно содержит:

  • event_id;
  • тип события;
  • время;
  • id сущности;
  • минимальные данные, нужные получателям;
  • версию схемы.

Пример:

{ "event_id": "7f7c9c2e-9a2a-4a49-9b8a-bf6c2f1d0d9b", "type": "BookCreated", "created_at": "2026-05-23T10:00:00Z", "book_id": "book_123", "title": "Distributed Systems" }

Idempotency

Очереди часто доставляют сообщение больше одного раза. Обработчик должен выдерживать повторную доставку.

Идемпотентный обработчик не ломает состояние, если событие пришло дважды:

if event_id already processed: skip else: handle event and save event_id

Без этого повторное событие может отправить два email, дважды начислить бонус или создать дубликат записи.

Типичные ошибки

  1. Делить систему на микросервисы слишком рано.
  2. Делать сервисы вокруг технических слоев, а не бизнес-областей.
  3. Использовать общую базу как интеграционный слой.
  4. Не ставить timeout на вызовы других сервисов.
  5. Повторять неидемпотентные операции без ключа.
  6. Прятать всю бизнес-логику в gateway.
  7. Не иметь request id и distributed tracing.

Чеклист микросервиса

  1. У сервиса есть четкая область ответственности.
  2. У сервиса свои данные или своя схема данных.
  3. Внешний контракт описан.
  4. Есть healthcheck и readiness.
  5. Есть structured logs с request id.
  6. Есть таймауты на внешние вызовы.
  7. Retry ограничены и не ломают состояние.
  8. Повторные события обрабатываются безопасно.
  9. Общие библиотеки не тащат бизнес-логику между сервисами.
  10. Команда понимает, зачем этот сервис отделен от монолита.

Следующий шаг после статьи

Закрепите тему в реальном проекте и продолжайте обучение на курсах Praxis.

Продолжить изучение

Выбери следующую статью по маршруту или углубись в смежную тему.

Похожие статьи