Приложение 1 отправляет запрос в приложение 2. Приложение 2 выполняет следующие шаги и возвращает ответ на приложение 1. Мне интересно, может ли приложение 2 извлечь выгоду из использования реактивных библиотек, таких как RxJava, Reactor и т.д. Если это так, пожалуйста, объясните, как?
Это как классический вариант использования для реактивных библиотек, как вы могли бы найти! :)
Ключевой частью "реактивных" архитектур является то, что они могут реагировать на события, а не ждать результатов. RxJava облегчает это через Observable
и Reactor делает это с помощью нескольких различных механизмов. В Reactor вы можете использовать простой Reactor
и установить replyTo
на Event
, вы можете использовать Stream
или Promise
для создания цепочки обработки значений, таких как RxJava Observable
, вы можете использовать Processor
для выполнения высокоскоростной обработки RingBuffer, или вы можете использовать ForkJoinPool
для выполнения простой обработки вил/присоединения. Это много вариантов, но каждый из них предназначен для работы в конкретном прецеденте без ущерба для других вариантов использования. Реактор каркаса - это не один, регулируемый гаечный ключ. Это набор гаечных ключей, предназначенных точно для того, что вам нужно.
В этом конкретном случае важной частью является параллелизм, достигаемый при выполнении большого количества операций одновременно, поскольку ваш источник данных IO, по-видимому, блокирует поток. RxJava имеет подключаемую модель исполнения, но она довольно грубая. Одной из сильных сторон реактора является эффективная, мелкозернистая диспетчерская поддержка задач и легкость, с которой вы можете реагировать на результаты.
Так как ваш пример использования довольно прост и намного ближе к стандартной ситуации ThreadPoolExecutor
, у меня может возникнуть соблазн использовать ForkJoinPool
в Reactor 1.1 (который является совершенно новым). ForkJoinPool
предоставляет вам один Promise<ImmutableList<T>>
который объединяет результаты всех задач, которые вы отправляете в пул, который поддерживается стандартным ThreadPoolExecutor
. Это в основном "реактивная" оболочка вокруг стандартного пула потоков, поэтому для этого требуется очень мало накладных расходов, но обеспечивает гибкость реагирования на завершение всех представленных задач. Он похож на RxJava Observable.merge()
.
join
вам может понадобиться метод fork
, который дает вам Stream
для которого вы можете установить обработчик when()
для ошибок и «нормальный» Consumer
для результатов. Вы должны будете следить за бухгалтерским учетом самостоятельно, чтобы знать, сколько результатов вы получили по сравнению с тем, сколько вы ожидали. Поддержка Spring в Reactor также имеет реализацию AsyncListenableTaskExecutor
которая использует настроенный вами Dispatcher
Reactor. Это, вероятно, лучший вариант для больших объемов, поскольку «нормальный» пул потоков при высокой нагрузке довольно неэффективен.
reactive
решение здесь, но я хочу добавить немного шума. В EIP он называетsplit-aggregate
а Spring Integration предоставляет это решение как готовое. В этом случае сплиттер может отправлять элементы вThreadPoolExecutor
или, если хотите, в Reactor или просто в RingBuffer. Каждаяdata source service
должна отправлять свой результатaggregator
а последняя просто отправляет объединенный ответ.