美文网首页
TIME_WAIT 问题解决

TIME_WAIT 问题解决

作者: OOM_Killer | 来源:发表于2020-03-14 11:46 被阅读0次

    TIME_WAIT 的问题

    应用服务器需要通过发起 TCP 连接其他服务器,比如 代理服务器需要请求上游服务器,每个连接会占用一个port,在高并发场景下,可能会导致端口耗尽。为了TCP正常断开连接,TCP 发起挥手的一端为了确保最后一个ACK 能够达到被动关闭方,所以会等待 2MSL。


    MSL (maximum segment lifetime):LINUX 的硬编码字段,名称为 TCP_TIMEWAIT_LEN,值为60s,而一个time_wait 默认等待的时间为 2MSL

    TIME_WAIT 的危害

    • 内存资源占用,内存资源的占用不是很严重,可暂且忽略
    • 端口资源占用,一个TCP连接需要消耗一个本地端口,一般可开启的端口为32768 ~ 61000。

    如何优化

    net.ipv4.ip_local_port_range

    制定主动建联时的端口范围

    net.ipv4.tcp_max_tw_buckets

    此值默认是 18000,当系统中处于 TIME_WAIT 的连接大于该值后,系统会将所有的 TIME_WAIT 连接重置,并打印出警告信息。这个方法过于暴力,解决的问题比带来的问题多,不建议使用

    调低 TCP_TIMEWAIT_LEN,重新编译系统

    得编译内核,而且TCP发明至今这些固化到内核的参数都是有一定道理的,不要乱改。

    SO_LINGER 设置

    在应用程序中设置套接字选项,调用close 或者 shutdown 关闭连接时候的行为。

    int setsockopt(int sockfd, int level, int optname, const void *optval,
            socklen_t optlen);
    
    struct linger {
     int  l_onoff;    /* 0=off, nonzero=on */
     int  l_linger;    /* linger time, POSIX specifies units as seconds */
    }
    
    • l_onoff: linger 的开关
      • l_onoff 为 0:关闭linger 选项,默认行为,close 或 shutdown 立即返回,如果在套接字发送缓冲区有数据残留,系统会将试着把这些数据都发送出去
      • l_onoff 为 1:打开linger 选项,具体行为看 l_linger
        • l_linger 为0:调用close后,立即发送一个RST标志给对端,该TCP跳过四次挥手,直接关闭,这种方式被称为“强行关闭”,这种情况下,排队的数据不会被发送,被动关闭方也不知道对端已经彻底断开,只有当被动关闭方正阻塞在recv() 调用上,接受到 RST 时,会立刻得到一个 “connect reset by peer”的异常。
        • l_linger 为1:调用close后,调用close的线程将阻塞,直到数据都被发送出去,或者设置 l_linger 的计时时间到。

    net.ipv4.tcp_tw_reuse : 更安全的设置

    Linux 对 net.ipv4_tw_reuse的解析如下:

    Allow to reuse TIME-WAIT sockets for new connections when it is safe from protocol viewpoint. Default value is 0.It should not be changed without advice/request of technical experts.

    这段话意思是说从协议角度理解如果是安全的话,可以复用处于 TIME_WAIT 的套接字为新的连接所用。

    协议角度 的安全是指:

    1. 只适用与连接的发起方,即客户端
    2. 对应的TIME_WAIT 状态的连接创建时间超过1s才可以被复用

    使用的这个选项的前提,需要打开对TCP时间戳的支持。
    即 net.ipv4.tcp_timestamps = 1 (默认即为1),重复的数据包会因为时间戳过期被自然丢弃。

    SO_REUSEADDR

    这个比较特殊,网上有很多教程都说拿这个解决 TIME_WAIT,其实是对的,但是不是一回事。为什么?
    这个是解决端口复用问题的,并不是解决 TIME_WAIT ,这个是告诉内核,即使TIME_WAIT 的套接字,也可以作为新的套接字使用,这是为了避免服务端监听端口时,因为被监听的端口处于 TIME_WAIT 导致服务端无法启动。
    其本质是解决 服务端 监听端口时的 TIME_WAIT ,而我们上面一直说的是作为客户端建联时没有足够的随机端口导致的无法建联。

    终极解决方案: 长连接

    条件允许的,把连接保持住,避免频繁的建连和断开。但是仅限内网这么搞,公网的话,一条连接总是不断,运营商可能会搞些小动作,给你限个速。

    相关文章

      网友评论

          本文标题:TIME_WAIT 问题解决

          本文链接:https://www.haomeiwen.com/subject/xuymshtx.html