← Назад к вопросам

Какие существуют способы декомпозиции системы на микросервисы?

1.0 Junior🔥 91 комментариев
#Требования и их анализ

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Декомпозиция системы на микросервисы

Микросервисная архитектура — это подход, когда большая система разбивается на множество независимых, слабо связанных сервисов, каждый из которых отвечает за определённую бизнес-функцию. Правильная декомпозиция критична для успеха микросервисной архитектуры.

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

Микросервис — это самостоятельное приложение, которое:

  • Отвечает за одну бизнес-функцию (Single Responsibility)
  • Может развертываться независимо
  • Взаимодействует с другими сервисами через API (REST, gRPC, Message Queue)
  • Имеет собственную БД (Database per Service)
  • Может быть написан на разном языке

Пример: E-commerce система разбивается на:

  • User Service (управление пользователями)
  • Product Service (каталог товаров)
  • Order Service (управление заказами)
  • Payment Service (обработка платежей)
  • Notification Service (отправка уведомлений)

Способы декомпозиции

1. По бизнес-домену (Business Capability / Domain-Driven Design)

Суть: Разделить систему на основе бизнес-функций, а не технологических слоёв.

Как это работает:

  • Каждый микросервис соответствует отдельному бизнес-домену
  • Домены определяют границы ответственности
  • Основан на Domain-Driven Design (DDD) концепции

Пример: Платформа доставки еды (Like Uber Eats)

┌─────────────────────────────────────────────────────┐
│           Платформа доставки еды                    │
├─────────────────────────────────────────────────────┤
│                                                     │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────┐  │
│  │ User Service │  │ Restaurant   │  │ Menu     │  │
│  │              │  │ Service      │  │ Service  │  │
│  └──────────────┘  └──────────────┘  └──────────┘  │
│                                                     │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────┐  │
│  │ Order Service│  │ Payment      │  │ Delivery │  │
│  │              │  │ Service      │  │ Service  │  │
│  └──────────────┘  └──────────────┘  └──────────┘  │
│                                                     │
│  ┌──────────────┐  ┌──────────────┐                │
│  │ Review       │  │ Notification │                │
│  │ Service      │  │ Service      │                │
│  └──────────────┘  └──────────────┘                │
│                                                     │
└─────────────────────────────────────────────────────┘

Преимущества:

  • Очень понятные границы
  • Каждая команда владеет своим сервисом
  • Новый разработчик легко поймёт архитектуру
  • Легко масштабировать отдельные части

Недостатки:

  • Высокая связанность между сервисами
  • Много коммуникации между командами

2. По User Experience / Feature (Vertical Slicing)

Суть: Разделить на основе пользовательских функций, а не слоёв архитектуры.

Как это работает:

  • Каждый микросервис содержит все слои для одной фичи (UI, API, БД)
  • "Вертикальный срез" через всю архитектуру
  • Команда владеет полной фичей от UI до БД

Пример: E-commerce

Монолит (Плохо):
┌────────────────────────────────┐
│ Presentation Layer             │  → Controllers, Views
├────────────────────────────────┤
│ Business Logic Layer           │  → Services, Use Cases
├────────────────────────────────┤
│ Data Access Layer              │  → Repositories, Models
└────────────────────────────────┘

Микросервисы (Хорошо):
┌────────────────────┐  ┌────────────────────┐
│ Cart Service       │  │ Wishlist Service   │
├────────────────────┤  ├────────────────────┤
│ UI (React)         │  │ UI (React)         │
│ API                │  │ API                │
│ DB                 │  │ DB                 │
└────────────────────┘  └────────────────────┘

Преимущества:

  • Команда может работать независимо (полная фича)
  • Быстрая разработка и развертывание
  • Высокая автономия

Недостатки:

  • Дублирование кода (UI, API слои)
  • Сложнее поддерживать единообразие

3. По техническому слою (Layered / Horizontal Slicing)

Суть: Разделить на основе технических слоёв (хотя это антипаттерн для микросервисов).

Как это работает:

  • Gateway Service (маршрутизация)
  • API Services (бизнес-логика)
  • Data Services (доступ к данным)

Пример (Плохо):

┌─────────────────────┐
│ API Gateway         │  ← Маршрутизирует запросы
└─────────────────────┘
         │
    ┌────┴────┐
    │         │
┌───────────────┐  ┌───────────────┐
│ Business      │  │ Data Access   │  ← Разделение по техслоям
│ Logic Service │  │ Service       │
└───────────────┘  └───────────────┘

Почему это плохо:

  • Высокая связанность через слои
  • Сложно развертывать независимо
  • Трудно масштабировать отдельные части
  • Не recomm. для микросервисов

4. По масштабируемости (Scalability Cube)

Суть: Разделить на основе того, какие части требуют разные уровни масштабирования.

Три измерения:

X-axis (Horizontal Duplication):

  • Копируем всю систему (одинаковые инстансы)
  • Load Balancer распределяет трафик
┌──────────────────────────────────┐
│        Load Balancer             │
└──────────┬───────────────────────┘
       │   │   │
   ┌───┴┐ │  ┌─┴───┐
   │App1│ │  │App2│  (идентичные копии)
   └────┘ │  └────┘
      ┌───┴─────┐
      │   App3  │
      └────┬────┘
           │
        ┌──┴────┐
      ┌─┴──┐  ┌─┴──┐
      │DB1 │  │DB2 │  (Database Replication)
      └────┘  └────┘

Z-axis (Data Partition / Sharding):

  • Разделяем данные по какому-то критерию (user_id, region)
  • Каждый сервис работает с подмножеством данных
┌──────────────────────────────────┐
│        Router (по user_id)        │
└──────────┬───────────────────────┘
       │   │   │
  ┌────┴┐ │  ┌─┴─────┐
  │Users│ │  │Users  │  (разные данные
  │1-100│ │  │101-200│   по критерию)
  └─────┘ │  └───────┘
   Shard1 │   Shard2

Y-axis (Functional Decomposition / Service Extraction):

  • Разделяем по функциям (в этом и есть микросервисы)
┌──────────────────────────────────┐
│      API Gateway                 │
└──────────┬───────────────────────┘
       │   │   │
   ┌───┴┐ │  ┌─┴─────┐
   │User│ │  │Product│  (разные
   │Svc │ │  │Service│   функции)
   └────┘ │  └───────┘

Пример: YouTube

X-axis: Множество инстансов каждого сервиса (Auto-scaling)
Y-axis: Разные сервисы (Search, Upload, Streaming)
Z-axis: Sharding по user_id или region

5. По отделам / командам (Conway's Law)

Суть: Разделить микросервисы в соответствии со структурой организации.

Принцип: Архитектура системы отражает организационную структуру компании.

Пример:

Организация:                    Архитектура:
┌──────────────────┐           ┌──────────────────────┐
│ Company          │           │   API Gateway        │
├──────────────────┤           └────────┬─────────────┘
│                  │                    │
├─ Mobile Team    │           ┌─────────┴─────────┐
│  (iOS, Android) │           │                   │
├─ Backend Team   │      ┌─────────────┐   ┌──────────┐
│  (REST APIs)    │      │ Mobile Srv  │   │ Backend  │
├─ Analytics Team │      │ (Push,Auth) │   │ Service  │
│  (Reports)      │      └─────────────┘   └──────────┘
└──────────────────┘

Преимущества:

  • Естественное отражение организации
  • Минимизирует коммуникацию между командами
  • Ясная ответственность

6. По Data Affinity (Affinity-based)

Суть: Разделить на основе того, какие данные часто используются вместе.

Как это работает:

  • Анализируем, какие данные запрашиваются вместе
  • Группируем их в один микросервис
  • Минимизируем inter-service вызовы

Пример: Social Media

Часто используются вместе:
- User Profile + User Settings → User Service
- Post + Comments + Likes → Post Service
- Followers + Following → Connection Service

Не стоит разделять, т.к. очень тесно связаны

7. По Strangler Fig Pattern (Incremental Migration)

Суть: Постепенно извлекать микросервисы из монолита.

Как это работает:

  1. Есть старый монолит
  2. Создаём первый микросервис
  3. API Gateway маршрутирует запросы
  4. Постепенно извлекаем всё больше функций
Шаг 1 (Старая система):
┌──────────────────┐
│ Legacy Monolith  │ (всё внутри)
└──────────────────┘

Шаг 2 (Начало миграции):
┌─────────────────────────────────┐
│        API Gateway              │
└──┬───────────────────────────┬──┘
   │                           │
┌──┴──────────┐         ┌──────┴─────┐
│ New Service │         │Legacy       │
│ (Auth)      │         │Monolith     │
└─────────────┘         └─────────────┘

Шаг N (Полная миграция):
┌──────────────────────────────────┐
│        API Gateway               │
└──┬──────────┬───────┬────────┬───┘
   │          │       │        │
┌──┴──┐  ┌────┴──┐  ┌─┴──┐  ┌─┴──┐
│Auth │  │Product│  │Order  │Pay  │
└─────┘  └───────┘  └──────┘└────┘

Как выбрать способ декомпозиции

Шаг 1: Анализ бизнес-доменов (DDD)

1. Список всех бизнес-функций:
   - User Management
   - Catalog Management
   - Order Processing
   - Payment Processing
   - Delivery Tracking

2. Определить Bounded Contexts (границы контекстов):
   - User Service (контекст: user accounts)
   - Product Service (контекст: inventory)
   - Order Service (контекст: orders)
   - Payment Service (контекст: payments)
   - Shipping Service (контекст: delivery)

3. Выявить зависимости:
   Order Service → Product Service (проверить наличие товара)
   Order Service → Payment Service (обработать платёж)
   Order Service → Shipping Service (создать доставку)

Шаг 2: Матрица связанности

        User  Product  Order  Payment  Shipping
User      -     Low    Medium  Low      Low
Product   Low    -     High    Low      Low
Order     Medium High   -      High    High
Payment   Low    Low    High    -      Low
Shipping  Low    Low    High    Low      -

Вывод:
- Order часто общается с Product, Payment, Shipping
- Можно объединить Order + Shipping в одной команде
- Product и User лучше отделить

Шаг 3: Анализ масштабируемости

Высокая нагрузка:     Product Service (много читает)
                      Order Service (много пишет)

Низкая нагрузка:      User Service (мало обращений)
                      Settings Service (редко меняется)

→ Product и Order должны быть готовы к масштабированию

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

Слишком мало микросервисов:

  • У вас всё ещё монолит
  • Результат: все проблемы монолита + сложность микросервисов

Слишком много микросервисов:

  • 50+ сервисов для стартапа
  • Результат: операционный кошмар, много зависимостей

Микросервисы по техническим слоям:

  • API Service, Data Service, Cache Service
  • Результат: высокая связанность, сложно разворачивать

Одна БД для всех сервисов:

  • Все сервисы пишут в одну таблицу
  • Результат: база становится узким местом

Декомпозиция без анализа бизнеса:

  • Просто технически разделили
  • Результат: нелогичные границы, много inter-service вызовов

Best Practices

1. Domain-Driven Design сначала

  • Определи бизнес-домены перед архитектурой
  • Используй Event Storming для визуализации

2. Начни с малого

  • 3-5 микросервисов в начале
  • Расширяй по мере роста

3. Single Responsibility

  • Каждый сервис отвечает за одно
  • Если описание услуги содержит "и" — расщепи

4. Database per Service

  • Каждый сервис имеет свою БД
  • Минимизирует связанность

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

  • Когда возможно, используй Message Queue
  • Снижает связанность

6. API Contracts первыми

  • Определи API между сервисами
  • Разработка может идти параллельно

Заключение

Выбор способа декомпозиции критичен для успеха микросервисной архитектуры. Domain-Driven Design + Business Capability — это рекомендуемый подход для большинства систем. Он даёт чёткие границы, минимизирует связанность и позволяет командам работать независимо.