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