Linux 出现Too many open files 原因以及解决办法

前几天部署JAVA项目,在测试环境上跑了几个小时Tomcat出现异常

java.net.SocketException: Too many open files  
        at java.net.PlainSocketImpl.socketAccept(Native Method)  
        at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:384)  
        at java.net.ServerSocket.implAccept(ServerSocket.java:453)  
        at java.net.ServerSocket.accept(ServerSocket.java:421)  
        at org.apache.tomcat.util.net.DefaultServerSocketFactory.acceptSocket(DefaultServerSocketFactory.java:60)  
        at org.apache.tomcat.util.net.JIoEndpoint$Acceptor.run(JIoEndpoint.java:216)  

出现这个错误原因是打开文件数(Linux一切皆文件,所以打开文件数包含文件和Socket连接数)超过Linux设置的最大值

使用lsof -p  pid | wc -l  查看Tomcat进程打开文件数5622   pid ---表示程序的进程号  

查看当前进程最大打开文件数限制  cat /proc/pid/limits   (一定要以查看当前进程为准)

Linux 出现Too many open files 原因以及解决办法_第1张图片

查看当前打开文件数限制 ulimit -a 显示 (有可能出现ulimit -a 查看的open files 和 cat /proc/pid/limits不一致的情况 ,一定要以上述查看当前进程为准,因为有可能在程序运行中,修改过open files的大小,而运行中的程序只会以启动时的open files大小为准)

Linux 出现Too many open files 原因以及解决办法_第2张图片

目前该用户单进程文件数打开限制为4096,解决方案当然是修改单进程文件数打开限制(比如修改为8192)

修改时需要将用户切换为root用户,否则修改会失败,普通用户不具备修改的权限

普通用户修改会出现如下错误 

su root  将用户切换为root用户

  • 临时修改方案:ulimit -n 8192然后查看 ulimit -a

Linux 出现Too many open files 原因以及解决办法_第3张图片

这种方式只能暂时起作用,比如系统重启后将恢复为原来的设置

  • 彻底修改方案: /etc/security/limits.conf  在文件末尾添加
* soft nofile 8192
* hard nofile 8192

执行如下命令 其中*号代表任意用户 在实际环境中指定为当前用户 如 xxxuser

echo "* soft nofile 8192" >> /etc/security/limits.conf
echo "* hard nofile 8192" >> /etc/security/limits.conf

修改完成后,重启应用,后面就没有出现该问题了,到这里问题是解决了,但是问题原因还是不清楚,到底是什么造成打开文件数过大,后来查看日志文件,以及问题复现,发现是并发访问过多。每一个访问都需要建立Socket连接,而每个Socket连接都有会占用句柄数,连接过多并且释放不及时,很多TCP连接处于CLOSE_WAIT状态,这时候就需要进一步去优化TCP连接参数

如果修改后,程序运行一段时间之后继续出现Too many open files异常,那么就应该查看句柄信息,进一步分析是什么句柄占用最多,排查原因,导出句柄信息到文件 lsof -p pid> lsof.log,筛选出占用句柄前十的信息

cat lsof.log | awk '{print $8}' | sort | uniq -c | sort -rn | head -n 10

然后再进行分析,希望能帮助你解决问题

(转载请注明出处)

你可能感兴趣的:(JAVA,Linux)