服务器http连接出现大量TIME_WAIT问题的解决方法
最近用户的tomcat服务器上出现大量TIME_WAIT 状态的连接,导致后面的连接进不去,出现服务没有响应的情况。
首先使用命令查看当前的各种状态的数量:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
执行后,一般结果如下:
TIME_WAIT 8
CLOSE_WAIT 323
SYN_SENT 1
ESTABLISHED 6171
其中常用的三个状态是:
ESTABLISHED 表示正在通信
TIME_WAIT 表示主动关闭
CLOSE_WAIT 表示被动关闭
1.出现TIME_WAIT的原因
TCP建立一个连接至少需要交换三个分组,也因此称之为TCP的三路握手(three-way handshake),然而在TCP终止连接时,由于双方都需要发送一个FIN分节给对端确认,因此TCP终止连接一般是需要交换四个分节。具体来看:
1) 应用进程(active close)首先调用close,于是导致TCP发送一个FIN分节,表示数据已分送完毕,请求关闭套接字。
2) 另一端应用进程(passive close)接受收到FIN,并由该端的TCP确认(确认的过程是TCP发送ACK分节给对端套接字)。FIN的接受也作为文件结束符传递给上层应用进程。这里的文件结束符并非应用进程的EOF,在TCP字节流中,EOF的读或写通过收发一个特殊的FIN分节来实现。
3) 另端(passive close)应用进程在接受到文件束符后,会调用close关闭它的套接字,这导致该端的TCP也发送了一个FIN分节。
4) 主动关闭端(active close)接受到这个FIN后,TCP对它进行确认。(TCP发送ACK分节,值得注意的是主动关闭端在未接受到FIN之前,它的状态就是TIME_WAIT)。
TIME_OUT状态的存在的意义
从图中,很清晰的看到TIME_WAIT状态发生在了active close 端,产生的时间点是发送ACK K+1 分节之后,原因是防止ACK分节在网络中丢失(lost),此时passive close进入LAST_ACK状态,意为等待ACK分节,如果此时ACK分节真的丢失了(passive close端的LAST_ACK超时),那么passive close端将会再次发送一个FIN K分节给对端。这就是为什么在图中,出现两次FIN的分节。
对于基于TCP的HTTP协议,关闭TCP连接的是Server端,这样,Server端会进入TIME_WAIT状态,可 想而知,对于访 问量大的Web Server,会存在大量的TIME_WAIT状态,假如server一秒钟接收1000个请求,那么就会积压 240*1000=240,000个 TIME_WAIT的记录,维护这些状态给Server带来负担。当然现代操作系统都会用快速的查找算法来管理这些 TIME_WAIT,所以对于新的 TCP连接请求,判断是否hit中一个TIME_WAIT不会太费时间,但是有这么多状态要维护总是不好。
2.解决出现大量TIME_WAIT情况的方法
对/etc/sysctl.conf文件进行修改:
#对于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃,不应该大于255,默认值是5,对应于180秒左右时间 net.ipv4.tcp_syn_retries=2 #net.ipv4.tcp_synack_retries=2 #表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为300秒 net.ipv4.tcp_keepalive_time=1200 net.ipv4.tcp_orphan_retries=3 #表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间 net.ipv4.tcp_fin_timeout=30 #表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。 net.ipv4.tcp_max_syn_backlog = 4096 #表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭 net.ipv4.tcp_syncookies = 1 #表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭 net.ipv4.tcp_tw_reuse = 1 #表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭 net.ipv4.tcp_tw_recycle = 1 ##减少超时前的探测次数 net.ipv4.tcp_keepalive_probes=5 ##优化网络设备接收队列 net.core.netdev_max_backlog=3000
修改完之后,执行:
/sbin/sysctl -p
这样参数就能生效了。
上面修改的参数里面,最主要的是4个参数:
net.ipv4.tcp_tw_reuse
net.ipv4.tcp_tw_recycle
net.ipv4.tcp_keepalive_*
上一篇: 视图--虚拟表
下一篇: php exception错误处理
推荐阅读
-
Centos7.4服务器安装apache及安装过程出现的问题解决方法
-
win7系统连接远程桌面出现闪退问题的两种解决方法详细教程
-
Linux服务器nginx访问日志里出现大量http 400错误的请求分析
-
web服务器程序运行出现乱码问题的解决方法
-
Winxp IIS5.1出现HTTP500内部服务器错误的解决方法
-
与虚拟机Oracle连接出现ora-12154问题的解决方法
-
关于Oracle本地连接出现与监听有关的问题的解决方法探讨
-
Linux连接windows的ftp unzip出现问题的解决方法
-
苹果Mac无法连接wifi怎么办 苹果Mac出现wifi连接问题的解决方法
-
WebSocket部署到服务器出现连接失败问题的分析与解决