должен ли менеджер соединений действительно завершить работу? - PullRequest
3 голосов
/ 13 декабря 2011

Иногда я получаю

java.net.SocketException: Too many open files 
java.net.Socket.createImpl(Socket.java:397) 
java.net.Socket.connect(Socket.java:527) 
org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:123) 
org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:123) 
org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:147) 
org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:108) 
org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:415) 
org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641) 
org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:597) 

Я видел похожий вопрос java.net.SocketException: слишком много открытых файлов , и я тоже использую apc httpclient, но, похоже, ответы былине совсем полезно для меня ...

Было два ответа:

1) выполнение httpClient.getConnectionManager().shutdown();

2) вызов entity.getContent().close() вместо entity.consumeContent()

Но, похоже, ни один из них не подходит ...

1) Проблема в том, что я использую ThreadSafeConnectionManager.Он создается один раз (при запуске приложения).и поэтому мы не делаем выключение (чтобы соединения можно было повторно использовать).Если я сделаю отключение на этом менеджере - все соединения будут закрыты.Было бы целесообразно, если я использую SingleClientConnectionManager, но я не делаю.Я прав?

2) Я обнаружил, что я тоже не закрываю поток.Но когда я начал отлаживать - кажется, что этот поток getContent() уже закрыт, даже до вызова consumeContent().Хотя (даже после consumeContent) socketInputStream внутри потока getContent () не был закрыт, как и сокет.Это плохо?Может ли это быть причиной проблемы?И я не нашел способ, как закрыть эту розетку!Он расположен внутри внешнего входного потока, поэтому я не могу его получить.Но я вижу в режиме отладки, что этот сокет не закрыт, а также SocketInputStream.

Как обычно мы должны работать с ThreadSafeConnectionManager - его нужно создавать только один раз?и если это так, как правильно закрыть эти сокеты, если таковые имеются?

1 Ответ

7 голосов
/ 13 декабря 2011

Если я сделаю выключение на этом менеджере - все соединение будет закрыто. Было бы целесообразно, если я использую SingleClientConnectionManager, но я нет. Я прав?

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

http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e659

Хотя (даже после потребление контента) socketInputStream внутри те getContent () поток не был закрыт, как и сокет. Это плохо?

Нет, это не так. Базовое соединение может быть сохранено, если оно находится в согласованном состоянии. Однако один должен закрыть поток контента, чтобы обеспечить сброс этого соединения обратно в диспетчер соединений.

Как обычно мы должны работать с ThreadSafeConnectionManager - это должно быть создано только один раз? и если это так, как правильно закрыть эти розетки, если таковые имеются?

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

И, наконец, обратите внимание, что другие компоненты вашего приложения могут также иметь утечку файловых дескрипторов. Виновником может быть не обязательно менеджер соединений HttpClient.

...