Sobes.tech
Senior
57

Turi backend ir vartotojo sąsaja. Technologijų rinkinys yra standartinis: Java, Spring, React, Postgres. Užduotis: suprojektuoti REST galinį tašką, kuris turi gauti duomenis iš 3 šaltinių ir grąžinti juos UI, užtikrinant maksimalų pralaidumą ir minimalų atsako laiką (maks./min. kriterijai pagal mūsų konkrečias sąlygas, nes iš esmės nėra stebuklingo sprendimo ir reikia rasti kompromisą). Žinoma, kad tikėtinas šio galinio taško viršūnės RPS bus 200. Žinomi šaltinių duomenys: 1. Šaltinis - mūsų duomenų bazė, užklausa trunka apie 15 sekundžių. 2. Šaltinis - susijęs REST paslauga, degraduoja iki 2 minučių esant 100 RPS, normaliu režimu atsako per 5 sekundes. Mes negalime keisti šio šaltinio elgesio. 3. Šaltinis - susijęs REST paslauga, atsako atsitiktinai (nebuvo nustatyti specifiniai modeliai) su 503 klaidomis, normaliu režimu atsako per 10 sekundžių. Mes negalime keisti šio šaltinio elgesio.

Įmonės kur klausė
солюшин

Atsakymas iš AI

sobes.tech AI

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

  1. Асинхронный параллельный запрос к источникам:

    • Запросы к базе и двум REST-сервисам выполняются параллельно, чтобы минимизировать общее время ожидания.
  2. Кеширование:

    • Для источника с долгим запросом к базе (15 сек) стоит реализовать кеширование результатов с разумным TTL, чтобы снизить нагрузку при пиковых запросах.
  3. Таймауты и fallback:

    • Для второго источника, который деградирует при высокой нагрузке, установить таймауты (например, 5-7 сек) и использовать кеш или возвращать частичные данные, если сервис не отвечает.
    • Для третьего источника, который иногда возвращает 503, реализовать повторные попытки с экспоненциальной задержкой и fallback на кеш или дефолтные данные.
  4. Реактивное программирование:

    • Использовать Spring WebFlux или CompletableFuture для неблокирующего выполнения запросов и объединения результатов.
  5. Агрегация и отдача данных:

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

    • Внедрить circuit breaker (например, Resilience4j) для защиты от деградации смежных сервисов.
    • Ограничить количество одновременных запросов к проблемным источникам.

Пример использования CompletableFuture для параллельного запроса:

CompletableFuture<Data1> future1 = CompletableFuture.supplyAsync(() -> fetchFromDb());
CompletableFuture<Data2> future2 = CompletableFuture.supplyAsync(() -> fetchFromService2());
CompletableFuture<Data3> future3 = CompletableFuture.supplyAsync(() -> fetchFromService3());

CompletableFuture.allOf(future1, future2, future3).join();

// Обработка результатов с учетом ошибок и таймаутов
Data1 d1 = future1.getNow(null);
Data2 d2 = future2.getNow(null);
Data3 d3 = future3.getNow(null);

// Формируем ответ
return aggregate(d1, d2, d3);

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