Сравнение архитектур
Общая таблица trade-offs
Каждый архитектурный стиль -- это набор компромиссов. Не существует "лучшей" архитектуры -- есть подходящая для конкретного контекста.
Характеристики архитектур (по шкале 1-5)
Layer Hexag Clean Micro Event Space Micro
ed onal kernel Driven Based services
────── ────── ────── ────── ────── ────── ──────
Сложность ★☆☆☆☆ ★★★☆☆ ★★★★☆ ★★★☆☆ ★★★★☆ ★★★★★ ★★★★★
Тестируемость ★★☆☆☆ ★★★★★ ★★★★★ ★★★★☆ ★★★☆☆ ★★★☆☆ ★★★★☆
Деплой ★☆☆☆☆ ★★☆☆☆ ★★☆☆☆ ★★★☆☆ ★★★★☆ ★★★★☆ ★★★★★
Масштабируемость ★☆☆☆☆ ★★☆☆☆ ★★☆☆☆ ★★☆☆☆ ★★★★★ ★★★★★ ★★★★★
Производительность ★★★☆☆ ★★★☆☆ ★★★☆☆ ★★★☆☆ ★★★★★ ★★★★★ ★★★★☆
Эволюционность ★☆☆☆☆ ★★★★☆ ★★★★☆ ★★★★★ ★★★★★ ★★★☆☆ ★★★★★
Fault tolerance ★☆☆☆☆ ★☆☆☆☆ ★☆☆☆☆ ★☆☆☆☆ ★★★★★ ★★★★★ ★★★★☆
Стоимость разр. ★☆☆☆☆ ★★★☆☆ ★★★★☆ ★★★☆☆ ★★★★☆ ★★★★★ ★★★★★
Детальное сравнение
Монолитные архитектуры
| Критерий | Layered | Hexagonal | Clean | Onion |
|---|---|---|---|---|
| Сложность | Низкая | Средняя | Высокая | Средняя |
| Тестируемость | Средняя | Отличная | Отличная | Отличная |
| Деплой | Монолит | Монолит | Монолит | Монолит |
| Зависимости | Сверху вниз | Внутрь (порты) | Внутрь (правило) | Внутрь (слои) |
| Domain isolation | Слабая | Сильная | Сильная | Сильная |
| Framework lock-in | Высокий | Низкий | Низкий | Низкий |
| Кривая обучения | Пологая | Средняя | Крутая | Средняя |
| Boilerplate код | Мало | Средне | Много | Средне |
Распределённые архитектуры
| Критерий | Microservices | Event-Driven | Space-Based |
|---|---|---|---|
| Сложность | Очень высокая | Высокая | Очень высокая |
| Тестируемость | Высокая (unit), Сложная (e2e) | Средняя | Средняя |
| Деплой | Независимый per service | Независимый | Независимый per unit |
| Масштабирование | Per-service | Per-consumer | Per-unit |
| Data consistency | Eventual | Eventual | Eventual |
| Latency | Network overhead | Async (low coupling) | In-memory (very low) |
| Operational cost | Высокая | Средняя | Очень высокая |
| Team requirements | DevOps culture | Event thinking | Специалисты по data grids |
Матрица выбора по контексту
По размеру команды
Команда
┌────────────────────────────────────────────────┐
│ │
│ 1-3 чел ──▶ Layered или Modular Monolith │
│ │
│ 3-8 чел ──▶ Hexagonal / Clean │
│ │
│ 8-20 чел ──▶ Modular Monolith или │
│ начало микросервисов │
│ │
│ 20+ чел ──▶ Microservices + EDA │
│ (по Conway's Law) │
│ │
└────────────────────────────────────────────────┘
По типу приложения
| Тип приложения | Рекомендация | Почему |
|---|---|---|
| CRUD-админка | Layered | Простота, быстрый старт |
| E-commerce (стартап) | Modular Monolith | Баланс сложности и гибкости |
| E-commerce (scale) | Microservices + EDA | Независимое масштабирование |
| Финтех/банкинг | Hexagonal + DDD + ES | Аудит, сложный домен |
| Real-time система | Event-Driven | Асинхронность, low latency |
| IDE/редактор | Microkernel | Расширяемость плагинами |
| Игровой сервер | Space-Based | Пиковые нагрузки |
| SaaS платформа | Clean + Microservices | Долгий lifecycle, заменяемость |
По характеристикам нагрузки
Нагрузка предсказуемая?
├── ДА
│ Много чтений vs записей?
│ ├── Read-heavy (95/5) → CQRS
│ ├── Write-heavy → Event Sourcing
│ └── Balanced → Layered / Hexagonal
│
└── НЕТ (пиковая)
Насколько непредсказуемая?
├── Умеренно → Microservices + auto-scaling
└── Экстремально → Space-Based
Реальные примеры компаний
Netflix
ЭВОЛЮЦИЯ NETFLIX
2007: Монолит (Java)
│
2008: Проблемы масштабирования
│ Downtime из-за DB corruption
│
2009-2012: Миграция на Microservices
│ Zuul (API Gateway)
│ Eureka (Service Discovery)
│ Hystrix (Circuit Breaker)
│
2012-2016: 500+ микросервисов
│ Event-Driven (Apache Kafka)
│ CQRS для каталога
│
Сегодня: 1000+ микросервисов
Chaos Engineering (Chaos Monkey)
Hexagonal внутри каждого сервиса
Уроки Netflix:
- Монолит → микросервисы заняли 7 лет
- Не "big bang" миграция, а постепенное выделение
- Инвестировали в инфраструктуру (Zuul, Eureka, Hystrix)
- Каждый микросервис -- Hexagonal Architecture внутри
Uber
ЭВОЛЮЦИЯ UBER
2010: Монолит (Python)
│
2013: Первые микросервисы
│ Отдельные сервисы для Dispatch, Payment
│
2015: SOA → Microservices
│ Domain-Oriented Microservice Architecture (DOMA)
│ Event-Driven для trip updates
│
2018: 2000+ микросервисов
│ Проблемы: "микросервисный спагетти"
│
2020: DOMA (Domain-Oriented Architecture)
Группировка микросервисов по доменам
Gateway per domain
Event-Driven между доменами
Уроки Uber:
- Слишком мелкие микросервисы создают хаос
- DOMA: группировка сервисов в домены (как Bounded Contexts)
- Event-Driven между доменами, синхронные вызовы внутри
- Вернулись к более крупным юнитам деплоя
Spotify
АРХИТЕКТУРА SPOTIFY
Организация по Squads (команды 6-12 чел)
│
├── Backend: Microservices (Java, Python)
│ Each Squad owns 1-3 services
│ Hexagonal Architecture внутри
│
├── Data: Event-Driven (Google Pub/Sub)
│ Real-time рекомендации
│ A/B тестирование
│
├── Client: Event Sourcing для плейлистов
│ Offline-first approach
│ Sync через события
│
└── Infrastructure: Kubernetes + GCP
Backstage (Developer Portal)
Уроки Spotify:
- Conway's Law работает: архитектура = организация
- Каждая Squad владеет своими сервисами
- Event-Driven для межкомандного взаимодействия
- Backstage -- внутренний developer portal (open-sourced)
Shopify
АРХИТЕКТУРА SHOPIFY
Модульный монолит на Ruby on Rails
│
├── 2.9M+ магазинов
├── $175B+ GMV
│
├── Архитектура:
│ ├── Модульный монолит (НЕ микросервисы!)
│ ├── Strict module boundaries
│ ├── Domain-driven modules
│ └── Шардирование по магазинам (tenant-based)
│
└── Почему не микросервисы?
├── Простота деплоя
├── Нет distributed debugging
├── Рефакторинг проще
└── Один CI/CD pipeline
Уроки Shopify:
- Микросервисы -- не единственный путь к масштабированию
- Модульный монолит + шардирование = масштабируемость
- Строгие границы модулей важнее, чем разделение на сервисы
- Доказали: можно обрабатывать $175B при монолите
Антипаттерны выбора архитектуры
1. Resume-Driven Development
❌ "Нужны микросервисы, CQRS и Event Sourcing для блога"
✅ "Для блога хватит Layered Architecture с простой БД"
2. Cargo Cult Architecture
❌ "Netflix использует микросервисы, мы тоже должны"
✅ "У Netflix 200 миллионов пользователей и 2000 инженеров.
У нас 1000 пользователей и 3 инженера"
3. Big Bang Rewrite
❌ "Перепишем монолит на микросервисы за 6 месяцев"
✅ "Постепенно выделяем сервисы: Strangler Fig Pattern"
4. Distributed Monolith
❌ Микросервисы, которые деплоятся только вместе
и общаются синхронно = худшее из обоих миров
✅ Либо настоящие микросервисы (независимые),
либо честный модульный монолит
Strangler Fig Pattern -- постепенная миграция
Этап 1: Монолит + первый сервис
┌─────────┐ ┌────────────────────┐
│ API │────▶│ МОНОЛИТ │
│ Gateway │ │ ┌──────────────┐ │
│ │ │ │ Payments │──┼──▶ ┌──────────┐
│ │ │ │ (выделен) │ │ │ Payment │
│ │ │ └──────────────┘ │ │ Service │
│ │ │ │ └──────────┘
└─────────┘ └────────────────────┘
Этап 2: Больше сервисов выделено
┌─────────┐ ┌────────────────────┐
│ API │────▶│ МОНОЛИТ │ ┌──────────┐
│ Gateway │ │ (уменьшается) │───▶│ Payment │
│ │ │ │ │ Service │
│ │─────┤ │ └──────────┘
│ │ └────────────────────┘ ┌──────────┐
│ │──────────────────────────────▶│ Order │
│ │ │ Service │
└─────────┘ └──────────┘
Этап N: Монолит исчез
┌─────────┐ ┌──────────┐ ┌──────────┐
│ API │────▶│ Payment │ │ Catalog │
│ Gateway │────▶│ Service │ │ Service │
│ │────▶└──────────┘ └──────────┘
│ │ ┌──────────┐ ┌──────────┐
│ │────▶│ Order │ │ User │
└─────────┘ │ Service │ │ Service │
└──────────┘ └──────────┘
Итоговая рекомендация
┌─────────────────────────────────────────────────────┐
│ ПРАВИЛО ТРЁХ │
│ │
│ 1. Начните с простого (Layered / Modular Monolith) │
│ │
│ 2. Усложняйте когда больно │
│ (не заранее, а когда проблема реальна) │
│ │
│ 3. Выбирайте архитектуру под контекст: │
│ - Размер команды │
│ - Сложность домена │
│ - Требования к масштабированию │
│ - Бюджет и сроки │
└─────────────────────────────────────────────────────┘
| Если у вас... | Начните с... | Усложните до... |
|---|---|---|
| MVP / стартап | Layered | Modular Monolith |
| Растущий продукт | Modular Monolith | Hexagonal + DDD |
| Крупный проект | Hexagonal + DDD | Microservices + EDA |
| Экстремальная нагрузка | Microservices + EDA | Space-Based |