记一次服务器大量CLOSE_WAIT的故障处理过程

in #closewait8 years ago (edited)
症状
  • CPU正常
  • 内存正常
  • 网络出现大量CLOSE_WAIT连接状态
  • 应用日志文件无异常

其中用到的网络连接统计命令:

netstat -apn|grep 443|awk '{if($2 > 1) print $1"\t"$2"\t"$3"\t"$4"\t"$5"\t"$6"\t"$7}'|sort -k 2

服务器上的应用程序是用Java编写,使用了tomcat,使用命令

jcmd 20165 Thread.print > threads.log

导出线程堆栈情况发现大量的WAITING状态线程,线程总数约200个,大部分线程调用堆栈都包含了httpclient包的调用,查看了对应的Java代码,发现如下写法:

HttpResponse res = httpClient.execute(post);
if(res.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
    //读取响应内容
    resp = EntityUtils.toString(res.getEntity(), "UTF-8");
}
return resp;
推测

如果响应的res状态码不是200,resp对应的输入流是没有正常读取释放的;如果不正常释放,httpclient维护的连接池及单个主机连接数是会被消耗光的,最终出现新的http请求会一直阻塞,进而消耗掉tomcat所有的工作线程(默认工作线程200个左右与thread.log统计一致)。

问题复现

解决方案

if条件后增加else处理,使用方法org.apache.http.util.EntityUtils#consumeQuietly对服务端返回的输入流进行读取消耗。

参考资料

服务器TIME_WAIT和CLOSE_WAIT详解和解决办法

Coin Marketplace

STEEM 0.05
TRX 0.32
JST 0.082
BTC 65704.64
ETH 1794.49
USDT 1.00
SBD 0.43