zoukankan      html  css  js  c++  java
  • TCP连接中time_wait在开发中的影响-搜人以鱼不如授之以渔

      根据TCP协议定义的3次握手断开连接规定,发起socket主动关闭的一方socket将进入TIME_WAIT状态,TIME_WAIT状态将持续2个MSL(Max Segment Lifetime),TIME_WAIT状态下的socket不能被回收使用. 具体现象是对于一个处理大量短连接的服务器,如果是由服务器主动关闭客户端的连接,将导致服务器端存在大量的处于TIME_WAIT状态的socket, 甚至比处于Established状态下的socket多的多,严重影响服务器的处理能力,甚至耗尽可用的socket,停止服务. TIME_WAIT是TCP协议用以保证被重新分配的socket不会受到之前残留的延迟重发报文影响的机制,是必要的逻辑保证。

    netstat -an|awk '/tcp/ {print $6}'|sort|uniq -c
         16 CLOSING
        130 ESTABLISHED
        298 FIN_WAIT1
         13 FIN_WAIT2
          9 LAST_ACK
          7 LISTEN
        103 SYN_RECV
       5204 TIME_WAIT
    状态:描述
    CLOSED:无连接是活动的或正在进行的
    LISTEN:服务器在等待进入呼叫
    SYN_RECV:一个连接请求已经到达,等待确认
    SYN_SENT:应用已经开始,打开一个连接
    ESTABLISHED:正常数据传输状态
    FIN_WAIT1:应用说它已经完成
    FIN_WAIT2:另一边已同意释放
    ITMED_WAIT:等待所有分组死掉
    CLOSING:两边同时尝试关闭
    TIME_WAIT:另一边已初始化一个释放
    LAST_ACK:等待所有分组死掉

    原文和作者一起讨论:http://www.cnblogs.com/intsmaze/p/7076624.html

    微信:intsmaze

    避免微信回复重复咨询问题,技术咨询请博客留言。

    netstat -ae |grep mysql
    tcp        0      0 aaaa:53045               192.168.12.13:mysql           TIME_WAIT   root       0
    tcp        0      0 aaaa:53044               192.168.12.13:mysql           TIME_WAIT   root       0
    tcp        0      0 aaaa:53051               192.168.12.13:mysql           TIME_WAIT   root       0
    tcp        0      0 aaaa:53050               192.168.12.13:mysql           TIME_WAIT   root       0
    tcp        0      0 aaaa:53049               192.168.12.13:mysql           TIME_WAIT   root       0

    发现系统存在大量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
    net.ipv4.tcp_keepalive_time = 1200    
    net.ipv4.ip_local_port_range = 1024    65000   ## 端口分配范围
    net.ipv4.tcp_max_tw_buckets = 5000   ## 设置"time_wait"的桶最多容纳5000个
    然后执行 /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 =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。
     
    [阿里巴巴java开发手册推荐]高并发服务器建议调小 TCP 协议的 time_wait 超时时间。
    说明: 操作系统默认 240 秒后,才会关闭处于 time_wait 状态的连接,在高并发访问下,服务器端会因为处于 time_wait 的连接数太多,可能无法建立新的连接,所以需要在服务器上调小此等待值。
    正例: 在 linux 服务器上请通过变更/etc/sysctl.conf 文件去修改该缺省值(秒) :
    net.ipv4.tcp_fin_timeout = 30。 

    搜人以鱼不如授之以渔,让我们来回顾计算机网络中TCP协议的部分详解,摘自-谢希仁 计算机网络

    TCP 的运输连接的三个阶段
    运输连接就有三个阶段,即:连接建立、数据传送和连接释放。运输连接的管理就是使运输连接的建立和释放都能正常地进行。
    连接建立过程中要解决以下三个问题:
    要使每一方能够确知对方的存在。
    要允许双方协商一些参数(如最大报文段长度,最大窗口大小,服务质量等)。
    能够对运输实体资源(如缓存大小,连接表中的项目等)进行分配。
    客户-服务器方式
    TCP 连接的建立都是采用客户服务器方式。
    主动发起连接建立的应用进程叫做客户(client)。
    被动等待连接建立的应用进程叫做服务器(server)。
    TCP 的连接建立

    A 的 TCP 向 B 发出连接请求报文段,其首部中的同步位 SYN = 1,并选择序号 seq = x,表明传送数据时的第一个数据字节的序号是 x。
    B 的 TCP 收到连接请求报文段后,如同意,则发回确认。
    B 在确认报文段中应使 SYN = 1,使 ACK = 1,其确认号ack = x + 1,自己选择的序号 seq = y。

    A 收到此报文段后向 B 给出确认,其 ACK = 1,确认号 ack = y + 1。
    A 的 TCP 通知上层应用进程,连接已经建立。

    B 的 TCP 收到主机 A 的确认后,也通知其上层应用进程:TCP 连接已经建立。 

    用三次握手建立 TCP 连接的各状态

     

    TCP 的连接释放

     

    数据传输结束后,通信的双方都可释放连接
    现在 A 的应用进程先向其 TCP 发出连接释放报文段,并停止再发送数据,主动关闭 TCP 连接。A 把连接释放报文段首部的 FIN = 1,其序号 seq = u,等待 B 的确认。

    B 发出确认,确认号 ack = u + 1,而这个报文段自己的序号 seq = v。

    TCP 服务器进程通知高层应用进程。从 A 到 B 这个方向的连接就释放了,TCP 连接处于半关闭状态。B 若发送数据,A 仍要接收。
    若 B 已经没有要向 A 发送的数据,其应用进程就通知 TCP 释放连接。A 收到连接释放报文段后,必须发出确认。在确认报文段中 ACK = 1,确认号 ack = w + 1,自己的序号 seq = u + 1。

    TCP 连接必须经过时间 2MSL 后才真正释放掉。

    第一,为了保证 A 发送的最后一个 ACK 报文段能够到达 B。
    第二,防止 “已失效的连接请求报文段”出现在本连接中。A 在发送完最后一个 ACK 报文段后,再经过时间 2MSL,就可以使本连接持续的时间内所产生的所有报文段,都从网络中消失。这样就可以使下一个新的连接中不会出现这种旧的连接请求报文段。
                老铁快->关注,点赞,转发

  • 相关阅读:
    利用消息机制实现.NET AOP(面向方面编程)--通过RealProxy实现 zz
    A Taste of AOP from Solving Problems with OOP and Design Patterns (Part II) zz
    在.Net中使用异步(一)
    在.Net中使用异步(二)
    技术人员的误区(zz)
    A Taste of AOP from Solving Problems with OOP and Design Patterns (Part III) zz
    利用矩阵进行坐标系转换
    如何选择开源许可证[zz]
    .Net,你为什么会慢
    理解 Thread.Sleep 函数
  • 原文地址:https://www.cnblogs.com/intsmaze/p/7076624.html
Copyright © 2011-2022 走看看