zoukankan      html  css  js  c++  java
  • Linux服务器 大量的CLOSE_WAIT、TIME_WAIT解决办法

    http://itindex.net/detail/50213-%E6%9C%8D%E5%8A%A1%E5%99%A8-time_wait-close_wait

    http://itindex.net/detail/47690-time_wait-tcp-%E6%80%A7%E8%83%BD

    http://itindex.net/detail/50143-time_wait-socket-time_wait

    http://itindex.net/detail/53528-nginx-time_wait

    http://itindex.net/detail/53493-tcp-ip-time_wait

    系统上线之后,通过如下语句查看服务器时,发现有不少TIME_WAIT和CLOSE_WAIT。

      netstat -an | awk '{print $6}' | sort | uniq -c | sort -rn

    netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

    打印显示如下:

    TIME_WAIT 297
    ESTABLISHED 53
    CLOSE_WAIT 5
    

         TIME_WAIT:表示主动关闭,通过优化系统内核参数可容易解决。

         CLOSE_WAIT:表示被动关闭,需要从程序本身出发。

         ESTABLISHED:表示正在通信

        通过上网了解,总结如下:

    一、TIME_WAIT(通过优化系统内核参数可容易解决)

           TIME_WAIT是主动关闭连接的一方保持的状态,对于服务器来说它本身就是“客户端”,在完成一个爬取任务之后,它就会发起主动关闭连接,从而进入TIME_WAIT的状态,然后在保持这个状态2MSL(max segment lifetime)时间之后,彻底关闭回收资源。为什么要这么做?明明就已经主动关闭连接了为啥还要保持资源一段时间呢?这个是TCP/IP的设计者规定的,主要出于以下两个方面的考虑:

            1.防止上一次连接中的包,迷路后重新出现,影响新连接(经过2MSL,上一次连接中所有的重复包都会消失)

            2.可靠的关闭TCP连接。在主动关闭方发送的最后一个 ack(fin) ,有可能丢失,这时被动方会重新发fin, 如果这时主动方处于 CLOSED 状态 ,就会响应 rst 而不是 ack。所以主动方要处于 TIME_WAIT 状态,而不能是 CLOSED 。另外这么设计TIME_WAIT 会定时的回收资源,并不会占用很大资源的,除非短时间内接受大量请求或者受到攻击。

            解决方案很简单,通过修改/etc/sysctl.conf文件,服务器能够快速回收和重用那些TIME_WAIT的资源  

            

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

            生效,如下命令        

    /sbin/sysctl -p

               

    二、CLOSE_WAIT(需要从程序本身出发)

           TCP状态转移要点

           TCP协议规定,对于已经建立的连接,网络双方要进行四次握手才能成功断开连接,如果缺少了其中某个步骤,将会使连接处于假死状态,连接本身占用的资源不会被释放。网络服务器程序要同时管理大量连接,所以很有必要保证无用连接完全断开,否则大量僵死的连接会浪费许多服务器资源.

            客户端TCP状态迁移:        

    CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
         
             服务器TCP状态迁移:      
    CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED

           当客户端开始连接时,服务器还处于LISTENING,客户端发一个SYN包后,他就处于SYN_SENT状态,服务器就处于SYS收到状态,然后互相确认进入连接状态ESTABLISHED。

           TIME_WAIT状态可以通过优化服务器参数得到解决,因为发生TIME_WAIT的情况是服务器自己可控的,要么就是对方连接的异常,要么就是自己没有迅速回收资源,总之不是由于自己程序错误导致的。

            但是CLOSE_WAIT就不一样了,如果一直保持在CLOSE_WAIT状态,那么只有一种情况,就是在对方关闭连接之后服务器程序自己没有进一步发出ack信号。换句话说,就是在对方连接关闭之后,程序里没有检测到,或者程序压根就忘记了这个时候需要关闭连接,于是这个资源就一直被程序占着。个人觉得这种情况,通过服务器内核参数也没办法解决,服务器对于程序抢占的资源没有主动回收的权利,除非终止程序运行。

           什么情况下,连接处于CLOSE_WAIT状态呢?

           答案一:在被动关闭连接情况下,在已经接收到FIN,但是还没有发送自己的FIN的时刻,连接处于CLOSE_WAIT状态。通常来讲,CLOSE_WAIT状态的持续时间应该很短,正如SYN_RCVD状态。但是在一些特殊情况下,就会出现连接长时间处于CLOSE_WAIT状态的情况。

            答案二:出现大量close_wait的现象,主要原因是某种情况下对方关闭了socket链接,但是我方忙与读或者写,没有关闭连接。代码需要判断socket,一旦读到0,断开连接,read返回负,检查一下errno,如果不是AGAIN,就断开连接。

    -----------------------------------------------------------------------------------------------

    http://www.cnblogs.com/sunxucool/p/3449068.html

    http://my.oschina.net/foxidea/blog/91431?fromerr=KjV5Lqr3

    发现存在大量TIME_WAIT状态的连接
    tcp        0      0 127.0.0.1:3306              127.0.0.1:41378             TIME_WAIT
    tcp        0      0 127.0.0.1:3306              127.0.0.1:41379             TIME_WAIT
    tcp        0      0 127.0.0.1:3306              127.0.0.1:39352             TIME_WAIT
    tcp        0      0 127.0.0.1:3306              127.0.0.1:39350             TIME_WAIT
    tcp        0      0 127.0.0.1:3306              127.0.0.1:35763             TIME_WAIT
    tcp        0      0 127.0.0.1:3306              127.0.0.1:39372             TIME_WAIT
    tcp        0      0 127.0.0.1:3306              127.0.0.1:39373             TIME_WAIT
    tcp        0      0 127.0.0.1:3306              127.0.0.1:41176             TIME_WAIT
     
     
     
    通过调整内核参数解决
    vi /etc/sysctl.conf


    编辑文件,加入以下内容:
    net.ipv4.tcp_syncookies = 1
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_tw_recycle = 1
    net.ipv4.tcp_fin_timeout = 30
     
    然后执行/sbin/sysctl -p让参数生效。
     
    net.ipv4.tcp_syncookies = 1表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;


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


    net.ipv4.tcp_tw_recycle = 1表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。


    net.ipv4.tcp_fin_timeout修改系統默认的TIMEOUT时间
     
    修改之后,再用命令查看TIME_WAIT连接数
    netstat -ae|grep “TIME_WAIT” |wc –l


       发现大量的TIME_WAIT 已不存在,mysql进程的占用率很快就降下来的,网站访问正常。
     不过很多时候,出现大量的TIME_WAIT状态的连接,往往是因为网站程序代码中没有使用mysql.colse(),才导致大量的mysql  TIME_WAIT.
     
      如果你的服务器是Windows平台,可以修改下面的注册表键值:
    [HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesTcpipParameters]
    "TcpTimedWaitDelay"=dword:0000001e


    此值是TIME_WAIT状态的最长时间。缺省为240秒,最低为30秒,最高为300秒。建议为30秒。
     
    注释:

    1,TCP结束的过程如下:


    Server                             Client


    -------------- FIN -------------->  server: fin_wait_1


    <------------- ACK --------------- client: close_wait  server:fin_wait_2


    <------------- FIN  --------------- client发出fin之后就关闭


    -------------- ACK ------------->  server发出ack后进入time_wait状态


    Time_Wait的默认时间是2倍的MLS,就是240秒钟。MLS是TCP片在网上的最长存活时间。
    TIME_Wait的主要作用是保证关闭的TCP端口不立即被使用。因为当网络存在延迟时,可能当某个端口被关闭后,网络中还有一些重传的TCP片在发向这个端口,如果这个端口立即建立新的TCP连接,则可能会有影响。所以使用2倍的MSL时间来限制这个端口立即被使用。


    现在的问题在于,4分钟的时间有点长。
    因此,Time_wait的影响,我想,首先每个TCP连接都各自有个数据结构,叫TCP Control Block.Time_wait的时候这个数据结构没有被释放。所以当有太多的TCP连接时,内存可能会被占用很多。
     
     
     
    2,To ValorZ:TIME_WAIT状态也称为2MSL等待状态,而不是2MLS,笔误吧!


    每个TCP报文在网络内的最长时间,就称为MSL(Maximum Segment Lifetime),它的作用和IP数据包的TTL类似。


    RFC793指出,MSL的值是2分钟,但是在实际的实现中,常用的值有以下三种:30秒,1分钟,2分钟。


    注意一个问题,进入TIME_WAIT状态的一般情况下是客户端,大多数服务器端一般执行被动关闭,不会进入TIME_WAIT状态,当在服务器端关闭某个服务再重新启动时,它是会进入TIME_WAIT状态的。


    举例:
    1.客户端连接服务器的80服务,这时客户端会启用一个本地的端口访问服务器的80,访问完成后关闭此连接,立刻再次访问服务器的80,这时客户端会启用另一个本地的端口,而不是刚才使用的那个本地端口。原因就是刚才的那个连接还处于TIME_WAIT状态。

    2.客户端连接服务器的80服务,这时服务器关闭80端口,立即再次重启80端口的服务,这时可能不会成功启动,原因也是服务器的连接还处于TIME_WAIT状态。

    windows

    TcpTimedWaitDelay和MaxUserPort设置
    描述:确定 TCP/IP 可释放已关闭连接并重用其资源前,必须经过的时间。
    关闭和释放之间的此时间间隔通称 TIME_WAIT 状态或两倍最大段生命周期(2MSL)状态。
    此时间期间,重新打开到客户机和服务器的连接的成本少于建立新连接。
    减少此条目的值允许 TCP/IP 更快地释放已关闭的连接,为新连接提供更多资源。如果运行的应用程序需要快速释放和创建新连接,而且由于 TIME_WAIT 中存在很多连接,导致低吞吐量,则调整此参数。
    如何查看或设置: 使用 regedit 命令访问 HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/ Services/TCPIP/Parameters 注册表子键并创建名为 TcpTimedWaitDelay 的新 REG_DWORD 值。
    将此值设置为十进制 30,其为十六进制 0x0000001e。
    该值将等待时间设置为 30 秒。
    停止并重新启动系统。 缺省值:0xF0,它将等待时间设置为 240 秒(4 分钟)。
    建议值:最小值为 0x1E,它将等待时间设置为 30 秒。
    MaxUserPort 描述:确定在应用程序从系统请求可用用户端口时,TCP/IP 可指定的最高端口号。
    如何查看或设置: 使用 regedit 命令访问 HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/ Services/TCPIP/Parameters 注册表子键并创建名为 MaxUserPort 的新 REG_DWORD 值。
    停止并重新启动系统。
    缺省值:无 建议值:至少十进制 32768。
    注:当在 Windows NT 或 Windows 2000 操作系统上调整 WebSphere Application Server 时,同时使用这两个参数。
    希望本站的知识能给您的工作、学习和生活带来方便和乐趣!  
     
    --------------------------------------------------------------------------------------------------------------
    server端tcp连接状态大量TIME_WAIT解决方法:
    在脚步中添加:
    /*保证迭代结束后关闭所有的链接。相应的函数放于下面两个函数之间,迭代后都会关闭连接。
    web_set_sockets_option("SHUTDOWN_MODE","ABRUPT");//相当于迭代重置,初始化
    ............
    web_set_sockets_option("CLOSE_KEEPALIVE_CONNECTIONS","1"); //关闭连接
    */
    web_set_sockets_option("SHUTDOWN_MODE","ABRUPT");
    web_set_sockets_option("SO_REUSE_ADDRESS","1");//端口复用
    web_set_sockets_option("OVERLAPPED_SEND","0");//禁用TTFB细分,问题即可解决,但是TTFB细分图将不能再使用.
  • 相关阅读:
    SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因
    微软BI 之SSIS 系列
    微软BI 之SSIS 系列
    微软BI 之SSIS 系列
    微软BI 之SSIS 系列
    微软BI 之SSIS 系列
    微软BI 之SSAS 系列
    微软BI 之SSRS 系列
    微软BI 之SSRS 系列
    配置 SQL Server Email 发送以及 Job 的 Notification通知功能
  • 原文地址:https://www.cnblogs.com/shengs/p/4495998.html
Copyright © 2011-2022 走看看