转自:简书链接,https://zhuanlan.zhihu.com/p/63841157,http://blog.itpub.net/15480802/viewspace-1334381/
1.TIME_AWAIT状态
TIME_WAIT的状态就是主动断开的一方,发送完最后一次ACK之后进入的状态。并且持续时间还挺长的。
是主动断开的一方会出现的状态。
1.1 TIME_AWAIT过多危害
- 网络情况不好时,如果主动方无TIME_WAIT等待,关闭前个连接后,主动方与被动方又建立起新的TCP连接,这时被动方重传或延时过来的FIN包过来后会直接影响新的TCP连接;如果没有TIME_WAIT的话,假设连接1已经断开,然而其被动方最后重发的那个FIN(或者FIN之前发送的任何TCP分段)还在网络上,然而连接2重用了连接1的所有的5元素(源IP,目的IP,TCP,源端口,目的端口),刚刚将建立好连接,连接1迟到的FIN到达了,这个FIN将以比较低但是确实可能的概率终止掉连接2.
- 同样网络情况不好并且无TIME_WAIT等待,关闭连接后无新连接,当接收到被动方重传或延迟的FIN包后,会给被动方回一个RST包,可能会影响被动方其它的服务连接。假设最终的 ACK 丢失 , server 将重发 FIN , client 必须维护 TCP 状态信息以便可以重发最终的 ACK ,否则会发送RST ,结果 server 认为发生错误。
- 过多的话会占用内存,一个time_await占用4k大小.
2.客户端很多处于TIME_AWAIT状态
https://blog.csdn.net/guchuanyun111/article/details/52047872
那么意味着是客户端选择关闭连接,
如果并发比较大,有很多客户端发出短连接,那么就会导致很多处于TIME_AWAIT状态。
3.解决办法
- 可以改为长连接,但代价较大,长连接太多会导致服务器性能问题;
- 客户端程序中设置socket的SO_LINGER选项;
- 客户端机器打开tcp_tw_recycle和tcp_timestamps选项
- 客户端机器打开tcp_tw_reuse和tcp_timestamps选项
- 客户端机器设置tcp_max_tw_buckets为一个很小的值
3.1 SO_LINGER
struct linger { int l_onoff; /* 0 = off, nozero = on */ int l_linger; /* linger time */ };
设置 l_onoff !=0 && l_linger = 0,则套接口关闭时TCP夭折连接,TCP将丢弃保留在套接口发送缓冲区中的任何数据并发送一个RST给对方,而不是通常的四分组终止序列,这避免了TIME_WAIT状态;
3.2 tcp_tw_recycle
tcp_tw_recycle选项作用为:Enable fast recycling TIME-WAIT sockets. Default value is 0.
tcp_timestamps选项作用为:TCP timestamps are used to provide protection against wrapped sequence numbers. 缺省值为1。(TCP时间戳用于提供对包装序列号的保护。)
1)快速回收到底有多快?
局域网环境下,700ms就回收;
3.3 tcp_tw_reuse
tcp_tw_reuse – BOOLEAN
Allow to reuse TIME-WAIT sockets for new connections when it is safe from protocol viewpoint. Default value is 0.
1)tcp_tw_reuse选项和tcp_timestamps选项也必须同时打开;
2)重用TIME_WAIT的条件是收到最后一个包后超过1s。
3.4 tcp_max_tw_buckets
tcp_max_tw_buckets – INTEGER
Maximal number of timewait sockets held by system simultaneously. If this number is exceeded time-wait socket is immediately destroyed and warning is printed.
系统同时持有的最大时间等待套接字数。如果超过这个数字,等待套接字立即被销毁并打印警告。