HttpClient的 java.net.SocketException: Too many open files

今天在维护一个老项目的时候发现,错误:

java.net.SocketException: Too many open files
	at java.net.Socket.createImpl(Socket.java:460)
	at java.net.Socket.getImpl(Socket.java:520)
	at java.net.Socket.bind(Socket.java:644)
	at sun.security.ssl.BaseSSLSocketImpl.bind(BaseSSLSocketImpl.java:124)
	at sun.security.ssl.SSLSocketImpl.bind(SSLSocketImpl.java:65)
	at sun.security.ssl.SSLSocketImpl.<init>(SSLSocketImpl.java:468)
	at sun.security.ssl.SSLSocketFactoryImpl.createSocket(SSLSocketFactoryImpl.java:153)
	at org.apache.commons.httpclient.protocol.SSLProtocolSocketFactory.createSocket(SSLProtocolSocketFactory.java:82)
	at org.apache.commons.httpclient.protocol.SSLProtocolSocketFactory.createSocket(SSLProtocolSocketFactory.java:127)
	at org.apache.commons.httpclient.HttpConnection.open(HttpConnection.java:707)
	at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:387)
	at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
	at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
	at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)

  

大致意思是,资源未释放。

代码用的是httpClient,在finally中也关比了资源

 HttpClient client = new HttpClient();
try{
   PostMethod postMethod = new PostMethod(url);
    ......
   // 执行postMethod
   int statusCode = client.executeMethod(postMethod);
}cache(Exception e){

}finally{
   if (postMethod != null) {
                postMethod.releaseConnection();
                postMethod = null;
            }
}

  

后来找度娘了解下:

HttpClient在method.releaseConnection()后并没有把链接关闭,这个方法只是将链接返回给connection manager。

  

所以,我的:postMethod.releaseConnection(); 并没有把链接关闭掉。

如果使用HttpClient client = new HttpClient()实例化一个HttpClient connection manager默认实现是使用SimpleHttpConnectionManager。SimpleHttpConnectionManager有个构造函数如下 

/** 
 * The connection manager created with this constructor will try to keep the  
 * connection open (alive) between consecutive requests if the alwaysClose  
 * parameter is set to <tt>false</tt>. Otherwise the connection manager will  
 * always close connections upon release. 
 *  
 * @param alwaysClose if set <tt>true</tt>, the connection manager will always 
 *    close connections upon release. 
 */  
public SimpleHttpConnectionManager(boolean alwaysClose) {  
    super();  
    this.alwaysClose = alwaysClose;  
}

  

那么在finally中,就需要关闭他:

 finally {
            if (postMethod != null) {
                postMethod.releaseConnection();
                postMethod = null;
            }
            if (client != null) {
                ((SimpleHttpConnectionManager) client.getHttpConnectionManager()).shutdown();
                client = null;
            }
        }

  

同时还搜索到了这个2个参数:

client = new HttpClient();
 //添加关闭连接优化Too many open files异常

 client.getParams().setBooleanParameter( "http.protocol.expect-continue" , false ); 

//请求头信息中添加关闭连接优化Too many open files异常

method.addRequestHeader("Connection", "close");

  

搜索了一些文档,没有发现对这两个参数细致的解释,只能不求甚解了。测试后也确实没有文件过多的异常了

大致可以这样写:

      HttpClient client = new HttpClient();
      //增加的
      client.getParams().setBooleanParameter("http.protocol.expect-continue", false);

        //超时时间
         client.setTimeout(90 * 1000);        
        MethodResult response = null;
        PostMethod postMethod = null;
        try {
            postMethod = new PostMethod(url);
            postMethod.setRequestHeader("Content-Type", "application/json;charset=utf-8");
           .......
    
           //增加的
            postMethod.addRequestHeader("Connection", "close");

            // 执行postMethod
            int statusCode = client.executeMethod(postMethod);
             ......
        } catch (HttpException e) {
            logger.error("发生致命的异常,可能是协议不对或者返回的内容有问题", e);
            e.printStackTrace();
            response.setBody("-201");
        } catch (IOException e) {
            logger.error("发生网络异常", e);
            e.printStackTrace();
            response.setBody("-200");
        } finally {
            if (postMethod != null) {
                postMethod.releaseConnection();
                postMethod = null;
            }
            //增加的
            if (client != null) {
                ((SimpleHttpConnectionManager) client.getHttpConnectionManager()).shutdown();
                client = null;
            }
        }

  

原文地址:https://www.cnblogs.com/achengmu/p/15180410.html