• 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;
                }
            }
    

      

  • 相关阅读:
    mysql函数基本使用
    django form 组件源码解析
    jwt
    python数据类型 ——bytes 和 bytearray
    汇编基础四 --函数调用与堆栈平衡
    汇编基础之三 -- 汇编指令
    汇编基础之二 -- 寄存器和内存堆栈
    汇编基础之一 -- 位运算和四则运算的实现
    存储过程中的设置语句含义
    (转载)SQL去除回车符,换行符,空格和水平制表符
  • 原文地址:https://www.cnblogs.com/achengmu/p/15180410.html
Copyright © 2020-2023  润新知