Microservice Patterns
System Design Interview
- Узнать все требования.
- Количество юзеров.
- Функциональные требования.
Решение проблем
Durability
Сервис упал, сеть оборвалась, брокер перегружен, сообщение потерялось или выполнилось дважды. Уменьшение
риска каскадных отказов.
- Retry(Повторная попытка)
- Circuit Breaker(Предохранитель)
- Idempotent Consumer/Idempotent Endpoint
- Dead Letter Queue (DLQ)
- Transactional Outbox
- Bulkhead (Перегородки)
- Message Persistency (Durable Queues)
Поддержка транзакций между микросервисами.
- Saga
- TCC(Try-Confirm-Cancel) - резервирует ресурсы на этапе try, подтверждает через confirm, если все части
успешны, или отменяет через cancel при ошибке. Часто используется для бронирований и платежей.
Симметричное распределение нагрузки и сложности бизнес-логики.
Для обеспечения последовательных изменений между микросервисами в состояние приложения.
Saga
Saga - если мы используем паттерн "Database per Microservice" нам нужно обеспечить согласованность данных
между сервисами. Управляет распределёнными транзакциями без глобальной блокировки.
Каждый сервис выполняет транзакцию в своей базе и публикует событие.
Ошибки обрабатываются компенсирующими транзакциями.
Реализуется через хореографию или оркестрацию.
Способы координации саг:
Хореография(Choreography)
Хореография(Choreography) - каждая транзакция публикует события, которые запускают транзакции в других
сервисах.
Будут выполнены следующие шаги:
- Order Service (Сервис Заказа) создает Order (Заказ) в статусе pending (в ожидании) и публикует событие
OrderCreated (ЗаказСоздан).
- Customer Service (Сервис Клиента) получает событие и пытается зарезервировать кредит для заказа. После
чего публикует одно из двух событий: CreditReserved (КредитЗарезервирован) или CreditLimitExceeded
(КредитныйЛимитПревышен).
- Order Service (Сервис Заказа) получает событие и изменяет состояние заказа в approved (подтвержден) или
cancelled (отменен).
Оркестровка (Orchestration)
Оркестровка(Orchestration) - оркестратор говорит участникам, какие транзакции должны быть запущены.
Будут выполнены следующие шаги:
- Order Service (Сервис Заказа) создает Order (Заказ) в статусе pending (в ожидании) и создает
CreateOrderSaga (СагаСозданияЗаказа).
- CreateOrderSaga (СагаСозданияЗаказа) отправляет команду ReserveCredit (ЗарезервироватьКредит) в Customer
Service (Сервис Клиента)
- Customer Service (Сервис Клиента) пытается зарезервировать кредит для заказа и отправляет назад ответ
- CreateOrderSaga (СагаСозданияЗаказа) получает ответ и отправляет ApproveOrder (ПодтвердитьЗаказ) or
RejectOrder (ОтменитьЗаказ) команду в Order Service (Сервис Заказа)
- Order Service (Сервис Заказа) изменяет состояние заказа в approved (подтвержден) или cancelled (отменен)
Command and Query Responsibility Segregation(CQRS)
CQRS — это стиль архитектуры, в котором операции чтения отделены от операций записи.
Решает проблему - не симметричное распределение нагрузки и сложности бизнес-логики на read(Query) и
write(Command) - подсистемы Большинство бизнес-правил и сложных проверок находится во write — подсистеме.
При этом читают данные зачастую в разы чаще, чем изменяют.
Недостатки
- Дубликат кода
- Большое количество запросов, для поддержки консистентность.
Event sourcing
Event sourcing - архитектурный шаблон. Все изменения, вносимые в состояние приложения, сохраняются
в той последовательности в которой они происходили.
Помогает эффективно распределять данные между микросервисами.
Преимущества:
- Хранения не объектов, а событий изменения состояний помогает консистенции.
- Надежная система аудирования событий(audit logging).
- В любой момент можно получить актуальное состояние.
- Пониженное сцепление между сущностями.
Недостатки:
- Нужно поддерживать событийность.
- Необходимо реализация CQRS.
- Необходимость поддерживание консистентность.
Database per Microservice
Database per Microservice - микросервисы не имеют доступа к базе соседних сервисов и обращаются между
собой средством REST, или через message broker.
Преимущество
- Слабая связанность сервисов. Изменения в бд одного сервиса не влияют на другие сервисы как при
Shared Database паттерне.
- Каждый сервис может использовать тот тип БД который подходит лучше для его нужд. Например: один сервис
может использовать Elastic поиск, второй NoSQL, третий SQL, если этого требует бизнес логика и NFR.
Недостатки
- Реализация бизнес-транзакций, охватывающих несколько сервисов, довольно комплексное задание.
Распределенных транзакций лучше избегать из-за CAP теоремы. Более того, многие современные (NoSQL)
базы данных их не поддерживают.
- Реализация запросов, которые джоинит данные с разных баз данных, не тривиальная задача.
- Сложность управления несколькими базами данных SQL и NoSQL.
Retry pattern
Retry pattern - механизм повторения запросов.
Виды:
- Fixed delay - фиксированное время.
- Incremental delay - время между попытками увеличивается.
- Exponential backoff - время между попытками увеличивается экспоненциально.
Circuit Breaker
pattern - защищает сервисы от избыточной нагрузки и отказов.
Помогает "Retry pattern" не добить нагруженный сервис количеством запросов.
Как работает:
- Замеряет ошибки – если система часто отвечает сбоем, то "выключает" запросы.
- Блокирует вызовы – на время переключается в режим отказа (open state).
- Пробует восстановиться – спустя время делает тестовые запросы и, если сервис снова работает,
возвращает его в работу.
Timeout pattern
Timeout pattern - ограничивает время ожидания запросов.
Виды timeout:
- Connection timeout - попытка соединения.
- Read/Write(response) timeout - время на запрос.
- Idle Timeout - автоматический разрыв соединения, если оно неактивно в течение определенного времени.
Fallback pattern
Fallback pattern - запасное действие в случае ошибки.
Виды fallback:
- Response by default
- Change client - попробовать другой способ получить данные(если такой есть)
Bulkhead pattern
Bulkhead pattern - используется для изоляции различных компонентов системы, чтобы сбои в одной части
не затронули всю систему. Для повышения отказоустойчивости и изоляции сбоев.
Применение Bulkhead pattern:
- Разделение ресурсов — выделение отдельных пулов потоков, соединений с базой данных или очередей
сообщений для разных сервисов.
- Изоляция отказов — если один сервис перегружен или выходит из строя, другие продолжают работать.
- Повышение устойчивости — уменьшение риска каскадных отказов.
Publisher–Subscriber(Pub/Sub)
Publisher–Subscriber (Pub/Sub) модель - архитектурный паттерн для обмена сообщениями между компонентами
системы, где отправители сообщений (publishers) не знают о получателях (subscribers), а доставка
обеспечивается через event bus / broker (например, Kafka, RabbitMQ, Redis Pub/Sub).
Основные идеи:
- Publisher публикует событие (сообщение) в определённый канал/тему (topic).
- Subscriber подписывается на интересующую его тему.
- Message Broker (или шина событий) принимает сообщение от издателя и доставляет всем подписчикам,
которые слушают этот канал/тему.
Преимущества:
- Слабая связанность — издатели и подписчики не знают друг о друге напрямую.
- Масштабируемость — легко добавлять новых подписчиков.
- Асинхронность — события можно обрабатывать в разное время.
- Гибкость — разные системы/сервисы могут взаимодействовать через общий брокер.
Недостатки:
- Сложность отладки — трудно проследить, кто именно обработал событие.
- Необходимость брокера — требуется дополнительная инфраструктура (Kafka, RabbitMQ и т.п.).
- Гарантии доставки зависят от реализации брокера (может быть at-most-once, at-least-once, exactly-once).
Реализации:
- Kafka (event streaming)
- RabbitMQ (очереди + pub/sub)
- Redis Pub/Sub (простая реализация)
- Google Pub/Sub, AWS SNS, Azure Event Grid (облачные решения)
Features flag
Feature flag - это приём в разработке, который позволяет включать или выключать определённые функции
приложения без деплоя новой версии.
Зачем они нужны?
- Постепенное выкатывание фич (progressive rollout) - можно включить новую фичу сначала 1% пользователей,
потом 10%, потом всем.
- A/B-тестирование - показываем разным группам разные варианты интерфейса/логики.
- Возможность быстро выключить фичу - если что-то сломалось → просто выключаем флажок, не делая откат деплоя.
- Раздельное развитие - несколько команд могут работать над функциями, которые ещё не готовы, но уже
находятся в кодовой базе.
- Безопасный деплой - код уже в проде, но скрыт до момента включения флага.
Виды feature flags
- Release flags - для постепенного и безопасного релиза новой фичи.
- Experiment flags - для экспериментов и A/B тестов.
- Ops flags - для аварийного отключения компонентов (например, дорогих по ресурсам задач).
- Permission flags - включают функции только определённым пользователям, ролям или тарифам.
Где хранятся флаги?
- В конфиге на сервере
- В базе данных
Минусы
- Фич-флаги надо чистить после использования, иначе код превращается в хаос.
- Много флагов → много ветвлений → сложнее тестировать.