Некоторое время я использую HttpClient в многопоточной среде. Для каждого потока, когда он инициирует соединение, он создает полностью новый экземпляр HttpClient.
Недавно я обнаружил, что использование этого подхода может привести к тому, что у пользователя будет открыто слишком много портов, и большинство подключений находятся в состоянии TIME_WAIT.
http://www.opensubscriber.com/message/commons-httpclient-dev@jakarta.apache.org/86045.html
Следовательно, вместо того, чтобы делать каждый поток:
HttpClient c = new HttpClient();
try {
c.executeMethod(method);
}
catch(...) {
}
finally {
method.releaseConnection();
}
Мы планируем иметь:
[СПОСОБ А]
// global_c is initialized once through
// HttpClient global_c = new HttpClient(new MultiThreadedHttpConnectionManager());
try {
global_c.executeMethod(method);
}
catch(...) {
}
finally {
method.releaseConnection();
}
В нормальной ситуации к global_c будут обращаться одновременно 50 ++ потоков. Мне было интересно, это создаст проблемы с производительностью? Использует ли MultiThreadedHttpConnectionManager безблокировочный механизм для реализации своей политики безопасности потоков?
Если 10 потоков используют global_c, будут ли заблокированы остальные 40 потоков?
Или было бы лучше, если бы в каждом потоке я создавал экземпляр HttpClient, но явно освобождал диспетчер соединений?
[МЕТОД Б]
MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManager();
HttpClient c = new HttpClient(connman);
try {
c.executeMethod(method);
}
catch(...) {
}
finally {
method.releaseConnection();
connman.shutdown();
}
Будет ли connman.shutdown () иметь проблемы с производительностью?
Могу ли я узнать, какой метод (A или B) лучше для приложения, использующего потоки 50 ++?
источник
Метод A рекомендуется сообществом разработчиков httpclient.
Пожалуйста, обратитесь к http://www.mail-archive.com/httpclient-users@hc.apache.org/msg02455.html для получения дополнительных сведений.
источник
netstat
отлично справляется с этим. technet.microsoft.com/en-us/sysinternals/bb897437.aspx тожеНасколько я понимаю, HttpConnection сам по себе не рассматривается как потокобезопасный, и, следовательно, MultiThreadedHttpConnectionManager предоставляет многоразовый пул HttpConnections, у вас есть один MultiThreadedHttpConnectionManager, общий для всех потоков и инициализированный ровно один раз. Итак, вам нужно внести несколько небольших уточнений в вариант А.
MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManag
Затем каждый поток должен использовать последовательность для каждого запроса, получать соединение из пула и возвращать его по завершении своей работы - использование блока finally может быть хорошим. Вы также должны указать возможность того, что у пула нет доступных соединений, и обработать исключение тайм-аута.
HttpConnection connection = null try { connection = connman.getConnectionWithTimeout( HostConfiguration hostConfiguration, long timeout) // work } catch (/*etc*/) {/*etc*/} finally{ if ( connection != null ) connman.releaseConnection(connection); }
Поскольку вы используете пул соединений, вы фактически не будете закрывать соединения, поэтому это не должно вызывать проблему TIME_WAIT. Этот подход предполагает, что каждый поток не остается в соединении надолго. Обратите внимание, что сам мошенник остается открытым.
источник
Я думаю, вы захотите использовать ThreadSafeClientConnManager.
Вы можете увидеть, как это работает, здесь: http://foo.jasonhudgins.com/2009/08/http-connection-reuse-in-android.html
Или в том,
AndroidHttpClient
кто его использует внутри.источник
С HttpClient 4.5 вы можете сделать это:
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(new PoolingHttpClientConnectionManager()).build();
Обратите внимание, что этот реализует Closeable (для закрытия диспетчера соединений).
источник