Модель параллелизма Springboot для webflux реактора - PullRequest
0 голосов
/ 07 декабря 2018

Я хотел бы больше узнать о базовой модели параллелизма для Springboot Webflux?

Является ли традиционная модель многопоточной блокировки с интенсивным использованием ЦП более подходящей?Или это вообще традиционная модель пула потоков, лучше подходящая согласно этой статье https://people.eecs.berkeley.edu/~brewer/papers/threads-hotos-2003.pdf?

Если у меня есть этап блокировки в цепи реактора, я использую publishOn, чтобы запланировать его для другогоThreadPool.Это освобождает оригинальную нить и делает всю цепочку все еще не блокирующейся?

1 Ответ

0 голосов
/ 08 декабря 2018

Где хорошо подходит WebFlux и как он работает под капотом

С моей точки зрения, лучше всего подходит для Spring WebFlux приложения с интенсивным использованием сети.Под капотом Spring WebFlux используется Reactor-Netty, который является оболочкой с поддержкой противодавления для Netty.Reactor-Netty использует почти ту же стратегию Netty Threading и создает Runtime.getRuntime().availableProcessors() * 2 Threads для своих внутренних EventLoopThreadPool.Это означает, что каждый Thread привязан к своему ядру / процессору и работает с минимальным конфликтом ресурсов процессора.Такая модель очень хорошо работает с сквозной неблокирующей связью.Таким образом, в случае, если входящий запрос заканчивается удаленным сетевым вызовом, этот вызов должен выполняться неблокирующим образом, чтобы тот же поток мог вернуться к остальным задачам в очереди четного цикла.Такая методика позволяет нам эффективно использовать наше оборудование практически без затрат на переключение контекста и высокую конкуренцию, что является общим свойством блокирования связи с большим количеством задействованных потоков.

Роль Project Reactor

Центральная роль Project Reactor в Spring WebFlux заключается в предоставлении модели программирования, которая сохраняет ясность сложного неблокирующего асинхронного выполнения.Он скрывает сложность продолжения обработки данных и позволяет нам легко создать функциональную декларативную трубу обработки элементов.Кроме того, модель потоков в Reactor - это всего лишь пара операторов, которые обеспечивают сложные и эффективные перепланировки обработки элементов в выделенном пуле потоков без головной боли.Под капотом используются те же ThreadPools и ExecutorServices, которые взяты из библиотеки Java Core.

Как справляться с задачами, интенсивно использующими процессор, хорошо ли там работает Project Reactor?

Я бы сказал - Reactor Nettyхорошо подходит для задач, интенсивно использующих процессор.Но в этом случае Project Reactor следует использовать надлежащим образом.В случае сложной обработки алгоритма или подобной работы лучше использовать чистую Java, поскольку Reactor увеличивает производительность на 100-150%.

Как создать эффективную обработку задач с интенсивным использованием ЦП с помощью Project Reactor и Reactor-Netty (WebFlux)

Я бы рекомендовал следующий шаблон «Очередь работы», чтобы каждый поток выполнял новую задачу, как толькопредыдущий завершен.

В случае, если у нас есть задача с интенсивным использованием ЦП, всегда рекомендуется запланировать ее в выделенном пуле потоков.Даже при том, что это добавит немного накладных расходов, у нас будет более высокая задержка для записи чтения ввода / вывода, которая является неотъемлемой частью любого сетевого приложения.В случае Netty мы будем уверены, что EventLoop Netty выполняет только чтение и запись в сеть и ничего более.

Для планирования задач в выделенном пуле потоков мы можем следовать методике, показанной в кодеПример ниже:

@PostMapping
public Mono<CpuIntensiveResult> cpuIntensiveProcessingHandler(
    Mono<CpuIntensiveInput> monoInput
) {
    return monoInput
        .publishOn(Schedulers.fromExecutorService(myOwnDedicatedExecutor))
        .map(i -> doCpuIntensiveInImperativeStyle(i));
}

Как видно из приведенного выше кода, используя одного оператора из арсенала Project Reactor, мы можем легко планировать обработку работ в выделенном Threadpool.В свою очередь, мы можем быстро обернуть любую существующую службу Executor Service в планировщик и использовать скрытую экосистему Reactor

А как насчет блокировки по многопоточной технике?

При обычной многопоточной технике, где у нас больше потоковчем ядра, мы не получим никаких преимуществ.Недостаток здесь тот же - переключение контекста и раздоры.Казалось бы, задачи обрабатываются одновременно.Однако системный планировщик выполняет ту же тяжелую работу по распределению времени ЦП между параллельными потоками.Он будет использовать один и тот же ЦП для нескольких интенсивных задач, поэтому в результате у каждой задачи будет более высокая задержка.В среднем время обработки будет больше, чем та же работа, выполняемая тем же числом потоков, что и процессорами / ядрами в системе.

Несколько замечаний относительно моделей потоков как "истинной" модели обработки.

Согласно упомянутому техническому документу, модель Threading является настоящей моделью программирования.Я предполагаю, что авторы этой статьи говорят о Green Threads .Зеленые потоки могут быть лучшей моделью программирования, но, в конце концов, вам придется следовать тем же правилам, что и выше для модели программирования Reactor.Недостатком Thread и, следовательно, императивной модели программирования является невозможность работать с потоком данных, где модель программирования Reactor отлично подходит.

Кроме того, я бы порекомендовал пересмотреть Универсальный закон о масштабируемости и обзор проблем конкуренции и согласованности (которые имеют отношение к текущим выполнениям Java Threading).Кроме того, хороший обзор масштабируемости объясняется в следующей статье .

Еще одним примером эффективного использования асинхронной + неблокирующей обработки запросов является архитектура Facebook, которая при выборке преобразуеточередь работы в стек работы, что позволяет сохранить минимальную задержку.

...