linux 下日志 too many open files 异常

too many open files 异常

项目运行过程中出现了too many open files 这种错误,查了linux配置 和代码工程,初步有了解决问题的思路,先记录下来。

  • 工程报错
  • 错误分析
  • 资料收集
  • 原因分析
  • 代码复查

工程报错

最近项目因为要跑定时任务而且频率非常大,在项目运行一段之后,在日志里面就报错too many open files。

linux 下日志 too many open files 异常_第1张图片

[2017-09-26 09:20:08] [WARN] [New I/O server boss #1 ([id: 0x37cac656, /0:0:0:0:0:0:0:0:20783])] com.alibaba.dubbo.remoting.transport.netty.NettyHelper$DubboLogger.warn(NettyHelper.java:90) -  [DUBBO] Failed to accept a connection., dubbo version: 5.0.2, current host: 127.0.0.1
java.io.IOException: Too many open files
        at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
        at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:241)
        at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink$Boss.run(NioServerSocketPipelineSink.java:244)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)

错误分析

在网络上搜索了下问题,发现大部分都给出的修改linux的配置参数来解决问题。
-http://www.blogjava.net/fly2008/archive/2009/08/26/292626.html

主要修改参数是open files 这个参数,系统默认大小是1024。

资料收集

查看系统允许打开的最大文件数:
cat /proc/sys/fs/file-max
查看每个用户允许打开的最大文件数:
ulimit -a
发现系统默认的是open files (-n) 1024,问题就出现在这里。
在系统文件/etc/security/limits.conf中修改这个数量限制,
在文件中加入内容:
* soft nofile 65536
* hard nofile 65536
另外方法:
1.使用ps -ef |grep java (java代表你程序,查看你程序进程) 查看你的进程ID,记录ID号,假设进程ID为12
2.使用:lsof -p 12 | wc -l 查看当前进程id为12的 文件操作状况
执行该命令出现文件使用情况为 1052
3.使用命令:ulimit -a 查看每个用户允许打开的最大文件数
发现系统默认的是open files (-n) 1024,问题就出现在这里。
4.然后执行:ulimit -n 4096
将open files (-n) 1024 设置成open files (-n) 4096

原因分析

好吧,修改环境参数就修改环境参数吧,我通过linux命令,查看服务器的参数配置,结果如下:
linux 下日志 too many open files 异常_第2张图片
可以看得出,目前系统的配置参数就是默认参数 大小1024 ,这样的话系统根本不够用,而时间文件句柄打开的大小是这样的:
这里写图片描述
实际产生的句柄达到了 4160个,远远大于1024,当然会报错了。
通过命令lsof -p 进程号 可以发现系统打开的文件句柄基本都是重复的文件。
linux 下日志 too many open files 异常_第3张图片

想了下问题原因,发现解决这种问题,也只有2种方法了。
1.修改linux系统参数,
通过设置open files的大小,可以设置为10240,这样就能避免程序跑到一定的时间再次出现这种问题。
但是想想这种办法还是指标不治本,如果java程序一直在产生句柄,只要服务一直运行,总有一天会达到最大值,而且对服务器的性能要求也很高。
2.优化java代码
java工程里面的所有的句柄都是以文件的形式打开的,那就在读取完毕后,将文件进行关闭。这样才能从根本上减少文件句柄的打开次数,避免这个错误。

代码复查

结合优化代码这个思路,仔细分析了下代码中打开文件的地方,特别的针对linux环境打开文件句柄较多的文件进行了分析,分析后发现在编码过程中只有打开文件而没有关闭文件。所以这就是问题的根本原因了。

##问题代码##
    public void init(){
        pro = new Properties();
        try {             pro.load(this.getClass().getResourceAsStream("/cfg/properties/cloudConfig.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
##优化后的代码##
    public void init(){
        pro = new Properties();
        try {           //pro.load(this.getClass().getResourceAsStream("/cfg/properties/cloudConfig.properties"));
            InputStream in = this.getClass().getResourceAsStream("/cfg/properties/cloudConfig.properties");
            pro.load(in);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

文件打开就要关闭,养成良好习惯是关键。

你可能感兴趣的:(异常,linux,java)