Как выполнить неблокирующие вызовы HTTP в Java? - PullRequest
2 голосов
/ 22 марта 2020

У меня есть сторонний API, который я вызываю с помощью HTTP GET-запроса. Каждый запрос занимает несколько секунд, чтобы получить ответ.

В настоящее время я использую CompletableFuture, который я выполняю на FixedThreadPool размером 64. Это приводит к блокировке потоков, пока он не получит ответ для GET запрос, то есть потоки бездействуют после отправки ответа GET, пока не получат ответ. Таким образом, мое максимальное количество одновременных запросов, которые я могу отправить, ограничено размером моего потока, то есть здесь 64.

Что я могу использовать вместо CompletableFuture, чтобы мои потоки не бездействовали в ожидании ответа?

1 Ответ

2 голосов
/ 22 марта 2020

Как @ user207421 говорит:

  • Действительно асинхронное (т.е. управляемое событиями) клиентское приложение HTTP является сложным.
  • Многопоточное (но принципиально синхронное) клиентское приложение HTTP является проще и масштабируется до такого количества потоков, на которое у вас есть память.
  • При условии, что у вас есть 64 рабочих потока, обрабатывающих запросы, фактическое узкое место вероятно будет ЛИБО вашей физической сетью пропускной способности, или ваш доступный клиентский процессор. Если вы достигли этих пределов, то:

    • увеличение количества рабочих потоков не поможет, а
    • переключение на асинхронную (управляемую событиями) модель не приведет к help.
  • Третья возможность заключается в том, что узким местом является ограничение ресурсов на стороне сервера или ограничение скорости. В этом случае увеличение числа потоков на стороне клиента может помочь, не повлиять или усугубить проблему. Это будет зависеть от того, как реализован сервер, от характера запросов и т. Д. c.

Если узким местом действительно является количество потоков, то попробуйте сделать следующее: уменьшение размера стека рабочих потоков, чтобы вы могли запускать их больше. Размер стека по умолчанию обычно составляет 1 МБ, и это, вероятно, будет значительно больше, чем нужно. (Это также уменьшит накладные расходы ... эээ ... памяти незанятых потоков, если это действительно проблема.)

Существует несколько Java асинхронных клиентских библиотек HTTP. Но я никогда не использовал и не могу рекомендовать один. И как @ user207421, я не уверен, что усилия по изменению действительно окупятся.


Что я могу [сделать], чтобы мои потоки не бездействовали в ожидании ответа ?

Свободные потоки на самом деле не проблема. Свободный поток использует только память (и некоторые возможные вторичные эффекты, которые, вероятно, здесь не имеют значения). Если у вас недостаточно памяти, это не будет иметь большого значения.

Примечание: если клиенту нужно что-то еще сделать, пока поток ожидает ответа сервера, планировщик потока ОС переключится на другое нить.

Таким образом, мое максимальное количество одновременных запросов, которые я могу отправить, ограничено размером моей нити [pool] , т.е. 64 здесь.

Это правда. Однако отправка большего количества одновременных запросов, вероятно, не поможет. Если клиентские потоки бездействуют, то , вероятно означает, что узким местом является либо сеть, либо что-то на стороне сервера. В этом случае добавление большего количества потоков не увеличит пропускную способность. Вместо этого отдельные запросы будут занимать (в среднем) больше времени, а пропускная способность останется прежней ... или, возможно, будет отброшена, если сервер начнет отбрасывать запросы из своей очереди запросов.

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

...