精华内容
下载资源
问答
  • 来自:http://blog.csdn.net/shootyou/article/details/6622226昨天解决了一个HttpClient调用错误导致的服务器异常,具体过程如下:里头的分析过程有提到,通过查看服务器网络状态检测到服务器有大量的CLOSE_WAIT的...

    991f13fc66a292706476b0ce671b3fb0.png

    来自:http://blog.csdn.net/shootyou/article/details/6622226

    昨天解决了一个HttpClient调用错误导致的服务器异常,具体过程如下:

    里头的分析过程有提到,通过查看服务器网络状态检测到服务器有大量的CLOSE_WAIT的状态。

    在服务器的日常维护过程中,会经常用到下面的命令:netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

    它会显示例如下面的信息:

    TIME_WAIT 814

    CLOSE_WAIT 1

    FIN_WAIT1 1

    ESTABLISHED 634

    SYN_RECV 2

    LAST_ACK 1

    常用的三个状态是:ESTABLISHED 表示正在通信,TIME_WAIT 表示主动关闭,CLOSE_WAIT 表示被动关闭。

    具体每种状态什么意思,其实无需多说,看看下面这种图就明白了,注意这里提到的服务器应该是业务请求接受处理的一方:

    0_13110767960diZ.gif

    这么多状态不用都记住,只要了解到我上面提到的最常见的三种状态的意义就可以了。一般不到万不得已的情况也不会去查看网络状态,如果服务器出了异常,百分之八九十都是下面两种情况:

    1.服务器保持了大量TIME_WAIT状态

    2.服务器保持了大量CLOSE_WAIT状态

    因为linux分配给一个用户的文件句柄是有限的(可以参考:http://blog.csdn.net/shootyou/article/details/6579139),而TIME_WAIT和CLOSE_WAIT两种状态如果一直被保持,那么意味着对应数目的通道就一直被占着,而且是“占着茅坑不使劲”,一旦达到句柄数上限,新的请求就无法被处理了,接着就是大量Too Many Open Files异常,tomcat崩溃。。。

    面来讨论下这两种情况的处理方法,网上有很多资料把这两种情况的处理方法混为一谈,以为优化系统内核参数就可以解决问题,其实是不恰当的,优化系统内核参

    数解决TIME_WAIT可能很容易,但是应对CLOSE_WAIT的情况还是需要从程序本身出发。现在来分别说说这两种情况的处理方法:

    1.服务器保持了大量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 。另外这么设计TIME_WAIT

    会定时的回收资源,并不会占用很大资源的,除非短时间内接受大量请求或者受到***。

    关于MSL引用下面一段话:MSL 為

    一個 TCP Segment (某一塊 TCP 網路封包) 從來源送到目的之間可續存的時間 (也就是一個網路封包在網路上傳輸時能存活的時間),由

    於 RFC 793 TCP 傳輸協定是在 1981 年定義的,當時的網路速度不像現在的網際網路那樣發達,你可以想像你從瀏覽器輸入網址等到第一

    個 byte 出現要等 4 分鐘嗎?在現在的網路環境下幾乎不可能有這種事情發生,因此我們大可將 TIME_WAIT 狀態的續存時間大幅調低,好

    讓 連線埠 (Ports) 能更快空出來給其他連線使用。

    再引用网络资源的一段话:值

    得一说的是,对于基于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不会太费时间,但是有这么多状态要维护总是不好。

    HTTP协议1.1版规定default行为是Keep-Alive,也就是会重用TCP连接传输多个 request/response,一个主要原因就是发现了这个问题。

    也就是说HTTP的交互跟上面画的那个图是不一样的,关闭连接的不是客户端,而是服务器,所以web服务器也是会出现大量的TIME_WAIT的情况的。

    现在来说如何来解决这个问题。

    解决思路很简单,就是让服务器能够快速回收和重用那些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让参数生效。

    这里头主要注意到的是net.ipv4.tcp_tw_reuse

    net.ipv4.tcp_tw_recycle

    net.ipv4.tcp_fin_timeout

    net.ipv4.tcp_keepalive_*

    这几个参数。

    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_*一系列参数,是用来设置服务器检测连接存活的相关配置。

    2.服务器保持了大量CLOSE_WAIT状态

    休息一下,喘口气,一开始只是打算说说TIME_WAIT和CLOSE_WAIT的区别,没想到越挖越深,这也是写博客总结的好处,总可以有意外的收获。

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

    是CLOSE_WAIT就不一样了,从上面的图可以看出来,如果一直保持在CLOSE_WAIT状态,那么只有一种情况,就是在对方关闭连接之后服务器程

    序自己没有进一步发出ack信号。换句话说,就是在对方连接关闭之后,程序里没有检测到,或者程序压根就忘记了这个时候需要关闭连接,于是这个资源就一直

    被程序占着。个人觉得这种情况,通过服务器内核参数也没办法解决,服务器对于程序抢占的资源没有主动回收的权利,除非终止程序运行。

    在那边日志里头我举了个场景,来说明CLOSE_WAIT和TIME_WAIT的区别,这里重新描述一下:

    务器A是一台爬虫服务器,它使用简单的HttpClient去请求资源服务器B上面的apache获取文件资源,正常情况下,如果请求成功,那么在抓取完

    资源后,服务器A会主动发出关闭连接的请求,这个时候就是主动关闭连接,服务器A的连接状态我们可以看到是TIME_WAIT。如果一旦发生异常呢?假设

    请求的资源服务器B上并不存在,那么这个时候就会由服务器B发出关闭连接的请求,服务器A就是被动的关闭了连接,如果服务器A被动关闭连接之后程序员忘了

    让HttpClient释放连接,那就会造成CLOSE_WAIT的状态了。

    所以如果将大量CLOSE_WAIT的解决办法总结为一句话那就是:查代码。因为问题出在服务器程序里头啊。

    参考资料:

    展开全文
  • Linux服务器 大量的CLOSE_WAIT、TIME_WAIT解决办法 系统上线之后,通过如下语句查看服务器时,发现有不少TIME_WAIT和CLOSE_WAIT。 netstat -an | awk ‘{print KaTeX parse error: Expected 'EOF', got '}' at ...

    Linux服务器 大量的CLOSE_WAIT、TIME_WAIT解决办法
    系统上线之后,通过如下语句查看服务器时,发现有不少TIME_WAIT和CLOSE_WAIT。
    netstat -an | awk ‘{print KaTeX parse error: Expected 'EOF', got '}' at position 2: 6}̲' | sort | uniq…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_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]
    “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细分图将不能再使用.

    展开全文
  • 一个很特别的参数,影响关闭socket后的行为,是立即释放,还是进入TIME_WAIT状态并等 待一段时间(单位:秒)才释放。这个参数,在Socket中可以设置,在Mina2的IoService中也有setSoLinger设置。对于新bs3 框架的...

    一个很特别的参数,影响关闭socket后的行为,是立即释放,还是进入TIME_WAIT状态并等 待一段时间(单位:秒)才释放。这个参数,在Socket中可以设置,在Mina2的IoService中也有setSoLinger设置。对于新bs3 框架的Service4Mina2s组件,可以通过以下两种方法设置。

    1

    1

    取值:-1表示使用OS缺省参数,0表示立即释放,nSec表示等待n秒后释放。

    优雅关闭的几个步骤:1)shutdown(SEND);2)recv(EOF, 5s);3) closeSocket();4) TIME_WAIT

    参考:http://hi.baidu.com/xingfengsoft/blog/item/021b03ce872e0430b700c89d.html

    【转自文静】减少Linux服务器过多的TIME_WAIT (2009/08/24 22:45)

    TIME_WAIT状态的意义:

    客户端与服务器端建立TCP/IP连接后关闭SOCKET后,服务器端连接的端口状态为TIME_WAIT

    是不是所有执行主动关闭的socket都会进入TIME_WAIT状态呢?

    有没有什么情况使主动关闭的socket直接进入CLOSED状态呢?

    主动关闭的一方在发送最后一个 ack 后,就会进入 TIME_WAIT 状态 停留2MSL(max segment lifetime)时间,这个是TCP/IP必不可少的,也就是“解决”不了的。

    也就是TCP/IP设计者本来是这么设计的

    主要有两个原因

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

    2。可靠的关闭TCP连接。在主动关闭方发送的最后一个 ack(fin) ,有可能丢失,这时被动方会重新发

    fin, 如果这时主动方处于 CLOSED 状态 ,就会响应 rst 而不是 ack。所以主动方要处于 TIME_WAIT 状态,而不能是 CLOSED 。

    TIME_WAIT 并不会占用很大资源的,除非受到攻击。

    在Squid服务器中可输入如下命令:

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

    LAST_ACK 14

    SYN_RECV 348

    ESTABLISHED 70

    FIN_WAIT1 229

    FIN_WAIT2 30

    CLOSING 33

    TIME_WAIT 18122

    状态:描述

    CLOSED:无连接是活动的或正在进行

    LISTEN:服务器在等待进入呼叫

    SYN_RECV:一个连接请求已经到达,等待确认

    SYN_SENT:应用已经开始,打开一个连接

    ESTABLISHED:正常数据传输状态

    FIN_WAIT1:应用说它已经完成

    FIN_WAIT2:另一边已同意释放

    ITMED_WAIT:等待所有分组死掉

    CLOSING:两边同时尝试关闭

    TIME_WAIT:另一边已初始化一个释放

    LAST_ACK:等待所有分组死掉

    也就是说,这条命令可以把当前系统的网络连接状态分类汇总。

    下面解释一下为啥要这样写:

    一个简单的管道符连接了netstat和awk命令。

    ——————————————————————

    先来看看netstat:

    netstat -n

    Active Internet connections (w/o servers)

    Proto Recv-Q Send-Q Local Address Foreign Address State

    tcp 0 0 123.123.123.123:80 234.234.234.234:12345 TIME_WAIT

    你实际执行这条命令的时候,可能会得到成千上万条类似上面的记录,不过我们就拿其中的一条就足够了。

    ——————————————————————

    再来看看awk:

    /^tcp/

    滤出tcp开头的记录,屏蔽udp, socket等无关记录。

    state[]

    相当于定义了一个名叫state的数组

    NF

    表示记录的字段数,如上所示的记录,NF等于6

    $NF

    表示某个字段的值,如上所示的记录,$NF也就是$6,表示第6个字段的值,也就是TIME_WAIT

    state[$NF]

    表示数组元素的值,如上所示的记录,就是state[TIME_WAIT]状态的连接数

    ++state[$NF]

    表示把某个数加一,如上所示的记录,就是把state[TIME_WAIT]状态的连接数加一

    END

    表示在最后阶段要执行的命令

    for(key in state)

    遍历数组

    print key,”/t”,state[key]

    打印数组的键和值,中间用/t制表符分割,美化一下。

    如发现系统存在大量TIME_WAIT状态的连接,通过调整内核参数解决,

    vim /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 让参数生效。

    Linux下高并发的Squid服务器,TCP TIME_WAIT套接字数量经常达到两、三万,服务器很容易被拖死。通过修改Linux内核参数,可以减少Squid服务器的TIME_WAIT套接字数量。

    vi /etc/sysctl.conf

    增加以下几行:引用

    net.ipv4.tcp_fin_timeout = 30

    net.ipv4.tcp_keepalive_time = 1200

    net.ipv4.tcp_syncookies = 1

    net.ipv4.tcp_tw_reuse = 1

    net.ipv4.tcp_tw_recycle = 1

    net.ipv4.ip_local_port_range = 1024 65000

    net.ipv4.tcp_max_syn_backlog = 8192

    net.ipv4.tcp_max_tw_buckets = 5000

    说明:

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

    net.ipv4.tcp_keepalive_time = 1200 表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。

    net.ipv4.ip_local_port_range = 1024 65000 表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000。

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

    net.ipv4.tcp_max_tw_buckets = 5000表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。默 认为180000,改为5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于 Squid,效果却不大。此项参数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。

    执行以下命令使配置生效:

    /sbin/sysctl -p

    http://dennis-zane.javaeye.com/blog/206963#comments 2008-06-23 TCP的TIME_WAIT状态

    主动关闭的Socket端会进入TIME_WAIT状态,并且持续2MSL时间长度,MSL就是maximum segment lifetime(最大分节生命期),这是一个IP数据包能在互联网上生存的最长时间,超过这个时间将在网络中消失。MSL在RFC 1122上建议是2分钟,而源自berkeley的TCP实现传统上使用30秒,因而,TIME_WAIT状态一般维持在1-4分钟。

    TIME_WAIT状态存在的理由:

    1)可靠地实现TCP全双工连接的终止

    在进行关闭连接四路握手协议时,最后的ACK是由主动关闭端发出的,如果这个最终的ACK丢失,服务器将重发最终的FIN,因此客户端必须 维护状态信息允 许它重发最终的ACK。如果不维持这个状态信息,那么客户端将响应RST分节,服务器将此分节解释成一个错误(在java中会抛出connection reset的SocketException)。因而,要实现TCP全双工连接的正常终止,必须处理终止序列四个分节中任何一个分节的丢失情况,主动关闭 的客户端必须维持状态信息进入TIME_WAIT状态。

    2)允许老的重复分节在网络中消逝

    TCP分节可能由于路由器异常而“迷途”,在迷途期间,TCP发送端可能因确认超时而重发这个分节,迷途的分节在路由器修复后也会被送到最终目的地,这个 原来的迷途分节就称为lost duplicate。在关闭一个TCP连接后,马上又重新建立起一个相同的IP地址和端口之间的TCP连接,后一个连接被称为前一个连接的化身 (incarnation),那么有可能出现这种情况,前一个连接的迷途重复分组在前一个连接终止后出现,从而被无解成从属于新的化身。为了避免这个情 况,TCP不允许处于TIME_WAIT状态的连接启动一个新的化身,因为TIME_WAIT状态持续2MSL,就可以保证当成功建立一个TCP连接的时 候,来自连接先前化身的重复分组已经在网络中消逝。

    新的SCTP协议通过在消息头部添加验证标志避免了TIME_WAIT状态。

    展开全文
  • 1 函数原型 #include <pthread.h> int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, ...int pthread_cond_wait(pthread_cond_t *restrict cond,

    1 函数原型

    #include <pthread.h>
    
    int pthread_cond_timedwait(pthread_cond_t *restrict cond,
               pthread_mutex_t *restrict mutex,
               const struct timespec *restrict abstime);
    int pthread_cond_wait(pthread_cond_t *restrict cond,
               pthread_mutex_t *restrict mutex);

    2 注意事项

    pthread_cond_timedwait()用于等待一个条件变量,等待条件变量的同时可以设置等待超时。这是一个非常有用的功能,如果不想一直等待某一条件变量,就可以使用这个函数。

    2.1 abstime参数

    这里面的超时时间是一个绝对值,也就是距离1970-1-1 日的时间值,而不是一个时间段。比如说当前时间为2021-5-15 17:14:00.100,我们想通过这个函数设置最大超时为2500ms,那么就需要设置abstime时间为2021-5-15 17:14:02.600.

    2.2 时间获取

    条件变量默认使用的时间是CLOCK_REALTIME。通过clock_gettime()接口获取时间。
     

    static long long tm_to_ns(struct timespec tm)
    {
    	return tm.tv_sec * 1000000000 + tm.tv_nsec;
    }
    
    static struct timespec ns_to_tm(long long ns)
    {
    	struct timespec tm;
    	tm.tv_sec = ns / 1000000000;
    	tm.tv_nsec = ns - (tm.tv_sec * 1000000000);
    	return tm;
    }
    
      
    { 
    
            示意代码:
    
    	struct timespec start_tm;
    	struct timespec end_tm;
            int timeout_ms = 2500;
    	
    	clock_gettime(CLOCK_REALTIME, &start_tm);
    	end_tm = ns_to_tm(tm_to_ns(start_tm) + timeout_ms*1000000);
    
    	pthread_mutex_lock(&mtx);
    	
    	while (等待的条件) {
    		if (pthread_cond_timedwait(&cond, &mtx, &end_tm) == ETIMEDOUT) {
    			/*
    			 * 如果超时则退出等待
    			 */
    			ret = -1;
    			break;
    		}
    	}
    
    
    }

    但是CLOCK_REALTIME时间容易产生变化,比如通过NTP校准系统时钟,那么系统时钟会产生跨度变化。所以一般我们需要使用CLOCK_MONOTONIC。

    但是条件变量默认使用的时钟是CLOCK_REALTIME,所以需要通过条件变量的属性来设置条件变量使用的时钟。

        pthread_condattr_t attr;
        pthread_condattr_init(&attr);
    	
    #if 0
    	clockid_t clock_id;
    	pthread_condattr_getclock(&attr, &clock_id);
    	printf("clock_id: %d\n", clock_id);
    #endif
    
        /*
         * pthread_cond_timedwait()默认使用的是CLOCK_REALTIME,
         * CLOCK_REALTIME容易受系统影响,比如校时操作
         * 所以条件变量使用的时钟改为CLOCK_MONOTONIC
         * 参考:https://man7.org/linux/man-pages/man3/pthread_cond_timedwait.3p.html
         */
        pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
    
        pthread_cond_init(&cond, &attr);
    	
        pthread_condattr_destroy(&attr);
    
    
    
    
    
    static long long tm_to_ns(struct timespec tm)
    {
    	return tm.tv_sec * 1000000000 + tm.tv_nsec;
    }
    
    static struct timespec ns_to_tm(long long ns)
    {
    	struct timespec tm;
    	tm.tv_sec = ns / 1000000000;
    	tm.tv_nsec = ns - (tm.tv_sec * 1000000000);
    	return tm;
    }
    
      
    { 
    
            示意代码:
    
    	struct timespec start_tm;
    	struct timespec end_tm;
            int timeout_ms = 2500;
    	
    	clock_gettime(CLOCK_MONOTONIC, &start_tm);
    	end_tm = ns_to_tm(tm_to_ns(start_tm) + timeout_ms*1000000);
    
    	pthread_mutex_lock(&mtx);
    	
    	while (等待的条件) {
    		if (pthread_cond_timedwait(&cond, &mtx, &end_tm) == ETIMEDOUT) {
    			/*
    			 * 如果超时则退出等待
    			 */
    			ret = -1;
    			break;
    		}
    	}
    
    
    }

    如果想看完整的使用历程可以参考:

    https://blog.csdn.net/huohongpeng/article/details/116855603?spm=1001.2014.3001.5501

    3 描述

    https://man7.org/linux/man-pages/man3/pthread_cond_timedwait.3p.html

    The pthread_cond_timedwait() and pthread_cond_wait() functions
           shall block on a condition variable. The application shall ensure
           that these functions are called with mutex locked by the calling
           thread; otherwise, an error (for PTHREAD_MUTEX_ERRORCHECK and
           robust mutexes) or undefined behavior (for other mutexes)
           results.

           These functions atomically release mutex and cause the calling
           thread to block on the condition variable cond; atomically here
           means ``atomically with respect to access by another thread to
           the mutex and then the condition variable''. That is, if another
           thread is able to acquire the mutex after the about-to-block
           thread has released it, then a subsequent call to
           pthread_cond_broadcast() or pthread_cond_signal() in that thread
           shall behave as if it were issued after the about-to-block thread
           has blocked.

           Upon successful return, the mutex shall have been locked and
           shall be owned by the calling thread. If mutex is a robust mutex
           where an owner terminated while holding the lock and the state is
           recoverable, the mutex shall be acquired even though the function
           returns an error code.

           When using condition variables there is always a Boolean
           predicate involving shared variables associated with each
           condition wait that is true if the thread should proceed.
           Spurious wakeups from the pthread_cond_timedwait() or
           pthread_cond_wait() functions may occur. Since the return from
           pthread_cond_timedwait() or pthread_cond_wait() does not imply
           anything about the value of this predicate, the predicate should
           be re-evaluated upon such return.

           When a thread waits on a condition variable, having specified a
           particular mutex to either the pthread_cond_timedwait() or the
           pthread_cond_wait() operation, a dynamic binding is formed
           between that mutex and condition variable that remains in effect
           as long as at least one thread is blocked on the condition
           variable. During this time, the effect of an attempt by any
           thread to wait on that condition variable using a different mutex
           is undefined. Once all waiting threads have been unblocked (as by
           the pthread_cond_broadcast() operation), the next wait operation
           on that condition variable shall form a new dynamic binding with
           the mutex specified by that wait operation. Even though the
           dynamic binding between condition variable and mutex may be
           removed or replaced between the time a thread is unblocked from a
           wait on the condition variable and the time that it returns to
           the caller or begins cancellation cleanup, the unblocked thread
           shall always re-acquire the mutex specified in the condition wait
           operation call from which it is returning.

           A condition wait (whether timed or not) is a cancellation point.
           When the cancelability type of a thread is set to
           PTHREAD_CANCEL_DEFERRED, a side-effect of acting upon a
           cancellation request while in a condition wait is that the mutex
           is (in effect) re-acquired before calling the first cancellation
           cleanup handler. The effect is as if the thread were unblocked,
           allowed to execute up to the point of returning from the call to
           pthread_cond_timedwait() or pthread_cond_wait(), but at that
           point notices the cancellation request and instead of returning
           to the caller of pthread_cond_timedwait() or pthread_cond_wait(),
           starts the thread cancellation activities, which includes calling
           cancellation cleanup handlers.

           A thread that has been unblocked because it has been canceled
           while blocked in a call to pthread_cond_timedwait() or
           pthread_cond_wait() shall not consume any condition signal that
           may be directed concurrently at the condition variable if there
           are other threads blocked on the condition variable.

           The pthread_cond_timedwait() function shall be equivalent to
           pthread_cond_wait(), except that an error is returned if the
           absolute time specified by abstime passes (that is, system time
           equals or exceeds abstime) before the condition cond is signaled
           or broadcasted, or if the absolute time specified by abstime has
           already been passed at the time of the call. When such timeouts
           occur, pthread_cond_timedwait() shall nonetheless release and re-
           acquire the mutex referenced by mutex, and may consume a
           condition signal directed concurrently at the condition variable.

           The condition variable shall have a clock attribute which
           specifies the clock that shall be used to measure the time
           specified by the abstime argument. The pthread_cond_timedwait()
           function is also a cancellation point.

           If a signal is delivered to a thread waiting for a condition
           variable, upon return from the signal handler the thread resumes
           waiting for the condition variable as if it was not interrupted,
           or it shall return zero due to spurious wakeup.

           The behavior is undefined if the value specified by the cond or
           mutex argument to these functions does not refer to an
           initialized condition variable or an initialized mutex object,
           respectively.

    展开全文
  • 1. time_wait产生的原因及作用 下面我们先来简单回顾一下TCP连接关闭动作: 在Linux环境下我们可以如下的方式来统计TCP连接的情况: # netstat -nat | awk '/^tcp/ {++S[$NF]} END{for(a in S) print S[a], "\...
  • JAVA并发-对象方法wait

    2021-03-06 22:05:00
    最简单的东西,往往包含了最复杂的实现,因为需要为上层的存在提供一个稳定的基础,Object作为java中所有对象的基类,其存在的价值不言而喻,其中wait和notify方法的实现多线程协作提供了保证。案例public class ...
  • TIME_WAIT 814 CLOSE_WAIT 1 FIN_WAIT1 1 ESTABLISHED 634 SYN_RECV 2 LAST_ACK 1 常用的三个状态是:ESTABLISHED 表示正在通信,TIME_WAIT 表示主动关闭,CLOSE_WAIT 表示被动关闭。 具体每种状态什么意思,其实...
  • SELECT SID,SEQ#,EVENT,WAIT_TIME,SECONDS_IN_WAIT,STATE FROM v$session_wait WHERE sid=14; SELECT SID,serial#,STATUS FROM v$session WHERE sid=14; SELECT * FROM v$sess_io WHERE sid=14; SELECT b.name,a....
  • 查看TIME_WAIT和CLOSE_WAIT数的命令:netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'它会显示例如下面的信息:TIME_WAIT 、CLOSE_WAIT 、FIN_WAIT1 、ESTABLISHED 、SYN_RECV 、LAST_ACK...
  • 1 _4 E( g* h5 G4 z (异常B)B回复A后进入CLOSE-WAIT状态,但没有发送下一个FIN报文,则B一直处于CLOSE-WAIT状态;/ [ c" |& D& j3 B1 c& z y6 t8 ^6 ]4 { (异常C)A收到B的ACK后进入FIN-WAIT-2状态,等待B的...
  • void ObjectMonitor::wait(jlong millis, boolinterruptible, TRAPS) {Thread* const Self =THREAD ;assert(Self->is_Java_thread(), "Must be Java thread!");JavaThread*jt = (JavaThread *)THREAD;DeferredIni...
  • static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p) { if (p && p->_qproc && wait_address) p->_qproc(filp, wait_address, p); } 使用这个函数一般要配合...
  • wait函数 包含头文件及原型 #include <sys/types.h> /* 提供类型pid_t的定义 */ #include <sys/wait.h> pid_t wait(int *status) 进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程...
  • [Java教程]TIME_WAIT、 CLOSE_WAIT0 2015-12-11 16:00:37内容提要TCP连接释放的过程TIME_WAIT大量TiME_WAIT的后果解决方案CLOSE_WAIT大量CLOSE_WAIT的后果解决方案TCP 连接释放的过程图中,A是主动关闭的一方,B是...
  • 点击关注公众号,利用碎片时间学习写在开头,大概 4 年前,听到运维同学提到 TIME_WAIT 状态的 TCP 连接过多的问题,但是当时没有去细琢磨;最近又听人说起,是一个新手进行压测过程...
  • Obj.wait(),与Obj.notify()必需要与synchronized(Obj)一起使用,也就是wait,与notify是针对已经获取了Obj锁进行操作,从语法角度来说就是Obj.wait(),Obj.notify必须在synchronized(Obj){...}语句块内。从功能上来...
  • Linux wait函数详解

    2021-05-13 03:26:02
    wait和waitpid出现的原因SIGCHLD--当子进程退出的时候,内核会向父进程SIGCHLD信号,子进程的退出是个异步事件(子进程可以在父进程运行的任何时刻终止)--子进程退出时,内核将子进程置为僵尸状态,这个进程成为僵尸...
  • 使用wait和notify

    2020-12-28 23:03:43
    调用wait()方法后,线程进入等待状态,wait()方法不会返回,直到将来某个时刻,线程从等待状态被其他线程唤醒后,wait()方法才会返回,然后,继续执行下一条语句。 有些仔细的童鞋会指出:即使线程在getTask()内部...
  • wait 和 notify

    多人点赞 2021-11-25 15:46:54
    由于线程之间是抢占式执行的,因此线程之间执行的先后顺序难以预知. ...wait( )方法:当操作条件不成熟,就等待 notify( )方法:当条件成熟时,通知指定的线程来工作 wait( )方法 notify( )方法 notifyAll( )方法 ...
  • 另外,为了支持更为高级的线程间同步机制,比如:类似于POSIX中的条件变量,Java在Object类中提供了wait、notify和notifyAll方法,使得所有的类都隐式的继承了这些方法。特别地,为了提供对于程序健壮性方面的考虑,...
  • 点击关注公众号,回复“1024”获取2TB学习资源!写在开头,大概 4 年前,听到运维同学提到 TIME_WAIT 状态的 TCP 连接过多的问题,但是当时没有去细琢磨;最近又听人说起,是...
  • Oracle动态性能视图v$session_wait & v$session这是一个寻找性能瓶颈的关键视图。它提供了任何情况下session在数据库中当前正在等待什么(如果session当前什么也没在做,则显示它最后的等待事件)。当系统存在性能...
  • 一、TIME_WAIT状态的必要性上述四次握手描述的是客户段主动关闭,服务器被动关闭的流程,其一般过程如下:1、客户端发送FIN报文段,进入FIN_WAIT_1状态。2、服务器端收到FIN报文段,发送ACK表示确认,进入CLOSE_WAIT...
  • 关于CLOSE_WAIT和TIME_WAIT状态,服务器端都有可能出现,TIME_WAIT出现应该是短连接较多,需要通过修改内核参数解决,CLOSE_WAIT状态则是服务器程序可能有问题,服务器需要主动close,以及epoll多路复用模型中使用...
  • 在服务器的日常维护过程中,会经常用到下面的命令:netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’其中$NF表示最后一个字段它会显示例如下面的信息:TIME_WAIT 814CLOSE_WAIT 1FIN_WAIT1 ...
  • 六: wait4 ()系统调用在父进程中,用wait4()可以获得子进程的退出状态,并且防止在父进程退出前,子进程退出造成僵死 状态,关于wait4()在用户空间的调用方式可以自行参考相关资料,在这里只是讨论内核对这个系统...
  • 一、什么是Java线程的等待/通知模式 1、等待/通知模式概述 首先先介绍下官方的一个正式的介绍: 等待/通知机制,是指一个线程A调用了对象object的wait()方法进入等待状态,而另一个线程B调用了对象object的notify...
  • wait方法是当前线程等待,释放锁,这是Object的方法。同时要注意,Java 14 之后引入的 inline class 是没有 wait 方法的 Sleep()原理 public static native void sleep(long millis) throws InterruptedException; ...
  • linux中wait系统调用

    2021-05-19 03:35:33
    系统中的僵尸进程都要由wait系统调用来回收,下面就通过实战看一看wait的具体用法:wait的函数原型是:#include /* 提供类型pid_t的定义 */#include pid_t wait(int *status);返回值: 如果执行成功则返回子进程识别...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,023,439
精华内容 409,375
关键字:

wait()