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

Что такое API Composition?

1.2 Junior🔥 181 комментариев
#Soft Skills и карьера

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

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

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

Что такое API Composition

Определение

API Composition (Композиция API) — это архитектурный паттерн микросервисной архитектуры, который позволяет клиентам или промежуточному сервису получать данные из нескольких сервисов, объединяя их результаты в один ответ.

Это решение проблемы, когда данные, необходимые клиенту, распределены между несколькими микросервисами.

Проблема в микросервисной архитектуре

В традиционной монолитной архитектуре вся информация находится в одной базе данных:

// Монолит — всё в одном месте
public User getUserWithOrders(Long userId) {
    User user = userRepository.findById(userId);
    user.setOrders(orderRepository.findByUserId(userId));
    return user;
}

В микросервисной архитектуре каждый сервис имеет свою БД:

  • User Service — знает про пользователей
  • Order Service — знает про заказы
  • Payment Service — знает про платежи

Решение: API Composition

API Composition объединяет данные несколько сервисов на клиентской стороне или в специальном Composer Service (также называется Aggregator Service):

// Composer Service (Aggregator)
@RestController
@RequestMapping("/api/users")
public class UserComposerController {
    
    private final UserServiceClient userClient;
    private final OrderServiceClient orderClient;
    private final PaymentServiceClient paymentClient;
    
    public UserComposerController(
        UserServiceClient userClient,
        OrderServiceClient orderClient,
        PaymentServiceClient paymentClient
    ) {
        this.userClient = userClient;
        this.orderClient = orderClient;
        this.paymentClient = paymentClient;
    }
    
    @GetMapping("/{userId}")
    public ResponseEntity<UserCompositeDTO> getUserWithAllData(@PathVariable Long userId) {
        // Шаг 1: получить данные пользователя
        UserDTO user = userClient.getUser(userId);
        
        // Шаг 2: получить заказы этого пользователя
        List<OrderDTO> orders = orderClient.getUserOrders(userId);
        
        // Шаг 3: получить платежи для каждого заказа
        List<PaymentDTO> payments = new ArrayList<>();
        for (OrderDTO order : orders) {
            payments.addAll(paymentClient.getOrderPayments(order.getId()));
        }
        
        // Шаг 4: композиция — объединить все данные
        UserCompositeDTO composite = new UserCompositeDTO();
        composite.setUser(user);
        composite.setOrders(orders);
        composite.setPayments(payments);
        
        return ResponseEntity.ok(composite);
    }
}

Архитектура API Composition

Клиент
  |
  v
Composer/Aggregator Service
  |
  +---> User Service API
  +---> Order Service API
  +---> Payment Service API
  |
  v
Ответ клиенту (объединённые данные)

Примеры реализации

Вариант 1: Синхронная композиция (блокирующие вызовы)

public UserCompositeDTO getUserSync(Long userId) {
    // Вызовы идут последовательно (медленнее)
    UserDTO user = userClient.getUser(userId); // wait
    OrderDTO order = orderClient.getUserOrders(userId); // wait
    PaymentDTO payment = paymentClient.getPayments(userId); // wait
    
    return compose(user, order, payment);
}

Вариант 2: Асинхронная композиция (параллельные вызовы)

@Async
public CompletableFuture<UserDTO> getUserAsync(Long userId) {
    return userClient.getUserAsync(userId);
}

@Async
public CompletableFuture<List<OrderDTO>> getOrdersAsync(Long userId) {
    return orderClient.getOrdersAsync(userId);
}

public UserCompositeDTO getUserWithAsyncComposition(Long userId) {
    CompletableFuture<UserDTO> userFuture = getUserAsync(userId);
    CompletableFuture<List<OrderDTO>> ordersFuture = getOrdersAsync(userId);
    
    // Все вызовы выполняются параллельно
    CompletableFuture<UserCompositeDTO> composite = 
        userFuture.thenCombine(
            ordersFuture,
            (user, orders) -> new UserCompositeDTO(user, orders)
        );
    
    return composite.join();
}

Достоинства API Composition

  • Простота реализации — нет необходимости в Event Bus или SAGA
  • Отсутствие зависимостей между сервисами на уровне данных
  • Контролируемая композиция — явно видно, какие данные откуда берутся
  • Быстрое выполнение при асинхронной реализации

Недостатки API Composition

  • Сетевая задержка — если вызывать сервисы последовательно, это медленнее
  • Потребление памяти — всё объединяется в одном ответе
  • Риск каскадных отказов — если один сервис недоступен, весь запрос падает
  • Возможные несогласованности данных между вызовами
// Проблема: если Order Service недоступен, пользователь не получит ничего
public UserCompositeDTO getUserWithFallback(Long userId) {
    try {
        UserDTO user = userClient.getUser(userId);
        List<OrderDTO> orders = orderClient.getUserOrders(userId);
        
        UserCompositeDTO composite = new UserCompositeDTO();
        composite.setUser(user);
        composite.setOrders(orders);
        return composite;
    } catch (Exception e) {
        // Fallback: вернуть хотя бы данные пользователя
        return new UserCompositeDTO(userClient.getUser(userId), new ArrayList<>());
    }
}

Сравнение подходов

ПодходСложностьПроизводительностьНадёжность
API CompositionПростаяСредняяЗависит от сервисов
Event SourcingСложнаяВысокаяВместимо-зависимая
SAGA PatternОчень сложнаяСредняяХорошая

Лучшие практики

  • Используй асинхронность для параллельных вызовов
  • Добавь timeout и retry logic для устойчивости
  • Кэшируй результаты, если данные не меняются часто
  • Используй fallbacks для graceful degradation
  • Логируй и мониторь композицию для отладки

Заключение

API Composition — это мощный паттерн для объединения данных из нескольких микросервисов на клиентской стороне. Это простое, но эффективное решение, особенно когда используется асинхронная реализация. Однако важно учитывать сетевые задержки, обработку ошибок и кэширование для оптимальной производительности.

Что такое API Composition? | PrepBro