zoukankan      html  css  js  c++  java
  • close_wait相关

    1. CLOSE_WAIT是什么

    TCP关闭时

    • 主动关闭: 发FIN(FIN_WAIT_1) --> 收ACK(FIN_WAIT_2) --> 收FIN(TIME_WAIT) --> 发ACK, TIME_WAIT会持续 2*MSL(1-4分钟)
    • 被动关闭: 收FIN(CLOSE_WAIT) --> 发ACK --> 发FIN(LAST_ACK) --> 收ACK(CLOSED), 如果程序不主动调用 close(fd) 关闭套接字,就不会主动发送FIN,就会一直在 CLOSE_WAIT 状态

    所以 CLOSE_WAIT 存在于被动关闭连接的情况,一般是服务器被动关闭,所以一般需要服务器去解决。

    2. 产生的原因

    主要有两点:

    1. 代码中没有写关闭连接的代码,存在bug;
    2. 该连接的业务代码处理事件太长,代码还在处理,对方已经发起断开连接的请求了;这时候会存在一段时间的 CLOS_WAIT,直到服务端处理到这里。

    总的来说,就是服务端没有及时调用close()关闭套接字。

    3. 一直不关闭,最多会存在多长时间

    内核会定时探测TCP连接是否存在,如果不存在,会自动关闭该TCP,回收系统资源。内核依靠如下参数来探测:

    • tcp_keepalive_time(7200): 如果在该参数指定的秒数内,TCP连接一直处于空闲,内核就开始向对端发起探测,看对端是否还在;
    • tcp_keepalive_intvl(75): 发起探测时,每隔这么多秒数,探测一次;
    • tcp_keepalive_probes(9): 总共探测这么多次;

    所以 CLOSE_WAIT 状态最多维持 tcp_keepalive_time + tcp_keepalive_intvl * tcp_keepalive_probes = 7200 +75*9 = 7875s,约130分钟,2小时多一点。

    这只是内核的限制,还可以在程序里使用 setsocketopt(fd, SOL_TCP, TCP_KEEPIDLE...) 对每个TCP连接设置。

    4. 有什么影响

    CLOSE_WAIT状态的端口表示正在被占用,如果没有设置端口复用,这个端口就变得不可用,过多的CLOSE_WAIT会耗尽系统的可用端口,新的连接进不来,服务变得不可用。

    5. 如何解决

    1. 程序方面,需要及时处理连接被动关闭的状态,特别是 recv() 收到0字节,表示对端关闭了;
    2. 系统方面,可以将 keepalive 相关的参数设置的小一些,让系统尽快探测到TCP不可用,尽快回收资源。

    6. 主动关闭时的两个较长的等待时间

    • FIN_WAIT_2: 等待对端发送 FIN
    • TIME_WAIT: 等待2MSL

    调用了shutdown(),但是没有调用close(),就会等在FIN_WAIT_2状态。跟这个状态有关的内核参数是:

    • net.ipv4.tcp_fin_timeout(30): 注意,这个参数只对调用了close()的孤儿tcp有效,如果程序只是调用了shutdown(),但是没有close(),该参数并不起作用。

    一般主动关闭连接的一方较常见 TIME_WAIT,产生的原因是主动关闭的时候,要等着对端收到了最后一个ACK才回收相应资源,防止对端没有收到ACK又重新发送最后一个FIN。但这也是占用了一个端口,跟这个状态有关的参数是:

    • net.ipv4.tcp_max_tw_buckets(180000): TIME_WAIT的最大数量,超过这个会被立刻清理,并打印警告信息
    • net.ipv4.tcp_tw_timeout(60): TIME_WAIT的过期时间
    • net.ipv4.tcp_tw_reuse(0): TIME_WAIT状态重用
    • net.ipv4.tcp_recycle(0): 开启 TIME_WAT 快速回收。不再是2MSL,而是一个RTO(动态计算的数据包重传超时时间)。还需要tcp_timestamps保证旧连接的数据包不会被新连接接收。NAT环境可能导致drop掉SYN包,无法发起新的连接;
    • net.ipv4.tcp_timestamps(1): 检查请求数据包的时间戳,快速回收需要配合这个时间戳选项;

    7. net.ipv4.tcp_timestamps=1和net.ipv4.tcp_recycle=1在NAT环境下的影响

    简单来说就是NAT会修改目的IP,但有的不修改tcp头里的timestamp,导致不同的客户端通过NAT过来的数据包时间戳不一样,时间戳小的就接不进server,所以server一般不开启 net.ipv4.tcp_recycle。

  • 相关阅读:
    在 Windows 上测试 Redis Cluster的集群填坑笔记
    vmware安装黑苹果教程
    微信支付v3发布到iis时的证书问题
    Linux下安装SQL Server 2016(连接篇SQL Server on linux)
    Linux下安装SQL Server 2016(连接篇SQL Server on linux)
    Linux下安装SQL Server 2016(安装篇SQL Server on linux)
    Linux下安装SQL Server 2016(准备篇SQL Server on linux)
    客服端与服务端APP支付宝支付接口联调的那些坑
    ASP.NET MVC]WebAPI应用支持HTTPS的经验总结
    .net平台下C#socket通信(中)
  • 原文地址:https://www.cnblogs.com/suntus/p/15468463.html
Copyright © 2011-2022 走看看