虚拟主机

当前位置:  首页 >  常见问题 >  TCP大并发短连接造成TIME_WAIT问题解决办法

TCP大并发短连接造成TIME_WAIT问题解决办法

来源:未知

作者:admin

更新时间:2019-07-30 16:40

景安网络—专业的多线服务器托管商!提供快云服务器,快云VPS,虚拟主机,域名注册,网站空间,服务器托管,服务器租用,SSL证书。快云vps 1核1G1M,199元/首年,活动进行中!查看详情

这两天用python写了一个TCP的短连接压力测试脚本,模拟100路并发不间断的访问。脚本运行几分钟后开始全面报错,错误代码为10048或者99,使用netstat命令查看网络发现大量的连接处于TIME_WAIT状态。
 
仔细阅读了《unix网络编程》相关章节,弄清楚了问题发生的原因,并找到了解决办法。
 
问题原因:
 
TCP连接的Close默认行为是将socket标记为关闭然后立即返回。此时socket描述符不能继续被进程使用:作为read和write的参数。但是socket依然向对端发生已经缓存在队列中的数据,当所有数据都发生完毕后,socket进入TCP的四次包交换关闭时序。主动调用Close的一端在收到对端发来的FIN之后进入TIME_WAIT状态,并持续2MSL的时间。MSL在不同的TCP的实现中是不同的,一般是30秒到2分钟之间,所以2MSL为1~4分钟。socket再进入closed状态之前端口是一直被占用的,因此在TCP短连接大规模并发时很快便耗尽了可用的端口,因此就出现了10048或者99的错误。
 
解决办法:
 
通过SO_LINGER Socket选项改变Close的行为。
 
首先来了解下SO_LINGER socket选项:
 
该选项决定socket的close行为,默认情况下,close立即返回,但是如果socket的发送缓冲区中仍然有数据时,系统将继续会发送这些数据到对端。
 
SO_LINGER socket选项让我们可以改变close的默认行为。该选项要求如下数据结构传递到内核,它的定义在<sys/socket.h>中。
 
struct linger 
{
    int   l_onoff; /* 0==off, nonzero=on*/
    int   l_linger; /* linger time, POSIX specifies units as seconds */
};
根据l_onoff和l_linger的不同的取值,有如下三种场景:
1. 如果l_onoff等于0,该选项关闭,l_linger的值忽略,close为默认行为。
 
2. 如果l_onoff非0时,l_linger也等于0,当调用close时,TCP立即断开连接。详细过程是TCP丢弃所有仍然留在发送缓冲区的数据,向对端发送一个RST, 不进入普通的四次包交换时序。该设置socket避免了CLOSE_WAIT状态。
 
3. 如果l_onoff非0,l_linger大于0,当socket被close时,系统内核将延迟。即,当socket的发送缓冲区中任然有未发送的数据时,进程进入睡眠直到以下几种情况发生:
 
i)所有的数据已经发送且收到TCP对端发来的ack, 或者ii) linger超时。
 
 
 
从上述的三种场景来看,很明显2符合避免CLOSE_WAIT状态的要求,是解决该问题的关键。python的实现代码如下:
 
optval = struct.pack("ii",1,0)
tcp_client.setsockopt(SOL_SOCKET, SO_LINGER, optval )

本文链接:https://ssl.zzidc.com/changjianwenti/2019/0730/650.html

关键字:TCP,大,并发,短,连接,造成,TIME,WAIT,问题,

若无特别注明,文章皆为景安网络原创,转载请注明出处。

上云HI购
 
返回顶部

联系我们

SSL产品
24小时客服热线:

4006-598-598

0371-9618961