天天看点

解决Linux服务器中TCP的FIN_WAIT2,CLOSE_WAIT状态连接过多的问题问题现象原因分析解决方法

问题现象

Linux系统服务器中FIN_WAIT2,CLOSE_WAIT状态的TCP链接过多,服务不能及时响应。

通过命令

netstat –ant|grep FIN_WAIT2|wc –l

查看连接数,发现值很大,这点不正常。

原因分析

  • 在HTTP服务中,Server由于某种原因会主动关闭连接,例如KEEPALIVE超时的情况下,作为主动关闭连接的Server就会进入FIN_WAIT2状态。
  • 在TCP/IP协议栈中,存在半连接的概念,FIN_WAIT2状态不算超时(不像TIME_WAIT状态),如果Client不关闭,FIN_WAIT2状态将保持到系统重启,越来越多的FIN_WAIT2状态会致使内核Crash。
  • 建议调小

    net.ipv4.tcp_fin_timeout

    参数的值,以便加快系统关闭处于

    FIN_WAIT2

    状态的TCP连接。

解决方法

修改各种有关TCP连接的参数。

/etc/sysctl.conf

是用来控制linux网络的配置文件,对于依赖网络的程序(如web服务器和cache服务器)非常重要。

  1. 修改

    /etc/sysctl.conf

    文件
vim /etc/sysctl.conf
           

修改或增加以下内容:

# 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭
net.ipv4.tcp_syncookies = 1

# 表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间
net.ipv4.tcp_fin_timeout = 30

# 表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数
net.ipv4.tcp_max_syn_backlog = 8192

# 表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。默认为180000,改为5000
net.ipv4.tcp_max_tw_buckets = 5000

# 表示TCP状态中TIME_WAIT的过期时间,默认情况是60秒
net.ipv4.tcp_tw_timeout = 10

# 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭
net.ipv4.tcp_tw_reuse = 1

# 表示开启TCP连接中TIME-WAIT sockets的快速回收,NAT环境可能导致DROP掉SYN包。默认为0,表示关闭
net.ipv4.tcp_tw_recycle = 1

# 表示TCP连接不再检查请求数据包的时间戳,默认为1,表示开启
net.ipv4.tcp_timestamps = 0

# 表示用于向外连接的端口范围。缺省情况下过窄:32768到61000,改为1024到65535
net.ipv4.ip_local_port_range = 1025 65500

# 表示防火墙最大跟踪的TCP连接数。请注意,此限制值要尽量小,以节省对内核内存的占用
net.ipv4.nf_conntrack_max = 102400

# 表示socket最大的读缓存,单位是byte
net.core.rmem_max = 16777216

# 表示socket最大的写缓存,单位是byte
net.core.wmem_max = 16777216

# 表示为每个TCP连接分配的读缓冲区内存大小,单位是byte
# 第一个数字表示,为TCP连接分配的最小内存,
# 第二个数字表示,为TCP连接分配的缺省内存,
# 第三个数字表示,为TCP连接分配的最大内存(net.core.rmem_max可覆盖该值)
net.ipv4.tcp_rmem = 4096 87380 16777216

# 表示为每个TCP连接分配的写缓冲区内存大小,单位是byte
# 第一个数字表示,为TCP连接分配的最小内存,
# 第二个数字表示,为TCP连接分配的缺省内存,
# 第三个数字表示,为TCP连接分配的最大内存(net.core.wmem_max可覆盖该值)
net.ipv4.tcp_wmem = 4096 65536 16777216

# 表示启用支持更大的TCP窗口。如果TCP窗口最大超过65535(64KB),必须设置该数值为1
net.ipv4.tcp_window_scaling = 1

# 表示启用转发应答,可以进行有选择应答(SACK)从而减少拥塞情况的发生
net.ipv4.tcp_sack = 1

# 表示当每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许发送到队列的数据包的最大数目,默认是1000。
# 对重负载服务器而言,该值太低,可调整到262144
net.core.netdev_max_backlog = 262144

# 表示一个tcp连接关闭后,把这个连接曾经有的参数,比如慢启动门限snd_sthresh、拥塞窗口snd_cwnd、srtt等信息保存到dst_entry中, 
# 只要dst_entry没有失效,下次新建立相同连接的时候就可以使用保存的参数来初始化这个连接。通常情况下是关闭的
net.ipv4.tcp_no_metrics_save = 1

# 表示系统同时发起的TCP连接数,一般默认值为128
net.core.somaxconn = 262144

# 用于设定系统中最多允许存在多少tcp套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,没有与用户文件句柄关联的tcp套接字符将立即被复位,同时给出警告信息。
# 这个限制只是为了防止简单的DoS工具。一般在系统内存比较充足的情况下,可以增大这个参数的赋值。
net.ipv4.tcp_max_orphans = 262144

# 用于设置内核放弃TCP连接之前向客户端发送SYN+ACK包的数量,为2表示最多发送2次
net.ipv4.tcp_synack_retries = 2

# 用于设置内核放弃建立连接之前发送SYN包的数量,为2表示最多发送2次
net.ipv4.tcp_syn_retries = 2

# 表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。
net.ipv4.tcp_keepalive_time = 1200
           
  1. 执行命令,使配置生效。如果系统没有错误提示,就表明系统对新的配置修改成功。
sysctl -p
           

对于Apache、Nginx等服务器,这些参数可以很好地减少TIME_WAIT套接字数量,但是对于Squid,效果却不大。此项参数

tcp_max_tw_buckets

可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。

继续阅读