最近在项目中遇到一个很奇怪的问题,因为修改配置(redis中缓存的),nginx服务突然报upstream timed out (110: Connection timed out),然后去查为什么会出现这样的问题,发现出问题的服务是一个golang的http server,查看程序日志,发现大量的accept4: too many open files报错,第一感觉应该是哪里文件句柄读取没有释放。
too many open files(打开的文件过多)是Linux系统中常见的错误,从字面意思上看就是说程序打开的文件数过多,不过这里的files不单是文件的意思,也包括打开的通讯链接(比如socket),正在监听的端口等等,所以有时候也可以叫做句柄(handle),这个错误通常也可以叫做句柄数超出系统限制。 引起的原因就是进程在某个时刻打开了超过系统限制的文件数量以及通讯链接数。
1. 查看系统的配置 ulimit -a | grep open,发现系统的配置正常。
![](https://static.studygolang.com/191009/5a58cb5c3f74f46da7d976104c943688.png)
2. 查看程序服务的打开文件限制,cat /proc/40636/limits,发现服务的限制并没有继承系统设置的,还是系统默认的1024限制。
![](https://static.studygolang.com/191009/64dac1cad11f114046cddf4aced50bda.png)
3. 查看程序服务打开文件数(连接数)情况,lsof -p 40636 | wc -l,发现已经超出限制,所以报错。
![](https://static.studygolang.com/191009/59f62200bc4d5be63efeb0b91c896598.png)
4. 再看看程序服务打开了哪些连接,lsof -p 40636 > openfiles.log,发现很多http连接打开没有关闭,看ip是报警服务的接口,于是顺着这条线索,终于找到了原因,因为程序中读取到的配置解析时报错给报警服务,大量的报警服务连接后未关闭,才导致的too many open files,这是问题的关键,但是程序为什么没有继承系统设置的最大配置限制,还需要继续查看。
5. 最终原因找到,因为程序服务是supervisor管理的,supervisor启动服务默认的minfds配置是1024,也就是打开文件限制是1024,在supervisor的配置中加入minfds=81920; 重启supervisorctl reload,再次查看程序进程文件限制,正常了,困扰我一上午的问题终于解决,大呼“爽”。
![](https://static.studygolang.com/191009/97cbec28d801bbfe3127a804b2d9b997.png)
有疑问加站长微信联系(非本文作者)
![](https://static.golangjob.cn/static/img/footer.png?imageView2/2/w/280)