• TCP 大量TIME_WAIT和CLOSE_WAIT问题


    四次挥手

    TIME_WAIT和CLOSE_WAIT主要发生在四次挥手期间。

    四次挥手过程:

    第一次挥手:主机A(可以是客户端,也可以是服务器端),设置Sequence Number和Acknowledgment Number,向主机B发送一个FIN报文段;此时,主机A进入FIN_WAIT_1状态;这表示主机A没有数据要发送给主机B了。

    第二次挥手:主机B收到了主机A发送的FIN报文段,向主机A回一个ACK报文段,Acknowledgment Number为Sequence Number加1,主机A进入FIN_WAIT_2状态;主机B告诉主机A,我也没有数据要发送了,可以进行关闭连接了。

    第三次挥手:主机B向主机A发送FIN报文段,请求关闭连接,同时主机B进入CLOSE_WAIT状态。

    第四次挥手:主机A收到主机B发送的FIN报文段,向主机B发送ACK报文段,然后主机A进入TIME_WAIT状态;主机B收到主机A的ACK报文段以后,就关闭连接;此时,主机A等待2MSL后依然没有收到回复,则证明主机B已正常关闭,那好,主机A也可以关闭连接了。

    大量TIME_WAIT

    在第四次挥手时这样的描述:“主机A等待2MSL后依然没有收到回复,则证明主机B已正常关闭”。正因为有2ML的存在,所以可能会发生大量time_wait存在的现象,从而影响服务器性能,甚至导致套接字数量达到服务器上限。

    (MSL,Maximum Segment Lifetime,“报文最大生存时间”,)

    1 客户端

    • HTTP 请求的头部,connection 设置为 keep-alive,保持存活一段时间:现在的浏览器,一般都这么进行了

    2 服务器端

    • 允许 time_wait 状态的 socket 被重用
    • 缩减 time_wait 时间,设置为 1 MSL(即,2 mins)

    可以通过修改内存参数缓解这类问题:

    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 修改系統默认的 TIMEOUT 时间。
    

    在经过这样的调整之后,除了会进一步提升服务器的负载能力之外,还能够防御一定程度的DDoS、CC和SYN攻击,是个一举两得的做法。

    大量CLOSE_WAIT

    主机B一直没有进行第三次挥手,会导致主机B存在大量close_wait状态的连接。大量这种情况发生会影响服务器性能,同样可能导致套接字数量达到服务器上限。

    网络连接未及时释放,通常是服务端发生异常后未关闭连接或者close_wait的配置时间过长。如果是mysql数据库也可能存在事务开启后没有正确rollback或commit的可能。

    总之,都是大概率是服务端代码或配置的问题。

    解决方式

    以下方法并不存在顺序,定位问题时也并不是一定同时需要。

    • top查看cpu利用率和load情况(大量close_wait属于io密集型,会导致load相比cpu利用率高出很多)
    • netstat观察close_wait的数量变化。
    • wireshark辅助查看网络包的发送情况。
    • perf或者火焰图定位热点函数。
    • java可以将服务器线程堆栈dump,查看大量线程在哪里blocked。

    END!!

  • 相关阅读:
    Eclipse JSP/Servlet 环境搭建
    1,有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?
    Electron-vue实战(二)— 请求Mock数据渲染页面
    Electron-vue实战(一)—搭建项目与安装Element UI
    Electron-vue实战(三)— 如何在Vuex中管理Mock数据
    vue学习笔记(六)— 关于Vuex可以这样简单理解
    vue学习笔记(五)— 组件通信
    OpenLayers学习笔记(十二)— 飞机速度矢量线预测(二)
    QML学习笔记(八)— QML实现列表侧滑覆盖按钮
    重学JavaScript
  • 原文地址:https://www.cnblogs.com/amunote/p/16328622.html
Copyright © 2020-2023  润新知