Существующий вопрос зависит от множества факторов:
- аппаратное обеспечение
- операционная система (и ее конфигурация)
- Реализация JVM
- Сетевые устройства
- Поведение сервера
Первый вопрос: должна ли разница быть такой значительной?
Зависит от нагрузки, размера пула и сети, но это может быть намного больше, чем наблюдаемый коэффициент 2 в каждом из направлений (в пользу асинхронного или многопоточного решения). Согласно вашему более позднему комментарию, разница больше из-за неправомерных действий, но ради аргумента я объясню возможные случаи.
Выделенные потоки могут быть довольно обузой. (Обработка прерываний и планирование потоков выполняются операционной системой в случае, если вы используете Oracle [HotSpot] JVM, поскольку эти задачи делегированы.) ОС/система может перестать отвечать на запросы, если потоков слишком много, что замедляет пакетную обработку ( или другие задачи). Существует много административных задач, связанных с управлением потоками, поэтому пулы потоков (и соединений) так важны. Хотя хорошая операционная система должна быть в состоянии обрабатывать несколько тысяч одновременных потоков, всегда есть шанс, что возникнут какие-то ограничения или события (ядра).
Вот где пригодятся объединение и асинхронное поведение. Например, существует пул из 10 физических потоков, выполняющих всю работу. Если что-то заблокировано (в данном случае ожидает ответа сервера), оно переходит в состояние «Заблокировано» (см. изображение), и следующая задача заставляет физический поток выполнить некоторую работу. Когда поток уведомляется (прибывают данные), он становится «выполняемым» (с этого момента механизм пула может его забрать [это может быть решение, реализованное в ОС или JVM]). Для дальнейшего чтения состояний потока я рекомендую W3Rescue. Чтобы лучше понять пулы потоков, я рекомендую эту статью о baeldung.
Второй вопрос: что-то не так с асинхронной реализацией? Если нет, то как здесь правильно поступить?
Реализация нормальная, проблем с ней нет. Поведение просто отличается от многопоточного способа. Главный вопрос в этих случаях в основном заключается в том, что такое SLA (соглашения об уровне обслуживания). Если вы являетесь единственным «пользователем услуги», то в основном вам приходится выбирать между задержка или пропускная способность, но решение будет касаться только вас. В большинстве случаев это не так, поэтому я бы порекомендовал какой-либо пул, который поддерживается используемой вами библиотекой.
Третий вопрос. Однако я только что отметил, что время, затрачиваемое на чтение потока ответов в виде строки, примерно такое же. Интересно, почему это?
Сообщение, скорее всего, пришло полностью в обоих случаях (вероятно, ответ не поток, а несколько http-пакетов), но если вы читаете только заголовок, который не требует разбора и загрузки самого ответа в регистры ЦП, тем самым уменьшая задержку чтения фактических полученных данных. Я думаю, что это отличное представление о задержках (источник и источник):
Это получился довольно длинный ответ, так что TL.DR.: масштабирование — очень сложная тема, она зависит от многих вещей:
- аппаратное обеспечение: количество физических ядер, многопоточность, скорость памяти, сетевой интерфейс.
- операционная система (и ее конфигурация): управление потоками, обработка прерываний
- Реализация JVM: управление потоками (внутреннее или переданное ОС), не говоря уже о конфигурациях GC и JIT.
- Сетевые устройства: некоторые ограничивают одновременные подключения с заданного IP-адреса, некоторые объединяют не
HTTPS
подключения и действуют как прокси.
- Поведение сервера: объединенные рабочие процессы или рабочие процессы по запросу и т. д.
Скорее всего в вашем случае узким местом был сервер, так как оба метода дали одинаковый результат в исправленном случае (HttpResponse::getStatusLine().getStatusCode() and HttpURLConnection::getResponseCode()
). Чтобы дать правильный ответ, вы должны измерить производительность своих серверов с помощью некоторых инструментов, таких как JMeter или LoadRunner и т. д., а затем соответствующим образом масштабируйте свое решение. Эта статья больше посвящена пулу соединений с БД, но логика применима и здесь.
person
Hash
schedule
10.12.2018
HttpResponse::getStatusLine().getStatusCode()
иHttpURLConnection::getResponseCode()
соответственно. Однако я только что отметил, что затраченное время примерно такое же, как и в тот момент, когда вы читаете поток ответов в виде строки. Интересно, почему это так? Оба не должны читать тело ответа, если поток не прочитан - person Erric   schedule 08.12.2018