Sobes.tech
Middle+

Há um backend, há um frontend. Stack padrão: Java, Spring, React, Postgres. Tarefa: Projetar um endpoint REST que deve obter dados de 3 fontes e entregá-los ao UI, garantindo a maior capacidade possível e o menor tempo de resposta possível (critérios máximos/mínimos de acordo com nossas condições específicas, pois na prática não há uma solução mágica e é preciso encontrar um compromisso). Sabe-se que o pico esperado de RPS para este endpoint REST será de 200. Detalhes conhecidos sobre as fontes: 1. Fonte - nosso banco de dados, consulta cerca de 3 segundos. 2. Fonte - um serviço REST relacionado, degrada até 2 minutos sob 100 RPS, em modo normal responde em 5 segundos. Não podemos alterar seu comportamento. 3. Fonte - outro serviço REST relacionado, responde aleatoriamente com erros 503 (não foi possível identificar um padrão), em modo normal responde em 10 segundos. Não podemos alterar seu comportamento.

sobes.tech IA

Resposta da IA

Для проектирования REST-эндпоинта с тремя источниками данных и требованиями по максимальной пропускной способности и минимальному времени отклика, учитывая особенности источников, можно предложить следующий подход:

  1. Асинхронный вызов источников:

    • Запрос к базе (3 сек) можно выполнять параллельно с вызовами к REST-сервисам.
    • Вызовы к двум REST-сервисам также выполнять параллельно.
  2. Кэширование:

    • Для второго источника, который деградирует при высокой нагрузке, стоит использовать кэширование результатов, чтобы снизить количество запросов к нему.
    • Кэш можно обновлять с определённой периодичностью или по событию.
  3. Обработка ошибок и таймауты:

    • Для третьего источника, который может отдавать 503, нужно реализовать механизм повторных попыток с экспоненциальной задержкой и fallback (например, возвращать последние успешные данные или заглушку).
    • Установить разумные таймауты для всех запросов, чтобы не блокировать ответ UI.
  4. Пул потоков и ограничение параллелизма:

    • Для REST-сервисов использовать пул потоков с ограничением количества одновременных запросов, чтобы не перегружать внешние сервисы.
  5. Сбор и агрегация данных:

    • После получения данных из всех источников агрегировать их и отдать UI.
  6. Мониторинг и метрики:

    • Внедрить мониторинг времени отклика и ошибок, чтобы оперативно реагировать на деградацию.

Пример упрощённого кода на Java с использованием CompletableFuture:

CompletableFuture<Data1> dbFuture = CompletableFuture.supplyAsync(() -> fetchFromDb());
CompletableFuture<Data2> service2Future = CompletableFuture.supplyAsync(() -> fetchFromService2WithCache());
CompletableFuture<Data3> service3Future = CompletableFuture.supplyAsync(() -> fetchFromService3WithRetry());

CompletableFuture.allOf(dbFuture, service2Future, service3Future).join();

Data1 d1 = dbFuture.get();
Data2 d2 = service2Future.get();
Data3 d3 = service3Future.get();

Response response = aggregate(d1, d2, d3);
return response;

Таким образом, достигается баланс между временем отклика и нагрузкой на внешние сервисы, а также обеспечивается устойчивость к ошибкам.