Nexus报Too Many Open Files错误

起因

  研发环境Nexus出现问题,导致npm包下载和上传失败

排查问题

首先查看Nexus服务日志:

Caused by: com.orientechnologies.common.io.OIOException: Error during file open
        at com.orientechnologies.orient.core.storage.fs.OFileClassic.open(OFileClassic.java:590)
        at com.orientechnologies.common.collection.closabledictionary.OClosableEntry.makeAcquiredFromClosed(OClosableEntry.java:102)
        at com.orientechnologies.common.collection.closabledictionary.OClosableLinkedContainer.acquire(OClosableLinkedContainer.java:297)
        at com.orientechnologies.orient.core.storage.cache.local.OWOWCache$PeriodicalFuzzyCheckpointTask.run(OWOWCache.java:2196)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.FileNotFoundException: /home/sonatype-work/nexus3/db/config/cleanup_name_idx.nbt (Too many open files)
        at java.io.RandomAccessFile.open0(Native Method)
        at java.io.RandomAccessFile.open(RandomAccessFile.java:316)
        at java.io.RandomAccessFile.<init>(RandomAccessFile.java:243)
        at com.orientechnologies.orient.core.storage.fs.OFileClassic.openChannel(OFileClassic.java:675)
        at com.orientechnologies.orient.core.storage.fs.OFileClassic.open(OFileClassic.java:580

 提示无法打开文件,Too Many Open Files。这类问题已然轻车熟路,遂查看/etc/security/limits.conf文件,准备修改最大文件数,发现该文件已经调整:

#*               soft    core            0
#*               hard    rss             10000
#@student        hard    nproc           20
#@faculty        soft    nproc           20
#@faculty        hard    nproc           50
#ftp             hard    nproc           0
#@student        -       maxlogins       4
#nexus - nofile 65536
* - nofile 655350
# End of file

但是为什么没有生效呢?bing一番,

Step 1: 查看 cat /etc/security/limits.d/20-nproc.conf是否有冲突配置:

# Default limit for number of user's processes to prevent
# accidental fork bombs.
# See rhbz #432903 for reasoning.

*          soft    nproc     65536
root       soft    nproc     unlimited

Step 2: 确保已启用pam_limit模块

  1. 修改/etc/ssh/sshd_config文件,确保开启一下配置:

      UsePAM yes

      UseLogin yes

  2. 修改 /etc/pam.d/login    /etc/pam.d/su     /etc/pam.d/sshd  /etc/pam.d/system-auth 几个文件,确认包含pam_limits.so

      session    required     pam_limits.so

完成以上两步,重启服务器,使用ulimit -a 查看 已生效,以为万事大吉,谁知隔天又报同样的错误。再Bing...

Step3 : 确认NOFILE配置是否应用到进程:

    1. 查看nexus进程号:

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

    2. 使用进程号查看进程的limits文件

      cat /proc/$pid/limits

     发现配置没有应用到进程上。

为什么明明配置了,而且使用ulimit查看也已经生效了,还是没有应用到进程上呢?再Bing...

Step4: 确认整个操作系统能够打开的文件数

    proc/sys/fs/file-max

    /proc/sys/fs/nr_open

    查看这两个文件的内容,数字并不小,与这个也没有关系。虽然没有关系,但是为了排除影响,也加上相关配置,修改/etc/sysctl.conf,t添加如下配置:

      

      fs.file-max = 102400 #内核可分配的最大文件数
      fs.nr_open = 1048576 #单个进程可分配的最大文件数
      fs.inotify.max_user_instances = 65535 #每个用户最大可创建inotify instances数量
      fs.inotify.max_user_watches = 102400 #每个用户可同时添加的watch数量

    使用 sysctl -p 使之生效。

还是无法解决问题,其实到这里已经没有什么思路了。。。此时我决定重启一下nexus服务,重启之后再使用cat /proc/$pid/limits 发现配置已经生效了。。。那为什么此前没有生效呢?

原来,nexus服务是开机启动的,其启动脚本在/etc/rc.d/rc.local中,这个开机启动优先级很高,导致NOFILE没有生效。改一下开机启动方式,使用systemd方式:

[Unit]
Description=Nexus Server
After=systemd-user-sessions.service network.target

[Service]
Type=forking
ExecStart=/home/nexus-3.15.2-01/bin/nexus start
ExecStop=/home/nexus-3.15.2-01/bin/nexus stop
KillMode=mixed
LimitNOFILE=655350

[Install]
WantedBy=multi-user.target

注意里面的LimitNOFILE配置选项,该选项使limit生效,至此问题解决。

如果这里还没有解决,建议查看服务是否是其他方式启动的,如自定义脚本,/etc/init.d,systemd等,加上相应的配置即可。

如果排除了启动方式的问题,是自己研发的服务,看看服务是否有bug,程序使用的文件描述符是否没有释放导致的。。。

PS: 还有一种方式可以临时更改某个进程的NOFILE限制:

  prlimit --pid ${pid} --nofile=65535:65535

参考资料:

  https://www.cnblogs.com/kingbase/p/15167892.html

  https://zhuanlan.zhihu.com/p/343556642

    

  

    

 

posted @ 2024-01-15 16:10  小张同学哈  阅读(51)  评论(0编辑  收藏  举报