连接管理员应该真的关机吗?

时间:2011-12-13 13:55:58

标签: java sockets connection-pooling apache-httpclient-4.x

有时我会收到

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: Too many open files,我也使用了apache的httpclient,但似乎答案对我来说没什么帮助...

有两个答案:

1)做httpClient.getConnectionManager().shutdown();

2)拨打entity.getContent().close()而不是entity.consumeContent()

但似乎没有一个适合......

1)问题在于我正在使用ThreadSafeConnectionManager。它创建一次(在应用程序启动时)。因此我们不会关闭(以便连接可重复使用)。如果我关闭此管理器 - 所有连接都将关闭。如果我使用SingleClientConnectionManager这是合适的,但我不这样做。我是对的吗?

2)我发现我也没有关闭流。但是当我开始调试时 - 即使在调用getContent()之前,这个consumeContent()流似乎已经关闭了。虽然(即使在consumeContent之后)这些getContent()流中的socketInputStream也未关闭,以及socket。这不好吗?它可能是问题的原因吗?我没有找到如何关闭这个插座的方法!它位于外部输入流的内部,所以我无法得到它。但我在调试模式中看到,此套接字未关闭,以及SocketInputStream

我们应该如何正常使用ThreadSafeConnectionManager - 它应该只创建一次吗?如果是这样,如何正确关闭这些套接字?

1 个答案:

答案 0 :(得分:7)

  

如果我关闭此管理器 - 所有连接都将关闭。   如果我使用SingleClientConnectionManager,那将是合适的,但我   别。我是对的吗?

每个不同的HTTP服务应该只使用一个连接管理器实例。你真的不需要关闭它,但你可能想要从池中驱逐已经闲置超过给定时间段的连接,如下所述:

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

  

虽然(甚至在consumeContent之后)socketInputStream里面   那些getContent()流没有关闭,以及socket。是吗   坏?

不,不是。如果底层连接处于一致状态,则它仍然可以保持活动状态。但是,一个 必须 关闭内容流,以确保将该连接释放回连接管理器。

  

我们应该如何正常使用ThreadSafeConnectionManager -   它应该只创建一次吗?如果是这样,如何正确关闭   那些插座是否有?

是的,它应该只创建一次。但是,您必须确保通过关闭响应内容流将连接正确释放回管理器。您可能还希望在一段时间不活动后主动驱逐池中的连接。

最后,请注意您的应用程序的其他组件也可能泄漏文件描述符。罪魁祸首可能不一定是HttpClient的连接管理器。