java.io.IOException: Too many open files

一、故障说明

今天登录系统总是显示失败,查看日志的时候,发现日志中报出了大量的异常Too many open files。根据经验判断应该是操作了大量的文件并且在操作后,没有关闭文件流。

2022-03-29 22:22:47 [http-nio-8777-Acceptor] ERROR org.apache.tomcat.util.net.Acceptor : Socket accept failed
java.io.IOException: Too many open files
        at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
        at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:422)
        at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:250)
        at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:461)
        at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:73)
        at org.apache.tomcat.util.net.Acceptor.run(Acceptor.java:95)
        at java.lang.Thread.run(Thread.java:748)

二、too many open files描述

too many open files是Linux系统中常见的错误,从字面意思上看就是说程序打开的文件数过多,不过这里的files不单是文件的意思,也包括打开的通讯链接(比如socket),正在监听的端口等等,所以有时候也可以叫做句柄(handle),这个错误通常也可以叫做句柄数超出系统限制。


三、故障排除

引起的原因就是进程在某个时刻打开了超过系统限制的文件数量以及通讯链接数,通过命令ulimit -a可以查看当前系统设置的最大句柄数是多少:

[root@test]# 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) 1029324
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65536
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) unlimited
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

open files那一行就代表系统目前允许单个进程打开的最大句柄数,这里是65536

因为我是用的是docker,里面仅仅启动了一个java程序。为此当我们使用top命令查看的时候,此处主要是为了获取程序的pid。

   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
     1 root      20   0 7403544 807388  13820 S   1.7  0.3 100:29.02 java
 21267 root      20   0   15388   2112   1636 S   0.0  0.0   0:00.01 bash
 21283 root      20   0   59628   2124   1504 R   0.0  0.0   0:00.01 top

第一次操作lsof命令可能需要安装:yum install -y lsof

接下来看我这个java程序到底打开了多少文件。此处使用命令:lsof

lsof -p 1 |wc -l
# 返回值:65572

此时发现,进程1,也就是我们的java程序操作了65572个文件,并且没有关闭。超过了我们系统允许的数量65536。

如果是普通的虚拟机或者物理,可以通过如下命令,找到打开文件数量最多的进程:
#查看了排在前面的几个进程
lsof -n | awk '{print $2}' | sort | uniq -c | sort -nr | more

重新回到我们刚才的java 程序操作中,我们发现java程序的打开的文件太多了,我们将其操作的文件导出到文件中,在文件中查看。

lsof -p 1 > openfile.log

在导出的文件中找到打开次数最多的文件,然后在代码中排除即可。
我们的代码中是重复操作了同一个文件,文件名相同,比较好找,如果文件名字不同,可能需要开发人员细心排除一下了。

四、其他解决方案

如果故障原因不是因为文件没有关闭,或者项目需要开启更多句柄,可以修改配置文件,从而允许打开更多文件。

1、临时修改方案,重启失效。

# 将句柄设置为102048
ulimit -n 102048

2、永久方案

sudo vim /etc/security/limits.conf

文件的最后添加

*       soft    nofile  65535
*       hard    nofile  65535

最终效果:

#<domain>      <type>  <item>         <value>
#
 
#*               soft    core            0
#root            hard    core            100000
#*               hard    rss             10000
#@student        hard    nproc           20
#@faculty        soft    nproc           20
#@faculty        hard    nproc           50
#ftp             hard    nproc           0
#ftp             -       chroot          /ftp
#@student        -       maxlogins       4
 
*       soft    nofile  65535
*       hard    nofile  65535

最前的 * 表示所有用户,可根据需要设置某一用户
然后修改全系统总限制

sudo vim /etc/sysctl.conf

在文件底部添加:


fs.file-max=655350

立即生效:

sudo sysctl -p

这样就修改完毕了,用户级句柄数的修改需要重启一下才能生效,最好执行一下reboot,再次输入ulimit -n查看已经修改好了。

  • 7
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

aiming66

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值