`
langyu
  • 浏览: 883808 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

详解 Too many open files

    博客分类:
  • java
阅读更多

        运行在Linux系统上的Java程序可能会出现"Too many open files"的异常情况,且常见于高并发访问文件系统,多线程网络连接等场景。

        程序经常访问的文件、socket在Linux中都是文件file,系统需要记录每个当前访问file的name、location、access authority等相关信息,这样的一个实体被称为file entry。“open files table”(图中橙色标识)存储这些file entry,以数组的形式线性管理。文件描述符(file descriptor)作为进程到open files table的指针,也就是open files table的下标索引,将每个进程与它所访问的文件关联起来了。




        每个进程中都有一个file descriptor table管理当前进程所访问(open or create)的所有文件,文件描述符关联着open files table中文件的file entry。细节不表,对于open files table能容纳多少file entry。Linux系统配置open files table的文件限制,如果超过配置值,就会拒绝其它文件操作的请求,并抛出Too many open files异常。这种限制有系统级和用户级之分。

       系统级:
                系统级设置对所有用户有效。可通过两种方式查看系统最大文件限制
                1  cat /proc/sys/fs/file-max 
                2  sysctl -a 查看结果中fs.file-max这项的配置数量
                如果需要增加配置数量就修改/etc/sysctl.conf文件,配置fs.file-max属性,如果属性不存在就添加。
                配置完成后使用sysctl -p来通知系统启用这项配置


       用户级:
                Linux限制每个登录用户的可连接文件数。可通过  ulimit -n来查看当前有效设置。如果想修改这个值就使用 ulimit -n <setting number> 命令。

              对于文件描述符增加的比例,资料推荐是以2的幂次为参考。如当前文件描述符数量是1024,可增加到2048,如果不够,可设置到4096,依此类推。

       在出现Too many open files问题后,首先得找出主要原因。最大的可能是打开的文件或是socket没有正常关闭。为了定位问题是否由Java进程引起,通过Java进程号查看当前进程占用文件描述符情况:
lsof -p $java_pid 每个文件描述符的具体属性
lsof -p $java_pid | wc -l  当前Java进程file descriptor table中FD的总量

        分析命令的结果,可判断问题是否由非正常释放资源所引起。




文件描述符资料 : 简介      PDF下载
  • 大小: 25.7 KB
2
1
分享到:
评论
6 楼 来迟了 2015-06-02  
cl1_1_1 写道
ulimit -n <setting number>
不知道为啥,还是会报错 java.net.SocketException: socket failed: EMFILE (Too many open files)

我也是不尽报Too many open files的异常,就连后面连接数据的代码也一起报错The Network Adapter could not establish the connection,在出现Too many open files的异常前数据库是可以连上的,之前的数据都进数据库了。。。。
5 楼 tuzi37 2014-05-18  
牛掰~~~~
4 楼 cl1_1_1 2013-08-09  
ulimit -n <setting number>
不知道为啥,还是会报错 java.net.SocketException: socket failed: EMFILE (Too many open files)
3 楼 MyDream83 2011-01-03  
2 楼 langyu 2010-12-31  
MyDream83 写道

但想到一个问题 log4j也是多线程写同一个日志文件,为什么会不报这个系统错误呢?
写日志的时候也没有做线程同步

只是我们在用的时候没有看到线程同步,但底层肯定是做了,不然一个线程的一行还没有写完,会被其它线程打断。我们只见过多线程写log时log行不固定,但没见过一行中出现不同线程操作结果的。

贴出apache-log4j-1.2.16中log同步的代码
public void callAppenders(LoggingEvent event) {
    int writes = 0;

    for(Category c = this; c != null; c=c.parent) {
      // Protected against simultaneous call to addAppender, removeAppender,...
      synchronized(c) {
	if(c.aai != null) {
	  writes += c.aai.appendLoopOnAppenders(event);
	}
	if(!c.additive) {
	  break;
	}
      }
    }

    if(writes == 0) {
      repository.emitNoAppenderWarning(this);
    }
  }
1 楼 MyDream83 2010-12-30  
研究的很透彻!
想请教个问题,  我写了个socket服务端,多线程的, 处理异常时会写nohup.out
一段时间后就too many open files, 后来想办法捕获了异常,
但想到一个问题 log4j也是多线程写同一个日志文件,为什么会不报这个系统错误呢?
写日志的时候也没有做线程同步

相关推荐

Global site tag (gtag.js) - Google Analytics