如何排除“Too many open files”错误

02

排查思路

一般遇到“ Too many open files ”错误;正常情况下,肯定首先要使用lsof命令查看哪类文件出现了问题,但是考虑web服务基本上不太可能是普通文件出现问题,95%以上的下是因为TCP链接有问题。

所以直接建议业务方使用netstat命令查看,如下:

从输出来看,有大量的TCP链接处于CLOSE_WAIT状态,很明显不正常。一般处于 CLOSE_WAIT就是服务没有正常处理关闭操作。

所以应该找到和哪些链接的服务没有正常关闭,再使用 netstat命令,查看状态为 CLOSE_WAIT链接情况。

基本上会发现和某一类应用的机器始终保持着CLOSE_WAIT状态,这样基本上就定位到相关业务代码了。然后去相关的代码去找到释放链接的逻辑即可。

03

TCP链接状态讲解

TCP的状态图如下:

一般情况下,我们只需要关注下面2种异常状态:

  • TIME_WAIT:表示主动关闭链接

  • CLOSE_WAIT:表示被动关闭链接

TIME_WAIT主动关闭方在发送四次挥手的最后一个ACK会变为TIME_WAIT状态,保留次状态的时间为两个MSL,一般是客户端的状态。 TIME_WAIT状态一般不是由于 自己程序错误引起的。一般是通过调整内核参数来避免该问题。 相关的内核参数有: net.ipv4.tcp_tw_reuse 、net.ipv4.tcp_tw_recycle、net.ipv4.tcp_fin_timeout 等参数。

CLOSE_WAIT表示 对方发送一个FIN后,程序这边没有进一步发送ACK以确认。换句话说就是在对方关闭连接后,程序里没有检测到,或者程序里本身就已经忘了这个时候需要关闭连接,于是这个资源就一直被程序占用着。 所以处于 CLOSE_WAIT本身就表示程序中有bug,需要从程序角度去解决问题。 一般情况下,导致CLOSE_WAIT主要有两种可能:

  • 程序Bug,接收到FIN信号后没有及时关闭socket。比如:程序异常,导致close()方法没有执行。

  • 关闭socket不及时;比如:I/O线程太少,导致I/O操作处理不及时,链路不能被及时释放。