zoukankan      html  css  js  c++  java
  • TIME_WAIT和CLOSE_WAIT

    先看下三次握手四次挥手的状态变化:

    0_13110767960diZ

    通常会遇到下面两种情况:

    • 服务器保持了大量TIME_WAIT状态
    • 服务器保持了大量CLOSE_WAIT状态

    因为linux分配给一个用户的文件句柄是有限的,而TIME_WAIT和CLOSE_WAIT两种状态如果一直被保持,那么意味着对应数目的通道就一直被占着,而且是“占着茅坑不使劲”,一旦达到句柄数上限,新的请求就无法被处理了,接着就是大量Too Many Open Files异常。

    关于TIME_WAIT

    这种情况比较常见,一些爬虫服务器或者WEB服务器(如果网管在安装的时候没有做内核参数优化的话)上经常会遇到这个问题,这个问题是怎么产生的呢?

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

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

    解决思路就是让服务器能够快速回收和重用那些TIME_WAIT的资源。

    #对于一个新建连接,内核要发送多少个 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

    上面的参数中:

    • net.ipv4.tcp_tw_reuse和net.ipv4.tcp_tw_recycle的开启都是为了回收处于TIME_WAIT状态的资源。
    • net.ipv4.tcp_fin_timeout这个时间可以减少在异常情况下服务器从FIN-WAIT-2转到TIME_WAIT的时间。
    • net.ipv4.tcp_keepalive_*一系列参数,是用来设置服务器检测连接存活的相关配置。

    关于CLOSE_WAIT

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

    举个例子说明CLOSE_WAIT是怎么发生的:服务器A是一台爬虫服务器,它使用简单的HttpClient去请求资源服务器B上面的apache获取文件资源,正常情况下,如果请求成功,那么在抓取完 资源后,服务器A会主动发出关闭连接的请求,这个时候就是主动关闭连接,服务器A的连接状态我们可以看到是TIME_WAIT。如果一旦发生异常呢?假设 请求的资源服务器B上并不存在,那么这个时候就会由服务器B发出关闭连接的请求,服务器A就是被动的关闭了连接,如果服务器A被动关闭连接之后程序员忘了 让HttpClient释放连接,那就会造成CLOSE_WAIT的状态了。

    一旦遇到了大量CLOSE_WAIT,解决办法只有一个:查代码。

    ##########################

  • 相关阅读:
    mysql BETWEEN操作符 语法
    mysql IN操作符 语法
    mysql LIKE通配符 语法
    mysql TOP语句 语法
    mysql DELETE语句 语法
    mysql Update语句 语法
    mysql INSERT语句 语法
    mysql ORDER BY语句 语法
    mysql OR运算符 语法
    mysql AND运算符 语法
  • 原文地址:https://www.cnblogs.com/amunote/p/10347319.html
Copyright © 2011-2022 走看看