Использование ForkJoinPool вместе с AsyncHttpClient — имеет ли смысл?

Мои вопросы в некоторой степени связаны с этим вопросом о ForkJoinPool и операциях, ориентированных на ввод-вывод, но он немного более общий (и вопрос, на который я ссылался, не получил определенного ответа). Короче говоря, если я хочу отправить много HTTP-запросов параллельно и уже использую асинхронный HTTP-клиент (например, AsyncHttpClient), есть ли смысл отправлять запросы параллельно, используя ForkJoinPool?

Первоначально я думал, что это противоречит цели использования асинхронного HTTP-клиента, который уже позволяет отправлять запросы параллельно. Однако, читая этот связанный вопрос о ForkJoinPool , в котором упоминалось, что ForkJoinPool может повысить производительность, даже «когда все задачи асинхронны и отправлены в пул, а не разветвлены», заставил меня усомниться в моем понимании того, как асинхронные операции работают в Java и как их следует выполнять. Есть ли еще преимущество использования ForkJoinPool в моей ситуации, и если да, то почему?

Я также прочитал этот вопрос о том, как отправлять HTTP-запросы в Parallel в Java, и во всех ответах упоминается либо использование ExecutorService, либо AsyncHttpClient, но ни в одном ответе не упоминается оба.


person Dean Gurvitz    schedule 27.03.2020    source источник


Ответы (1)


Это ортогональные концепции, поэтому вы не видите их упоминания в одних и тех же ответах.

Целью AsyncHttpClient является (среди прочего) использование одного потока для всех сетевых взаимодействий (выполняемых внутри Netty через Java NIO неблокирующим асинхронным способом) вместо традиционного потока на один поток. - модель запроса. В дополнение к одному потоку сетевого уровня в библиотеке есть рабочие потоки, которые выполняют асинхронную обработку уровня приложения, видимую для пользователей AsyncHttpClient, что означает, что у нее уже есть (небольшой) внутренний пул потоков.

ForkJoinPool стремится максимизировать загрузку ЦП, имея много потоков (общий пул по умолчанию имеет CPU cores - 1, созданные вами могут иметь больше/меньше) и за счет перехвата работы, чтобы потоки не простаивали, и это наиболее эффективен с небольшими рекурсивными задачами.

В ссылке обсуждается, что кража работы также эффективна с нерекурсивными задачами. Слово «асинхронный» сбило вас с толку, но оно просто относится к обычной задаче, которую вы отправляете в пул, и она завершается асинхронно.

Таким образом, вы можете либо выполнять поток на запрос (т. е. базовый ввод-вывод или «старый ввод-вывод») с пулом потоков, или вы можете использовать одиночный многопоточный неблокирующий NIO (т. е. новый ввод-вывод) без пула потоков.

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

person Kayaman    schedule 27.03.2020
comment
2 быстрых вопроса относительно вашего ответа: 1. Действительно ли Java поддерживает однопоточные асинхронные операции, как вы упомянули? Я знаю, что асинхронность С# работает, но я не знал, что в Java тоже есть механизмы для этого. 2. Вы имели в виду написать will или should в последнем предложении - person Dean Gurvitz; 27.03.2020
comment
@DeanGurvitz это не связано с ключевым словом async. Это сетевые операции, которые выполняются в одном потоке (с использованием селектора, который также работает асинхронно). AsyncHttpClient затем имеет дополнительные функции для асинхронных операций (на стороне Java). 2. будет, потому что написать базовый ввод-вывод с несколькими потоками легко, но в конечном итоге вы захотите повысить производительность и перейти к более сложной, но более производительной модели. - person Kayaman; 27.03.2020
comment
@DeanGurvitz это может немного сбивать с толку, потому что есть асинхронная модель NIO (внутри Netty) и асинхронная модель AsyncHttpClient. Первый имеет низкий уровень, а второй — более высокий уровень. - person Kayaman; 27.03.2020
comment
@DeanGurvitz добавил информацию о том, как AsyncHttpClient управляет видимыми вам асинхронными операциями. Как вы правильно сказали, в Java нет однопоточного async (и, похоже, в ближайшем будущем не будет, некоторые обходные пути с CompletableFuture были сделаны, но они не совпадают), поэтому должны быть некоторые дополнительные потоки в дополнение к потоку, выполняющему сетевое взаимодействие. - person Kayaman; 27.03.2020
comment
Отлично, это помогает еще больше прояснить ситуацию. - person Dean Gurvitz; 27.03.2020