Apache HttpClient Управление соединениями - PullRequest
1 голос
/ 13 июня 2019

Я пытаюсь понять лучший подход к управлению http-соединениями с использованием Apache HttpClient в реализации (не моей). Я думаю, то, как это реализовано сейчас, - пустая трата времени, но, поскольку я не очень знаком с этой библиотекой, я хотел бы подтвердить свои мысли.

Рассмотрим этот сценарий:

  • У меня есть веб-приложение в tomcat, что означает многопоточную среду.
  • Мне нужно связаться с Rest WebService из класса Rest. новый экземпляр класса Rest создается каждым запросом к моему приложению, чтобы вызвать нужную мне службу.

Опция 1 (в настоящее время реализовано): класс Rest создает новый экземпляр PoolingHttpClientConnectionManager и выполняет запрос.

Лично я думаю, что это пустая трата времени. Только один поток одновременно обращается к экземпляру менеджера. Таким образом, в этом подходе нет никакой пользы. Это на самом деле хуже, так как я предполагаю, что этот менеджер может быть дорогим для создания (?). Итак, в действительности мы в конечном итоге создаем несколько PoolingHttpClientConnectionManager, по одному на поток (по одному на запрос).

Вариант 2: класс Rest может создавать только один PoolingHttpClientConnectionManager как своего рода синглтон.

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

Вариант 3: класс Rest может создать один новый экземпляр BasicHttpClientConnectionManager.

Я попробовал это и работаю просто отлично. Это означает, что каждый поток будет иметь свой собственный менеджер соединений. Несмотря на то, что у этого менеджера есть одно соединение, поскольку у нас есть один менеджер на поток, мы выполняем параллельное выполнение.

Я думаю, что недостатком этого подхода является отсутствие ограничений. Поэтому, если мое приложение получает слишком много запросов, мы каждый раз создаем нового менеджера, плюс мы не будем повторно использовать соединения по тому же маршруту.

Буду признателен за любые мысли по этому поводу. Я видел много примеров, но всегда простые примеры из основной функции и явное создание потоков. Не видел ни одного примера с сервера приложений, такого как tomcat.

Ответы [ 3 ]

1 голос
/ 13 июня 2019

Опция 2 настоятельно рекомендуется.

0 голосов
/ 15 июня 2019

Согласно Документация клиента Apache Commons HTTP вариант 2 является наиболее разумным.

Сначала говорится:

Процесс установления соединенияот одного хоста к другому довольно сложен и включает в себя несколько обменов пакетами между двумя конечными точками, что может занять довольно много времени.Затраты на установление соединения могут быть значительными, особенно для небольших HTTP-сообщений.Можно достичь гораздо более высокой пропускной способности данных, если открытые соединения можно повторно использовать для выполнения нескольких запросов.

HTTP / 1.1 указывает, что соединения HTTP могут повторно использоваться для нескольких запросов по умолчанию.Конечные точки, совместимые с HTTP / 1.0, также могут использовать механизм для явного сообщения о своих предпочтениях, чтобы поддерживать соединение и использовать его для нескольких запросов.HTTP-агенты также могут поддерживать незанятые соединения в течение определенного периода времени, если для последующих запросов требуется соединение с тем же целевым хостом.Способность поддерживать соединения в действии обычно называется постоянством соединения.HttpClient полностью поддерживает постоянство соединения.

Итак, после этого абзаца мы можем заключить, что да, это очень плохая идея создавать экземпляры HTTP-соединений каждый раз, когда мы хотим сделать HTTP-запрос и то, что вы называете опцией1 в вашем вопросе - не самый лучший путьподключений и может обслуживать запросы на подключение из нескольких потоков выполнения.Соединения объединяются для каждого маршрута.Запрос на маршрут, для которого у менеджера уже есть постоянное соединение, доступное в пуле, будет обслуживаться путем аренды соединения из пула, а не создания нового соединения.

Итак, после прочтения этогоВ связи с этим мы можем заключить, что да, имеет смысл иметь единый пул соединений, общий для всех потоков приложения.Таким образом, в идеале вы должны создать его один раз и поделиться им везде, где вам необходимо получить HTTP-соединение.

Наконец, в отношении варианта 3 в документации сказано:

BasicHttpClientConnectionManager - этопростой диспетчер соединений, который поддерживает только одно соединение одновременно.Несмотря на то, что этот класс является поточно-ориентированным, он должен использоваться только одним потоком выполнения.BasicHttpClientConnectionManager предпримет попытку повторно использовать соединение для последующих запросов по тому же маршруту.Однако он закроет существующее соединение и снова откроет его для данного маршрута, если маршрут постоянного соединения не совпадает с маршрутом запроса соединения.Если соединение уже выделено, генерируется исключение java.lang.IllegalStateException.

Итак, вариант 3 имеет смысл, но определенно это звучит не лучше, чем вариант 2 с точки зрения повторного использования дорогих ресурсов.

0 голосов
/ 13 июня 2019

На самом деле я только что прочитал о вопросе, связанном с этим, но в c #, и я не профессионал в этом вопросе, в основном рекомендуется вариант 2.Создание нового диспетчера соединений для каждого соединения может привести к снижению производительности, так как он создает новый экземпляр только для нового соединения (он может быть только соединением запроса, но фактически его не использовать и истощит менеджер httpclient).И этой причины будет достаточно, чтобы выбрать ваш вариант.Вот ссылка на тему ссылка ...

Надеюсь, эта помощь.

...