Микросервисы и архитектурные паттерны
Монолит vs Микросервисы
Монолитная архитектура
┌─────────────────────────────────────────────┐
│ МОНОЛИТ │
│ ┌─────────┬──────────┬──────────────┐ │
│ │ Auth │ Orders │ Products │ │
│ │ Module │ Module │ Module │ │
│ ├─────────┴──────────┴──────────────┤ │
│ │ Shared Database │ │
│ └───────────────────────────────────┘ │
│ Один процесс │
│ Один деплой │
│ Одна кодовая база │
└─────────────────────────────────────────────┘Преимущества монолита:
- Простая разработка и отладка
- Простой деплой (один артефакт)
- Нет сетевых задержек между модулями
- Транзакции в одной БД
Недостатки монолита:
- Масштабируется только целиком
- Сбой в одном модуле ломает всё
- Сложность растёт экспоненциально
- Долгие циклы деплоя
Микросервисная архитектура
┌──────────┐ ┌──────────┐ ┌──────────────┐
│ Auth │ │ Orders │ │ Products │
│ Service │ │ Service │ │ Service │
│ (Node.js)│ │ (Go) │ │ (Python) │
├──────────┤ ├──────────┤ ├──────────────┤
│ Auth DB │ │ Orders DB│ │ Products DB │
│ (Redis) │ │(Postgres)│ │ (MongoDB) │
└──────────┘ └──────────┘ └──────────────┘
↕ ↕ ↕
──────── API Gateway / Message Broker ────────Преимущества:
- Независимое масштабирование каждого сервиса
- Технологическая свобода (polyglot)
- Изолированные сбои
- Маленькие команды, быстрый деплой
Недостатки:
- Сложность распределённой системы
- Сетевые задержки
- Согласованность данных (eventual consistency)
- Мониторинг и отладка сложнее
Когда переходить на микросервисы
Правило
Не начинайте с микросервисов! Начните с монолита и выделяйте сервисы по мере необходимости.
┌─────────────────────────────────────────────────────────┐
│ Стоит переходить, если: │
│ │
│ ✓ Команда > 10-15 разработчиков │
│ ✓ Разные модули масштабируются по-разному │
│ ✓ Нужна независимость деплоя │
│ ✓ Разные требования к технологиям │
│ ✓ Модули имеют чёткие границы (bounded contexts) │
├─────────────────────────────────────────────────────────┤
│ НЕ стоит, если: │
│ │
│ ✗ Маленькая команда (1-5 человек) │
│ ✗ Стартап на ранней стадии │
│ ✗ Нет опыта работы с распределёнными системами │
│ ✗ Границы между модулями нечёткие │
└─────────────────────────────────────────────────────────┘Коммуникация между сервисами
Синхронная (REST / gRPC)
Сервис A ────HTTP/REST────→ Сервис B
←──── Ответ ─────
Сервис A ────gRPC──────→ Сервис B
←── Ответ ────
REST:
+ Простой, понятный (JSON over HTTP)
+ Широкая поддержка
- Больше накладных расходов (JSON parsing)
gRPC:
+ Быстрее (Protocol Buffers, HTTP/2)
+ Строгая типизация (proto файлы)
+ Стриминг
- Сложнее отлаживатьАсинхронная (Message Broker)
┌─────────────────┐
Сервис A ──msg──→│ Message Broker │──msg──→ Сервис B
│ (Kafka/RabbitMQ)│──msg──→ Сервис C
└─────────────────┘──msg──→ Сервис D
Преимущества:
+ Сервисы не зависят друг от друга
+ Буферизация при пиковых нагрузках
+ Гарантия доставки
+ Реплей сообщений (Kafka)
Недостатки:
- Eventual consistency
- Сложнее отладка
- Дополнительная инфраструктураПаттерны обмена сообщениями
1. Request-Reply:
A ──request──→ Queue ──→ B
A ←──reply───← Queue ←── B
2. Publish-Subscribe:
Publisher ──→ Topic ──→ Subscriber 1
──→ Subscriber 2
──→ Subscriber 3
3. Event-Driven:
Order Service ──"OrderCreated"──→ Event Bus
Payment Service ←─────────────────── (listens)
Notification Service ←────────────── (listens)
Inventory Service ←──────────────── (listens)API Gateway
Единая точка входа для всех клиентских запросов.
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Web App │ │Mobile App│ │ Partner │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
└──────────────┼──────────────┘
│
┌────────▼────────┐
│ API Gateway │
│ │
│ • Routing │
│ • Auth │
│ • Rate Limiting │
│ • Load Balance │
│ • Caching │
│ • Logging │
└────────┬────────┘
│
┌───────────┼───────────┐
↓ ↓ ↓
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Users │ │ Orders │ │Products │
│ Service │ │ Service │ │ Service │
└─────────┘ └─────────┘ └─────────┘Популярные решения:
- Kong
- AWS API Gateway
- Nginx (как reverse proxy)
- Traefik
Service Discovery
Как сервисы находят друг друга в динамическом окружении.
Client-Side Discovery:
┌──────────┐ 1. Запрос ┌───────────────┐
│ Сервис A│ ──────────────→│ Service │
│ │ ←──────────────│ Registry │
│ │ 2. Список │ (Consul/Etcd) │
│ │ инстансов └───────────────┘
│ │
│ │ 3. Прямой запрос
│ │ ──────────────→ Сервис B (instance 2)
└──────────┘
Server-Side Discovery:
┌──────────┐ 1. Запрос ┌───────────────┐
│ Сервис A│ ──────────────→│ Load Balancer │
└──────────┘ │ │
│ 2. Маршрутиз. │
└───────┬───────┘
│
┌─────────────┼──────────────┐
↓ ↓ ↓
Сервис B Сервис B Сервис B
(inst. 1) (inst. 2) (inst. 3)Паттерны отказоустойчивости
Circuit Breaker
Предотвращает каскадные сбои, "размыкая цепь" при частых ошибках.
┌─────────────┐
│ CLOSED │ ← Нормальная работа
│ (замкнут) │ Запросы проходят
└──────┬──────┘
│ Ошибки > порога
↓
┌─────────────┐
│ OPEN │ ← Цепь разомкнута
│ (разомкнут) │ Запросы отклоняются
└──────┬──────┘ (fail fast)
│ Таймаут
↓
┌─────────────┐
│ HALF-OPEN │ ← Пробные запросы
│ (полуоткрыт)│ Если OK → CLOSED
└─────────────┘ Если ошибка → OPENRetry с Exponential Backoff
Попытка 1: сразу
Попытка 2: через 1 сек
Попытка 3: через 2 сек
Попытка 4: через 4 сек
Попытка 5: через 8 сек ← max backoff
+ Jitter (случайная задержка) для предотвращения
"thundering herd" — когда все клиенты повторяют
одновременноBulkhead (Переборка)
Изоляция ресурсов, чтобы сбой в одном компоненте не затронул другие.
┌─────────────────────────────────────────────┐
│ Thread Pool: Orders (20 потоков) │
│ ████████████████████ │
├─────────────────────────────────────────────┤
│ Thread Pool: Payments (10 потоков) │
│ ██████████ ← Если Payment завис, │
│ Orders продолжает работать │
├─────────────────────────────────────────────┤
│ Thread Pool: Notifications (5 потоков) │
│ █████ │
└─────────────────────────────────────────────┘Saga Pattern
Управление распределёнными транзакциями через последовательность локальных транзакций.
Хореография (Event-Based)
Order Payment Inventory Shipping
Service Service Service Service
│ │ │ │
│ OrderCreated │ │
├──────────→│ │ │
│ │ PaymentProcessed │
│ ├──────────→│ │
│ │ │ ItemsReserved
│ │ ├──────────→│
│ │ │ │ ShippingScheduled
│ │ │ ├──→ Done ✓
Компенсация при ошибке:
│ │ │ InventoryFailed
│ │ ├──── X
│ │ RefundIssued │
│ ├←──────────│ │
│ OrderCancelled │ │
├←──────────│ │ │Оркестрация (Orchestrator)
┌──────────────┐
│ Saga │
│ Orchestrator │
└──────┬───────┘
│
┌──────────┼──────────┬──────────┐
↓ ↓ ↓ ↓
┌─────────┐┌─────────┐┌─────────┐┌─────────┐
│ Order ││ Payment ││Inventory││Shipping │
│ Service ││ Service ││ Service ││ Service │
└─────────┘└─────────┘└─────────┘└─────────┘
Orchestrator управляет порядком шагов
и компенсациями при ошибкахАрхитектурные стили
Event-Driven Architecture
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Producer │────→│ Event Bus │────→│ Consumer │
│ │ │ (Kafka) │────→│ Consumer │
│ Генерирует │ │ │────→│ Consumer │
│ события │ │ Хранит и │ │ │
│ │ │ маршрутизир. │ │ Реагируют │
└──────────────┘ └──────────────┘ └──────────────┘Serverless
Событие → Function → Результат
┌───────────┐ ┌─────────────┐ ┌──────────┐
│ HTTP запрос│──→│ Lambda/ │──→│ DynamoDB │
│ S3 upload │──→│ Cloud Func │──→│ S3 │
│ Timer │──→│ Azure Func │──→│ SQS │
│ Queue msg │──→│ │──→│ Email │
└───────────┘ └─────────────┘ └──────────┘
+ Нет управления серверами
+ Автоматическое масштабирование
+ Оплата за выполнение (pay-per-use)
- Cold start
- Ограничения по времени выполнения
- Vendor lock-inSidecar Pattern
┌─────────────────────────────────────┐
│ Pod │
│ ┌─────────────┐ ┌──────────────┐ │
│ │ Main │ │ Sidecar │ │
│ │ Container │ │ Container │ │
│ │ (App) │←→│ (Envoy/ │ │
│ │ │ │ Istio) │ │
│ └─────────────┘ └──────────────┘ │
│ │
│ Sidecar обеспечивает: │
│ • Service mesh │
│ • mTLS шифрование │
│ • Retry/Circuit Breaker │
│ • Observability │
└─────────────────────────────────────┘Observability (Наблюдаемость)
Три столпа наблюдаемости в микросервисной архитектуре:
┌────────────────┬────────────────┬────────────────┐
│ Логи │ Метрики │ Трейсы │
│ (Logs) │ (Metrics) │ (Traces) │
├────────────────┼────────────────┼────────────────┤
│ Что случилось │ Как работает │ Где проблема │
│ │ │ │
│ ELK Stack │ Prometheus │ Jaeger │
│ (Elastic, │ + Grafana │ Zipkin │
│ Logstash, │ │ OpenTelemetry │
│ Kibana) │ DataDog │ │
│ │ │ │
│ Structured │ RED: │ Distributed │
│ logging │ Rate, Errors, │ tracing │
│ (JSON) │ Duration │ (TraceID) │
└────────────────┴────────────────┴────────────────┘Distributed Tracing
Request: GET /api/order/123
TraceID: abc-123
Service A (API Gateway) ──────────────────────── 120ms
│
├─ Service B (Orders) ────────────────── 80ms
│ │
│ ├─ Service C (Users) ──────── 20ms
│ │
│ └─ Service D (Products) ───── 30ms
│
└─ Service E (Cache) ──── 5ms
→ Видим полный путь запроса через все сервисы
→ Определяем узкие местаВопросы на собеседовании
1. Как бы вы разделили монолит на микросервисы?
Шаг 1: Определить bounded contexts (DDD)
Шаг 2: Выделить наименее связанный модуль
Шаг 3: Strangler Fig Pattern:
┌──────────────────────────────────┐
│ API Gateway / Proxy │
│ /users → Новый User Service │
│ /orders → Старый монолит │ ← Постепенная миграция
│ /products → Старый монолит │
└──────────────────────────────────┘
Шаг 4: Разделить БД
Шаг 5: Повторить для следующего модуля2. Как обеспечить согласованность данных между сервисами?
Варианты:
1. Saga Pattern — цепочка локальных транзакций + компенсации
2. Event Sourcing — источник истины в событиях
3. Outbox Pattern — записать событие в ту же транзакцию
4. Two-Phase Commit (2PC) — строгая согласованность
(обычно избегают из-за производительности)3. Как организовать CI/CD для микросервисов?
Mono-repo:
+ Единый CI/CD pipeline
+ Простой рефакторинг
- Сложная система сборки
Poly-repo (отдельный репозиторий на сервис):
+ Независимые pipelines
+ Чёткие границы ответственности
- Сложнее шарить код
- Версионирование зависимостейРезюме
┌─────────────────────────────────────────────────────────┐
│ 1. Начинайте с монолита, переходите на микросервисы │
│ при необходимости │
│ 2. Определите чёткие границы сервисов (DDD) │
│ 3. Используйте async коммуникацию где возможно │
│ 4. Реализуйте Circuit Breaker и Retry │
│ 5. Saga Pattern для распределённых транзакций │
│ 6. API Gateway как единая точка входа │
│ 7. Observability: логи + метрики + трейсы │
│ 8. Автоматизируйте деплой (CI/CD per service) │
└─────────────────────────────────────────────────────────┘