服务器TIME_WAIT和CLOSE_WAIT区别及解决方案

标签: 服务器 time wait | 发表时间:2014-06-29 15:08 | 作者:dengqsintyt
出处:http://www.iteye.com

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

 

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,就断开连接。

        

 



已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [服务器 time wait] 推荐:

wait、sleep、yield区别

- - CSDN博客推荐文章
1、属于Object的本地方法. 2、暂停当前线程,并释放锁. 3、调用notify()或notifyAll()方法唤醒线程. 1、Thread类的静态方法. 2、当前线程休眠,但不释放锁. 3、其他线程可以继续执行,无论该线程优先级高与否. 4、休眠一段时间后,自动执行. 1、Thread类的静态方法.

掀起新.Time Capsule 的盖头来,让我看看...咦!说好的服务器级硬盘到哪去了?

- 亚 强 - Engadget 中国版
呃,什么叫做相见不如怀念,大概就是拆开号称装有「服务器级」硬盘的新 Time Capsule 之后,却发现里头装的那颗硬盘是 Western Digital 的绿标 WD20EARS. 看完之后心里只有一堆问号,难道说最近在北卡开张的那座数据中心里头的服务器都是用这款硬盘. 难怪最近开 iTunes 下载软件时好像有变卡的感觉.

Java多线程之wait()和notify()

- - CSDN博客推荐文章
直接看测试代码吧,细节之处,详见注释.  * Java多线程之wait()和notify()的妙用 .  * @see 问题:同时启动两个线程和同时启动四个线程,控制台打印结果是不同的 .  * @see      同时启动两个线程时,控制台会很规律的输出1010101010101010 .  * @see      同时启动四个线程时,控制台起初会规律的输出10101010,一旦某一刻输出一个负数,那么后面的输出就会"一错再错" .

java多线程设计wait/notify机制

- - CSDN博客推荐文章
  当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait() , 放弃对象锁..   之后在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A:.   # 调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj) {…} 代码段内.

Java多线程之wait和notify

- - ITeye博客
最近在看Java特种兵,看到多线程部分,对wait和notify不是很理解,于是写了代码来帮助理解.              wait方法通过参数可以指定等待的时长. 如果没有指定参数,默认一直等待直到被通知. notify方法是通知某个正在等待这个对象的控制权的线程可以继续运行. 调用wait方法时候,必须加上synchronized同步块,不然会抛出java.lang.IllegalMonitorStateException异常.

Long time no see,英式中文

- cow - 刁民公園
昨天「星期日檔案」探討港式英語. 節目中好幾個嘉賓包括楊鐵樑先生都說long time no see是港式英語. 楊官的英文程度不會令人懷疑,但long time no see有其背景,不能算作港式英語.

被忽视的time命令

- - 火丁笔记
如果要选 Linux 下最容易被忽视的命令,time 应该算一个. 简单来说,它是一个用来计算命令运行时间的工具,之所以说它容易被忽视,一方面很多人根本不知道 time 的存在,而是习惯在命令启动前后记录两个时间戳,然后手动计算命令运行时间;另一方面很多人虽然知道 time 的存在,但是却并没有真正理解它的含义.

Java Sleep() 与 Wait()的机制原理与区别

- - CSDN博客推荐文章
Java中的多线程是一种抢占式的机制而不是分时机制. 线程主要有以下几种状态:可运行,运行,阻塞,死亡. 抢占式机制指的是有多个线程处于可运行状态,但是只有一个线程在运行.        当有多个线程访问共享数据的时候,就需要对线程进行同步.        Thread类的方法:sleep(),yield()等.

[转载]java之yield(),sleep(),wait()区别详解

- - 移动开发 - ITeye博客
使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁. 也就是说如果有synchronized同步快,其他线程仍然不能访问共享数据. 例如有两个线程同时执行(没有synchronized)一个线程优先级为MAX_PRIORITY,另一个为MIN_PRIORITY,如果没有Sleep()方法,只有高优先级的线程执行完毕后,低优先级的线程才能够执行;但是高优先级的线程sleep(500)后,低优先级就有机会执行了.

最简实例说明wait、notify、notifyAll的使用方法

- - Java - 编程语言 - ITeye博客
wait()、notify()、notifyAll()是三个定义在Object类里的方法,可以用来控制线程的状态. 这三个方法最终调用的都是jvm级的native方法. 随着jvm运行平台的不同可能有些许差异. •如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态.