Senior
56
Υπάρχει ένα backend, υπάρχει μια διεπαφή χρήστη. Η τεχνολογική στοίβα είναι στάνταρ: Java, Spring, React, Postgres. Αποστολή: Σχεδιάστε ένα REST endpoint που πρέπει να λαμβάνει δεδομένα από 3 πηγές και να τα επιστρέφει στο UI, διασφαλίζοντας τη μέγιστη δυνατή διαπεραστικότητα και το ελάχιστο δυνατό χρόνο απόκρισης (κριτήρια μέγιστο/ελάχιστο βάσει των συγκεκριμένων συνθηκών μας, καθώς στην ουσία δεν υπάρχει μαγική λύση και πρέπει να βρεθεί μια συμβιβαστική λύση). Γνωρίζουμε ότι η αναμενόμενη κορύφωση RPS για αυτό το endpoint θα είναι 200. Λεπτομέρειες γνωστές σχετικά με τις πηγές: 1. Πηγή - η βάση δεδομένων μας, η ερώτηση διαρκεί περίπου 15 δευτερόλεπτα. 2. Πηγή - σχετικός REST υπηρεσία, υποβαθμίζεται έως 2 λεπτά υπό 100 RPS, απαντά σε 5 δευτερόλεπτα σε κανονική λειτουργία. Δεν μπορούμε να αλλάξουμε τη συμπεριφορά αυτής της πηγής. 3. Πηγή - σχετικός REST υπηρεσία, απαντά τυχαία (δεν έχουν εντοπιστεί συγκεκριμένα μοτίβα) με σφάλματα 503, σε κανονική λειτουργία απαντά σε 10 δευτερόλεπτα. Δεν μπορούμε να αλλάξουμε τη συμπεριφορά αυτής της πηγής.
Εταιρείες όπου ρωτήθηκαν
солюшин
Απάντηση από AI
sobes.tech AI
Для проектирования REST-эндпоинта с тремя источниками данных и учетом требований по пропускной способности и времени отклика, предлагаю следующий подход:
-
Асинхронный параллельный запрос к источникам:
- Запросы к базе и двум REST-сервисам выполняются параллельно, чтобы минимизировать общее время ожидания.
-
Кеширование:
- Для источника с долгим запросом к базе (15 сек) стоит реализовать кеширование результатов с разумным TTL, чтобы снизить нагрузку при пиковых запросах.
-
Таймауты и fallback:
- Для второго источника, который деградирует при высокой нагрузке, установить таймауты (например, 5-7 сек) и использовать кеш или возвращать частичные данные, если сервис не отвечает.
- Для третьего источника, который иногда возвращает 503, реализовать повторные попытки с экспоненциальной задержкой и fallback на кеш или дефолтные данные.
-
Реактивное программирование:
- Использовать Spring WebFlux или CompletableFuture для неблокирующего выполнения запросов и объединения результатов.
-
Агрегация и отдача данных:
- После получения данных из всех источников агрегировать их в единый ответ.
- Если какой-то источник не доступен, возвращать частичные данные с указанием статуса.
-
Мониторинг и ограничение нагрузки:
- Внедрить 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);
Таким образом, достигается баланс между скоростью отклика и надежностью, учитывая ограничения и особенности каждого источника.