使用httpclient时候,出现“Too many open files”问题

原文https://www.cnblogs.com/yzlpersonal/p/5127240.html

前段时间服务器运行两天就宕机,报错Too many open files。经排查句柄数过大,经过查阅资料发现是httpclient参数设置不严谨造成,也是收益这篇文章。现贴在这里,供更多的人查阅。

推荐使用第一种设置参数的方法。设置服务器句柄数无异于自欺欺人。

下面是原文:

最近接触的sendHttpPostRequest的问题比较多,近期碰到了关于 "java.net.SocketException: Too many open files" 的问题

异常信息如下:

复制代码

ERROR | 2016-01-12 03:19:36.642 | ERROR | IREAD | [Exception]exception stack info | com.huawei.bme.commons.util.debug.DebugLogImpl.doLog(DebugLogImpl.java:480)
java.net.SocketException: Too many open files
    at java.net.Socket.createImpl(Socket.java:397)
    at java.net.Socket.getImpl(Socket.java:460)
    at java.net.Socket.bind(Socket.java:577)
    at sun.reflect.GeneratedMethodAccessor26.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.commons.httpclient.protocol.ReflectionSocketFactory.createSocket(ReflectionSocketFactory.java:139)
    at org.apache.commons.httpclient.protocol.DefaultProtocolSocketFactory.createSocket(DefaultProtocolSocketFactory.java:125)
    at org.apache.commons.httpclient.HttpConnection.open(HttpConnection.java:707)
    at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$HttpConnectionAdapter.open(MultiThreadedHttpConnectionManager.java:1361)
    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)
    at com.huawei.iread.duibaintf.duiba.sns.SNSServer.sendPostRequestWithCode(SNSServer.java:296)
    at com.huawei.iread.duibaintf.duiba.sns.SNSEngine.sendPostRequestWithCode(SNSEngine.java:92)
    at com.huawei.iread.duibaintf.duiba.duibamall.GetDuibaExchangeResultNotifyImpl.getDuibaExchangeResultNotify(GetDuibaExchangeResultNotifyImpl.java:91)

复制代码

其实也就是因为 sendPostRequestWithCode 和 getDuibaExchangeResultNotify 方法调用了 HttpClient.executeMethod 引起的。


 

查找linux服务器中open files文件数,发现好多是下面的情况,意思是socket资源泄漏,进程使用的sock未关闭:

复制代码

COMMAND     PID       USER   FD      TYPE             DEVICE   SIZE/OFF       NODE NAME
java      27185      duiba  100u     sock                0,7      0t0   92280355 can't identify protocol
java      27185      duiba  101u     sock                0,7      0t0   92282035 can't identify protocol
java      27185      duiba  102u     sock                0,7      0t0   92280901 can't identify protocol
java      27185      duiba  103u     sock                0,7      0t0   92282036 can't identify protocol
java      27185      duiba  104u     sock                0,7      0t0   92280389 can't identify protocol
java      27185      duiba  105u     sock                0,7      0t0   92280390 can't identify protocol
java      27185      duiba  106u     sock                0,7      0t0   92280391 can't identify protocol
java      27185      duiba  107u     sock                0,7      0t0   92280392 can't identify protocol

复制代码


Java源代码中是这样写的:

复制代码

try{
    httpMethod = new PostMethod(url)
    // 设置header信息,传输XML格式的
    httpMethod.setRequestHeader(CONTENT_TYPE_NAME, CONTENT_TYPE_VALUE_XML_UTF_8);
    httpMethod.setRequestEntity(entity);

    HttpClient httpClient = new HttpClient(new MultiThreadedHttpConnectionManager());//使用连接池技术创建
    httpClient.executeMethod(httpMethod);
}catch{...}
finally{

    if (null != httpMethod)
    {
        httpMethod.releaseConnection();//释放资源
    }

}

复制代码

从上面看,最后, httpMethod.releaseConnection();//释放资源。实际上,HttpClient建立Socket时 ,post.releaseConnection()并没有真正关闭连接,而是将该连接提交给 MultiThreadedHttpConnectionManager,等待复用。而http的连接是等待timeout才会自动断开的,所以,当用完系统的句柄后,自然会报Too many open files。

所以,应该添加下面的代码进行释放socket:

复制代码

try{
    httpMethod = new PostMethod(url)
    // 设置header信息,传输XML格式的
    httpMethod.setRequestHeader(CONTENT_TYPE_NAME, CONTENT_TYPE_VALUE_XML_UTF_8);
    httpMethod.setRequestEntity(entity);
    //请求头信息中添加关闭连接
    httpMethod.addRequestHeader("Connection", "close");

    HttpClient httpClient = new HttpClient(new MultiThreadedHttpConnectionManager());//使用连接池技术创建
    httpClient.executeMethod(httpMethod);
    //连发三次机制                           
    httpClient.getParams().setBooleanParameter("http.protocol.expect-continue", false);
}catch{...}
finally{
    if (null != httpMethod)
    {
        httpMethod.releaseConnection();//释放资源
    }

}  

复制代码


还有一种说法:

linux的文件打开数超过了默认的1024个文件,具体查看linux下面的文件打开最大值的命令ulimit -a,出现信息如下:

复制代码

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 69631
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 69631
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimite

复制代码

其中open files                      (-n) 1024 默认为1024,
有说解决方法是加大文件打开的最大值,ulimit -n 8192
但是由于Httpclient引起的。当并发访问量过大的时候,这个方法只是治标不治本的。所有还是解决Httpclient远程请求所造成Socket没有释放,使用上面的方法较好。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值