龙空技术网

项目出现“打开的文件过多”异常的解决思路

编程智慧 14

前言:

当前咱们对“centos65清空列命令”大致比较重视,姐妹们都想要知道一些“centos65清空列命令”的相关文章。那么小编同时在网络上搜集了一些对于“centos65清空列命令””的相关文章,希望小伙伴们能喜欢,看官们快快来学习一下吧!

在Linux环境下,当我们的项目运行一段时间之后,系统就不能正常访问了。本文以一个实际的案例来做一个剖析。

本案例是一个基于SpringBoot框架开发的项目网站系统,部署在centos操作系统下,网站运行一段时间之后,访问网页就长时间没有响应结果。

1、从现象中确定问题是什么

当项目出现这个问题之后,我们第一步需要确定问题到底是什么。我们通过查看项目日志,在日志中发现了下面异常信息:

java.io.IOException: 打开的文件过多at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method) ~[na:1.8.0_352]at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:421) ~[na:1.8.0_352]at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:249) ~[na:1.8.0_352]at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:547) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:79) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.tomcat.util.net.Acceptor.run(Acceptor.java:129) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at java.lang.Thread.run(Thread.java:750) [na:1.8.0_352]2023-07-09 04:41:38.675 ERROR 53912 --- [o-8081-Acceptor] org.apache.tomcat.util.net.Acceptor      : Socket accept failed
java.io.FileNotFoundException: /website/css/common.css (打开的文件过多)at java.io.FileInputStream.open0(Native Method) ~[na:1.8.0_352]at java.io.FileInputStream.open(FileInputStream.java:195) ~[na:1.8.0_352]at java.io.FileInputStream.<init>(FileInputStream.java:138) ~[na:1.8.0_352]at java.io.FileInputStream.<init>(FileInputStream.java:93) ~[na:1.8.0_352]

从异常信息中,我们可以确定问题是项目打开的文件数量超出了系统设定的上限

2、分析为什么出现这样的问题

项目打开的文件数量为什么会超出系统设定的限额?这个问题我们进行一下拆解,可以细化为下面两个问题:

1、打开文件太多可能会导致什么问题呢?

内存溢出:如果打开的文件太多,占用了大量的内存,可能会导致内存溢出。文件描述符不足:在 Linux 系统中,每个进程可打开的文件描述符是有限的。当打开的文件超过系统限制时,再尝试打开文件就会失败。IO 异常:当打开的文件太多时,可能会引起 IO 异常。

2、项目为什么会打开过多的文件?

程序打开文件后没有进行关闭程序并发打开过多

程序打开文件后没有进行关闭的导致项目运行一段时间之后,出现打开的文件过多的可能性最大。因为项目打开了文件没有关闭,打开的文件肯定会越来越多,从而超出了系统设定的限额。这也是开发者最容易犯下的错误。

3、提出问题的解决思路

通过上面的分析,我们如果只是系统设定限额太低,那很简单,只需要通过提高限额就可以了。使用下面的命令,可以查看系统设定的限额。

ulimit -n

如果需要增加该限额,可以修改系统配置即可:

vim /etc/security/limits.conf  # 添加或者修改下面两个配置,数字即为限额  * soft nofile 4096  * hard nofile 4096 

如果是程序打开文件没有进行关闭,如果我们通过分析代码,是很难快速定位的。我们可以通过下面的步骤来解决问题。

首先通过lsof命令来查看打开文件的情况。为提高效率,我们通过下面的方式先查找到项目的进程ID。查看项目的进程ID,有多种方式。假设项目的启动文件名包含"cms",我们执行下面的指令,会打印出项目的进程ID。

ps aux | grep cms | grep -v grep | awk '{print $2}'23223

然后执行使用下面的指令(23223为上面指令的结果)就可以查看打开了多少文件。

lsof | grep 23223 | wc -l

如果这个文件数确实非常大,而且在不断的增加,那么可以执行下面的命令查看具体打开了些什么文件。

lsof -p 23223 | grep '/website/' | grep -v '\.jar'

指令 lsof -p 23223 的结果列出进程打开了哪些文件。然后过滤出项目文件夹(假设项目部署在/website)下不包含.jar的其他文件。之所以排除.jar文件,因为那些文件都是项目的程序文件,是必须的。当然如果文件还是挺多,那么你可以使用相同的方法把其他的文件排除掉,例如 .css 和 .js 等,这样让显示的文件范围更加精准。

比如结果中出现很多的 .pdf 文件,那就说明我们的程序中打开 .pdf 文件的地方肯定是打开文件而忘记了关闭。

关闭文件示例

标签: #centos65清空列命令