Sobes.tech
Назад к вопросам
Junior — Middle
49

Имеете ли опыт работы с Reactive Streams и библиотекой Project Reactor для реализации асинхронных и нер blocking операций?

Компании, где спрашивали
СБЕРСБЕР

Ответ от нейросети

sobes.tech AI

Что хотят услышать интервьюеры:

Да, есть опыт работы с Reactive Streams и Project Reactor для построения асинхронных, неблокирующих цепочек обработки данных. Понимаю, как использовать Mono и Flux, управлять композициями операторов и не блокировать event loop. Также понимаю базовые принципы backpressure и когда reactive-подход действительно оправдан.

Определение:

Reactive Streams — это спецификация для асинхронной потоковой обработки данных с поддержкой backpressure, то есть контроля скорости потребления. Project Reactor — реализация этой модели в Java, где Mono представляет 0..1 элемент, а Flux — 0..N элементов. Основная идея — строить цепочки операторов без блокирующих вызовов и эффективно работать с конкурентными I/O-операциями.

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

Типичный кейс — получение данных из нескольких внешних сервисов и объединение результатов без блокировок.

Mono<User> userMono = userClient.getUser(userId);
Mono<List<Order>> ordersMono = orderClient.getOrders(userId);

Mono<UserProfile> profileMono = Mono.zip(userMono, ordersMono)
    .map(tuple -> new UserProfile(tuple.getT1(), tuple.getT2()));

profileMono.subscribe(
    profile -> System.out.println("Profile: " + profile),
    error -> System.err.println("Error: " + error.getMessage())
);

Пояснение кода:

В примере userClient.getUser(userId) и orderClient.getOrders(userId) возвращают неблокирующие Mono.
Оператор Mono.zip(...) запускает оба запроса параллельно и ждёт результаты обоих.
После этого map(...) собирает итоговый объект UserProfile.
Метод subscribe(...) запускает выполнение цепочки и обрабатывает успешный результат или ошибку.

Ключевые моменты:

  • Mono — для одного результата или пустого значения, Flux — для потока элементов.
  • Reactor позволяет писать неблокирующий код и лучше масштабировать I/O-нагруженные сценарии.
  • Backpressure важен, когда источник данных может производить события быстрее, чем потребитель их обрабатывает.
  • map, flatMap, zip, filter, onErrorResume — базовые операторы, которые часто используют в цепочках.
  • Не стоит вызывать block() в реактивном потоке без необходимости, чтобы не терять преимущества non-blocking подхода.