转载

一则小坑:java.io.FileNotFoundException Too many open files

最近项目准备上线,在测试环境测试通过,准备把项目部署到『预发布环境』,可以把它理解为我们上线前的最后一个验证环境。在部署的过程中,发现涉及的几个项目都部署失败了,jenkins 集成平台上『一片报红』,把我给整懵逼了。

一则小坑:java.io.FileNotFoundException Too many open files

这里再交代一下项目部署的方式:通过 jenkins 进行一系列 build 相关的操作之后,将构建产物(war包形式)传输到指定环境机器的 tomcat 容器中,启动运行。

问题解决

赶紧把机器上 tomcat 日志拉下来看一波,很快发现对应的几个项目虽然都成功部署到了容器当中,但是启动过程都失败了。

看日志应该是在解压 jar 包的过程中遇到了问题,显示 【Too many open files】,从字面上理解应该是和当前机器打开的文件数量有关。

一则小坑:java.io.FileNotFoundException Too many open files

文件句柄

这里就要引出 linux 文件句柄的概念了, 句柄可以理解为一个特殊标识,经过操作系统的处理之后,可以指向一块内存区域,听起来有点像『指针』,区别在于指针是直接指向内存,而句柄则是依赖于操作系统或者其它程序的处理之后,重定向到某块内存区域

这边只需要理解,应用进程操作文件需要通过操作系统提供的句柄对象。

句柄限制

文件句柄既然由操作系统提供, linux系统当然不会让你无休止打开文件,它对单个进程允许打开的句柄数进行了限制。

通过 ulimit -a 命令可以查看到所有系统资源限制参数,其中 open files 行就是当前允许单个进程打开的最大句柄数,为65535。

[root@iZ8vbcrus31oj4g007u7b0Z ~]# ulimit -a
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 6871
max locked memory       (kbytes, -l) 16384
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 6871
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
复制代码

当然也可以直接通过 ulimit -n 查看句柄限制。

[root@iZ8vbcrus31oj4g007u7b0Z ~]# ulimit -n
65535
复制代码

接下来我们查看某个进程打开的文件数。

通过 ps 命令,先找到对应进程的 PID,例如 mysql 服务进程。

[root@iZ8vbcrus31oj4g007u7b0Z ~]# ps -ef |  grep 'mysql'
UID        PID  PPID  C STIME TTY          TIME CMD
mysql     1058     1  0 4月05 ?       00:17:36 /usr/sbin/mysqld
复制代码

之后通过 lsof 命令可以查看指定进程打开的文件详情,再对结果进行统计,以此得到某个进程打开的文件数,可以看到我机器上的 mysql 服务当前打开的文件数为 77

[root@iZ8vbcrus31oj4g007u7b0Z ~]# lsof -p 1058 | wc -l
77
复制代码

修改句柄配置

可以重新配置的这个句柄限制数,可以看到默认给 root 用户配置了限制数为 65535,即这个限制是针对 root 用户打开的进程。

vi /etc/security/limits.conf
复制代码
一则小坑:java.io.FileNotFoundException Too many open files

不指定登录用户,则是针对于所有用户进行的限制。

soft nofile 65535
hard nofile 65535
复制代码

注意,修改配置后需要断开 ssh 连接,重新登录,配置才会生效。

原文  https://juejin.im/post/5e92645ae51d454700273882
正文到此结束
Loading...