close_wait状态出现的原因是被动关闭方未关闭socket造成,基本都是代码原因,比如HttpClient没有关闭连接、数据库连接没有关闭。
CLOSED 表示socket连接没被使用。
LISTENING 表示正在监听进入的连接。
SYN_SENT 表示正在试着建立连接。
SYN_RECEIVED 进行连接初始同步。
ESTABLISHED 表示连接已被建立。
CLOSE_WAIT表示远程计算器关闭连接,正在等待socket连接的关闭。
FIN_WAIT_1 表示socket连接关闭,正在关闭连接。
CLOSING先关闭本地socket连接,然后关闭远程socket连接,最后等待确认信息。
LAST_ACK 远程计算器关闭后,等待确认信号。
FIN_WAIT_2 socket连接关闭后,等待来自远程计算器的关闭信号。
TIME_WAIT 连接关闭后,等待远程计算器关闭重发。
查看各状态连接总数
netstat -natp|awk '{print $6}'|sort|uniq -c
查看CLOSE_WAIT连接
netstat -antp | grep CLOSE_WAIT
经过排查代码发现是http连接关闭只调用response.close();httpPost.releaseConnection();只会归还连接并不会关闭连接,关闭还要调用((SimpleHttpConnectionManager)client.getHttpConnectionManager()).closeIdleConnections(0);
改造后发现虽然CLOSE_WAIT没了,但是有大量的TIME_WAIT导致端口(每台机器只有6万多个端口可用)被占满了,TIME_WAIT连接达到了6万多的上限之后网络没有可用的端口而导致网络连接异常Address already in use。主动关闭socket的一方最终为time_wait,被动关闭的则为close_wait;time_wait在2msl时间后才会超时释放,这是为了让可能未到达的报文超时被抛弃避免影响后续重用该端口的连接。如果短时间内大量建立和关闭http连接会产生大量TIME_WAIT的连接占用端口无法及时释放而影响网络。正确使用应该建立http连接池而非每次都建立连接。临时解决办法就是先限制连接数量并开启重用,
打开sysctl.conf文件,修改以下几个参数:
vi /etc/sysctl.conf增加以下配置
#控制TIME_WAIT的最大数量
net.ipv4.tcp_max_tw_buckets=40000
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_timestamps = 1
然后让配置生效执行 sysctl -p /etc/sysctl.conf
http连接还是应该复用,不应该每次都关闭closeIdleConnections(0),http工具类自带连接池,应该使用起来,回退修改后升级http的jar包。 业务代码也做了些优化解决。