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

Что быстрее работает с запросами клиента: монолит или микросервисная архитектура

1.7 Middle🔥 121 комментариев
#REST API и микросервисы#SOLID и паттерны проектирования

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

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

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

Производительность: монолит vs микросервисы при работе с запросами

Это распространённое заблуждение, что микросервисы быстрее. На самом деле, выбор между ними зависит от сценария и масштаба. Разберу объективно.

Монолит: примеры работы

Простой запрос в монолите:

Клиент → HTTP Request → Веб-сервер → Java AppServer
  ↓
Service Layer (In-memory, same JVM)
  ↓
Repository Layer (Database query)
  ↓
Network: 0 (local call)
Response: 50-100ms (БД запрос)

Время ответа: 50-100ms (если БД быстра)

Сложный запрос (нужны данные из разных частей):

// Монолит: всё в одном процессе
@Service
public class OrderService {
    @Autowired UserService userService;
    @Autowired InventoryService inventoryService;
    @Autowired PaymentService paymentService;
    
    public OrderDTO createOrder(OrderRequest request) {
        // Все сервисы в памяти — никаких сетевых вызовов
        User user = userService.getUser(request.getUserId());
        List<Item> items = inventoryService.getItems(request.getItemIds());
        Payment payment = paymentService.validate(request.getCardToken());
        
        // Типичное время: 50-150ms (в памяти + несколько БД запросов)
        return new OrderDTO(user, items, payment);
    }
}

Время ответа: 50-150ms

Микросервисы: примеры работы

Простой запрос в микросервисе:

Клиент → HTTP Request (localhost:8080)
  ↓
User Service → Get User (50ms) → Response

Время ответа: 50ms (если быстрое БД соединение)

Сложный запрос (нужны данные из разных сервисов):

Клиент → API Gateway (localhost:3000)
  ↓
Orchestration Service (25ms):
  ├→ User Service (50ms) ──────┐
  ├→ Inventory Service (60ms) ──┤
  └→ Payment Service (40ms) ────┼→ Collect results (10ms)
  ↓
Network latency: 3 x 10ms = 30ms (local) / 100ms (remote)
Total: 150-200ms

Время ответа: 150-200ms (с network overhead)

Прямое сравнение

Сценарий 1: Получить данные пользователя (простой запрос)

Монолит: SELECT user FROM users WHERE id = 1
  DB Query: 20ms
  Total: 20-30ms

Микросервисы: HTTP -> User Service -> SELECT
  Network: 5ms (round trip)
  DB Query: 20ms
  Service overhead: 5ms
  Total: 30-40ms (примерно одинаково)

Сценарий 2: Создать заказ (нужны данные из 3 сервисов)

Монолит:
  userService.getUser(id) → 20ms (DB)
  inventoryService.getItems(ids) → 30ms (DB)
  paymentService.validate(token) → 40ms (API call)
  Total: 20 + 30 + 40 = 90ms (ПОСЛЕДОВАТЕЛЬНО в памяти)

Микросервисы (параллельно):
  User Service: 20ms (DB) + 5ms (network) = 25ms
  Inventory Service: 30ms (DB) + 5ms (network) = 35ms
  Payment Service: 40ms (API) + 5ms (network) = 45ms
  Orchestration: max(25, 35, 45) = 45ms
  Combine results: 10ms
  Total: 45 + 10 = 55ms (ПАРАЛЛЕЛЬНО)

Итог: Микросервисы БЫСТРЕЕ за счёт параллелизма!

Когда монолит быстрее

1. Много небольших синхронных операций

// Монолит: в памяти
for (int i = 0; i < 100; i++) {
    result += calculateSomething(data[i]);  // 1ms × 100 = 100ms
}

// Микросервисы: 100 сетевых вызовов
for (int i = 0; i < 100; i++) {
    result += httpClient.post("/calculate", data[i]);  
    // (1ms + 5ms network) × 100 = 600ms
}

Монолит ВЫИГРЫВАЕТ: 100ms vs 600ms

2. Сложные транзакции

Монолит: ACID транзакция, lock in memory
  Transfer money: A.balance -= 100, B.balance += 100
  Time: 10ms (одна DB транзакция)

Микросервисы: Distributed transaction, Saga pattern
  1. Debit from A: 20ms
  2. Wait for confirmation: 10ms
  3. Credit to B: 20ms
  4. Compensation if failed: 50ms
  Time: 50ms (best case) to 100ms (with retry)

Монолит БЫСТРЕЕ: 10ms vs 50-100ms

3. При низкой нагрузке

10 запросов в секунду

Монолит:
  - Один сервис
  - Минимальная infrastructure
  - Latency: 50ms

Микросервисы:
  - 5+ сервисов
  - API Gateway
  - Service Discovery
  - Network overhead
  - Latency: 100-150ms

Монолит БЫСТРЕЕ: 50ms vs 100ms (плюс complexity)

Когда микросервисы быстрее

1. Параллельные операции (как выше)

Микросервисы могут выполняться параллельно → общее время меньше

2. Независимое масштабирование

Есть бутылочное горлышко:
  Платежный сервис: 100ms (медленный API)
  Другие сервисы: 20ms

Монолит: масштабируем ВСЕ (даже быстрые части)
Микросервисы: масштабируем ТОЛЬКО платежный

Результат: микросервисы эффективнее

3. Использование кеша и CDN

Микросервис User Service + Redis cache
  Первый запрос: 50ms (DB)
  Следующие: 5ms (Redis)

Монолит:
  Каждый запрос может требовать DB (если нет кеша)
  Кеш может быть разделён между потоками (lock contention)

Микросервисы выигрывают благодаря отдельному кешу

Реальные цифры из production

Компания А: Монолит (Java + PostgreSQL)

Операция          Время
─────────────────────────
Получить user     20ms
Создать заказ     100ms
Опубликовать      150ms
Получить список   200ms (500 записей)

Компания Б: Микросервисы (Spring Boot + gRPC)

Операция          Время
─────────────────────────
Получить user     25ms (немного медленнее из-за сети)
Создать заказ     60ms (параллельные вызовы)
Опубликовать      80ms (асинхронно через очередь)
Получить список   150ms (кеш + parallel fetch)

Микросервисы выигрывают при операциях с parallelization.

Оптимизация в монолите

// 1. Кеширование
@Cacheable("users")
public User getUser(Long id) {
    return repository.findById(id).orElseThrow();
}

// 2. Async обработка
@Async
public CompletableFuture<User> getUserAsync(Long id) {
    return CompletableFuture.completedFuture(
        repository.findById(id).orElseThrow()
    );
}

// 3. Batch обработка вместо N+1
List<Users> users = userRepository.findAllByIds(ids);
// Вместо: for (id : ids) findById(id);

// 4. Connection pooling и query optimization
// Уже встроено в Spring Data

// Результат: монолит может быть ТАК ЖЕ быстрым как микросервисы

Оптимизация в микросервисах

1. API Gateway + Request batching
   вместо 10 отдельных вызовов → 1 batch запрос

2. gRPC вместо REST
   REST: 50ms
   gRPC: 15ms (binary protocol, no JSON parsing)

3. Service mesh (Istio)
   - Connection pooling
   - Retry logic
   - Circuit breaker

4. Async messaging
   Event-driven вместо sync calls

Таблица сравнения

┌──────────────────────┬──────────────┬──────────────────┐
│ Критерий             │ Монолит      │ Микросервисы     │
├──────────────────────┼──────────────┼──────────────────┤
│ Простой запрос       │ 30ms ✅      │ 40ms            │
│ Сложный (параллель)  │ 150ms       │ 70ms ✅          │
│ Множество малых реквестов │ 50ms ✅ │ 300ms          │
│ Масштабируемость     │ Сложнее      │ Простая ✅       │
│ Сложность ops        │ Простая ✅   │ Сложная         │
│ Разработка           │ Быстро ✅    │ Медленно         │
│ Транзакции           │ Простые ✅   │ Сложные          │
└──────────────────────┴──────────────┴──────────────────┘

Мой совет

Выбирай монолит если:

  • < 100 RPS (requests per second)
  • Много синхронных зависимостей
  • Маленькая команда
  • Простая бизнес-логика
  • Результат: 20-30% быстрее при разработке + deployment

Выбирай микросервисы если:

  • 1000 RPS

  • Разные части масштабируются по-разному
  • Большая команда (разные teams)
  • Независимые сервисы
  • Результат: 20-30% быстрее при высокой нагрузке

Итог

При работе с запросами клиента:

  • Монолит часто быстрее при простых синхронных операциях
  • Микросервисы быстрее при параллельных независимых операциях
  • Разница может быть 50-100ms в зависимости от архитектуры
  • Оптимизация code часто важнее выбора архитектуры

Золотое правило: выбирай архитектуру по потребностям масштабируемости и организации команды, а не по производительности запросов.