处于 CLOSE_WAIT 状态的孤立连接

处于 CLOSE_WAIT 状态的孤立连接

我有一台 SLES 机器,它会在 CLOSE_WAIT 状态下累积 TCP 连接,似乎永远不会发生。这些描述符最终会耗尽所有可用内存。目前,我已经有 3037 个,但在最近匆忙重启之前这个数字要高得多。

有趣的是,它们不是来自与我期望有侦听进程的本地端口的连接。它们没有关联的 PID,并且它们的计时器似乎已过期。

# netstat -ton | grep CLOSE_WAIT
tcp      176      0 10.0.0.60:54882     10.0.0.12:31663      CLOSE_WAIT  off (0.00/0/0)
tcp       54      0 10.0.0.60:60957     10.0.0.12:4503       CLOSE_WAIT  off (0.00/0/0)
tcp       89      0 10.0.0.60:50959     10.0.0.12:3518       CLOSE_WAIT  off (0.00/0/0)

# netstat -tonp | grep CLOSE_WAIT
tcp       89      0 10.0.0.59:45598     10.0.0.12:1998       CLOSE_WAIT  -                   
tcp       15      0 10.0.0.59:60861     10.0.0.12:1938       CLOSE_WAIT  -                   
tcp        5      0 10.0.0.59:56173     10.0.0.12:1700       CLOSE_WAIT  -     

当涉及到 TCP 堆栈或内核网络时,我不是黑带,但 TCP 配置似乎很正常,因为根据手册页,这些值是默认值:

# cat /proc/sys/net/ipv4/tcp_fin_timeout 
60
# cat /proc/sys/net/ipv4/tcp_keepalive_time 
7200

那么什么给出呢?如果计时器过期了,堆栈不应该自动清除这些东西吗?随着这些事情的积累,我实际上给了自己一个长期的拒绝服务。

答案1

不,没有超时CLOSE_WAIT。我认为这就是off你的输出的含义。

要退出CLOSE_WAIT,应用程序必须显式关闭套接字(或退出)。

如何打破CLOSE_WAIT

如果在进程栏中netstat显示:-

  • 您是否以适当的权限和功能运行(例如作为 root)?
  • 它们可能是内核进程(例如 nfsd)

答案2

CLOSE_WAIT表示客户端正在关闭连接,但应用程序尚未关闭它,或者客户端尚未关闭。您应该确定哪个或哪些程序存在此问题。尝试使用

netstat -tonp 2>&1 | grep CLOSE

确定哪些程序保持连接。

如果没有列出任何程序,则该服务由内核提供。这些可能是 RPC 服务,例如nfsrpc.lockd。可以列出侦听内核服务

netstat -lntp 2>&1 | grep -- -  

除非 RPC 服务已绑定到固定端口,否则它们将绑定到您的连接显示的临时端口。您可能还想检查其他服务器上的进程和安装。

您可以通过执行以下操作将 NFS 服务绑定到固定端口:

  1. 选择四个未使用的 NFS 端口(此处使用 32763-32766)
  2. 添加 NFS 的固定端口/etc/services
    rpc.statd-bc 32763/udp # RCP statd 广播
    rpc.statd-bc 32763/tcp
    rpc.statd 32764/udp # RCP statd 监听
    rpc.statd 32764/tcp
    rpc.mountd 32765/udp # RPC挂载
    rpc.mountd 32765/tcp
    rpc.lockd 32766/udp # RPC lockd/nlockmgr
    rpc.lockd 32766/tcp
  3. 配置 statd 以使用选项--port 32763 --outgoing-port 32764
  4. 配置 rpcmountd 以使用该选项--port 32765
  5. 关闭并重新启动 NFS 和 RPC 服务。

答案3

虽然米克尔的回答可能也是正确的,像 NFS 这样的内核端套接字可能会导致这种情况,CLOSE_WAIT -没有关联 FD 的条目更常见:

listen()之前在本地队列中时被对方关闭的连接accept()可以被调用,请参阅我的详细答案与重现在这里

处于 CLOSE_WAIT 状态,似乎是永远的

他们将永远保持这种状态,直到你

  • accept()他们然后是close()他们,或者
  • close()整个套接字(这可能不是一个解决方案)。

这在本文中也有详细解释链接答案

这些描述符最终会耗尽所有可用内存。

这不应该发生,因为根据man 2 listen,队列的长度listen()受到限制

/proc/sys/net/ipv4/tcp_max_syn_backlog  # default 4096
/proc/sys/net/core/somaxconn            # default 4096

当然,除非您有多个套接字listen(),因为上述限制是针对每个此类套接字的。

相关内容