В чем разница между монолитной, сервис-ориентированной (SOA) и микросервисной архитектурой?

«В чем разница между монолитной, сервис-ориентированной (SOA) и микросервисной архитектурой?» — вопрос из категории Архитектура, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Эти архитектурные стили представляют собой эволюцию от тесно связанных систем к слабо связанным, распределенным.

Аспект Монолитная архитектура Сервис-ориентированная архитектура (SOA) Микросервисная архитектура (MSA)
Структура Единое, неделимое приложение. Все компоненты (UI, бизнес-логика, доступ к данным) развертываются вместе. Набор крупных, многофункциональных сервисов (например, "Сервис заказов", "Сервис клиентов"). Набор мелких, автономных сервисов, каждый отвечает за одну бизнес-возможность (например, "Сервис аутентификации", "Сервис уведомлений").
Связность Высокая. Компоненты вызывают друг друга напрямую через методы/функции. Средняя/низкая. Сервисы общаются по сети, часто через ESB (Enterprise Service Bus). Очень низкая. Сервисы общаются по сети через легковесные протоколы (HTTP/REST, gRPC, Messaging).
Масштабирование Горизонтальное масштабирование всей копии приложения, даже если нагрузка только на один модуль. Масштабирование отдельных сервисов, но они сами могут быть крупными. Точное, независимое масштабирование каждого микросервиса в зависимости от нагрузки.
Гранулярность Очень крупная. Крупная (бизнес-сервисы). Мелкая (единая ответственность).
Сложность Низкая на старте, но растет экспоненциально с увеличением кодовой базы («монстролит»). Высокая из-за сложности ESB и управления сервисами. Высокая операционная сложность (оркестрация, мониторинг, отказоустойчивость).

Пример на уровне кода:

// 1. Монолит: Всё в одном проекте
public class OrderService // В проекте MyBigApp.Web
{
    private readonly IEmailSender _emailSender;
    private readonly IInventoryRepository _inventoryRepo;

    public void ProcessOrder(Order order)
    {
        // Прямые вызовы внутри одного процесса
        _inventoryRepo.ReserveItems(order);
        SaveToDatabase(order);
        _emailSender.SendConfirmation(order.UserEmail); // Может упасть и откатить всю транзакцию
    }
}

// 2. Микросервис: Сервис заказов (отдельный проект/контейнер)
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase // Проект: OrderService
{
    [HttpPost]
    public async Task<IActionResult> CreateOrder([FromBody] Order order)
    {
        // Асинхронное взаимодействие с другими сервисами по сети
        await _httpClient.PostAsJsonAsync("http://inventory-service/api/reserve", order);
        await _dbContext.Orders.AddAsync(order);
        // Отправка события в очередь, а не прямой вызов
        await _messageBus.PublishAsync(new OrderCreatedEvent { OrderId = order.Id });
        return Accepted();
    }
}
// Сервис уведомлений (другой проект) подписывается на OrderCreatedEvent и отправляет email.

Ключевой вывод: Выбор архитектуры — это компромисс. Монолит прост для начала, SOA подходит для интеграции крупных корпоративных систем, а микросервисы — для сложных, быстро развивающихся продуктов, где критичны независимость команд и масштабируемость.