以下是我解决Too many open files异常时学习的知识的理解和总结,如有不正确指出,敬请指出!

此问题中文搜索雷同,你可以尝试以下关键字:"file descriptor leak" "stackoverflow" "how to solve open files exception“等。

一下是我的一些总结,或许对您有所帮助!

1.fd
fd is short for file descriptor
在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件,
应用程序就是通过fd识别该文件/设备/服务..
你可能需要自行了解更多fd的定义及功能知识。

2.lsof
linux下的命令, 全称:list system open files
第1节说linux所有资源都是以file形式的,所以这个lsof命令是我们查看系统资源占用情况的得力工具。排查linux下各种资源耗尽,异常
等问题都可以使用它。中文能找到的几乎都是这种http://www.cnblogs.com/ggjucheng/archive/2012/01/08/2316599.html,以下为引用:

在终端下输入lsof即可显示系统打开的文件,因为 lsof 需要访问核心内存和各种文件,所以必须以 root 用户的身份运行它才能够充
      地发挥其功能。直接输入lsof部分输出为:

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
          init 1 root cwd DIR 8,1 4096 2 /
          init 1 root rtd DIR 8,1 4096 2 /
          init 1 root txt REG 8,1 150584 654127 /sbin/init
          udevd 415 root 0u CHR 1,3 0t0 6254 /dev/null
          udevd 415 root 1u CHR 1,3 0t0 6254 /dev/null
          udevd 415 root 2u CHR 1,3 0t0 6254 /dev/null
          udevd 690 root mem REG 8,1 51736 302589 /lib/x86_64-linux-gnu/libnss_files-2.13.so
          syslogd 1246 syslog 2w REG 8,1 10187 245418 /var/log/auth.log
          syslogd 1246 syslog 3w REG 8,1 10118 245342 /var/log/syslog
          dd 1271 root 0r REG 0,3 0 4026532038 /proc/kmsg
          dd 1271 root 1w FIFO 0,15 0t0 409 /run/klogd/kmsg
          dd 1271 root 2u CHR 1,3 0t0 6254 /dev/null

每行显示一个打开的文件,若不指定条件默认将显示所有进程打开的所有文件。
          lsof输出各列信息的意义如下:
          COMMAND:进程的名称 PID:进程标识符
          USER:进程所有者
          FD:文件描述符,应用程序通过文件描述符识别该文件。如cwd、txt等 TYPE:文件类型,如DIR、REG等
          DEVICE:指定磁盘的名称
          SIZE:文件的大小
          NODE:索引节点(文件在磁盘上的标识)
          NAME:打开文件的确切名称

你可能需要自行了解lsof命令使用细节

3. fix too many open files excepiton(POSIX)

a. 网上尤其使用baidu搜出来的答案几乎全是“ulimit -n”查看最大能打开的fd的限制值,通常是 1024(意思是最多能打开1024个),然后
     使用“ulimit -n 4096”调大该限制。这里先下个结论,这个解决方案是碰运气式的,详情且看下面分解。

b. too many open files 出现的原因:

》第1节有说,linux(POSIX)所有存在都是以file形式表示的,所以引起这个异常的原因(几乎)就是你打开了太多‘files’,超过了限制。
         那a中调大限制的方法明显可以用啊。下面这段话给出了不推荐这样做的理由:

摘自http://oroboro.com/file-handle-leaks-server/
            Wrong Answers, Myths and Bad Ideas
            Raise the file handle limit
               One common answer to this problem is to just raise the limit of open file handles and then restart the server every
           day or every few hours.
               This will delay the problem but likely will not fix it. It is possible that your program is not leaking and has a
           legitimate need to hold a large number of file handles. But if your program is designed correctly there usually isn’t
           a need to keep a large number of handles open – even if you have thousands of simultaneous connections. We’ll discuss
           some methods of managing that later.
                If this was a good idea the operating system would already come configured with a higher file descriptor limit. If
           this was necessary, Apache would require you to up this limit before running.

》原因(大多数时候)

The problem is almost certainly that you are leaking file handles. That is, handles are being opened, and after you are
           done with them they are not closed.

Leaked file handles can come from many sources, not just open files. Some common sources are:Sockets,Pipes,Database
           connections,Windows HANDLES,Files.

c. 如何排查及修复(重点)

》当不满足于“ulimit -n 4096”的解决方案,深入想要分析原因时,搜索到的分析方法也大同小异,大多和lsof命令相关,以下罗列一些;

=.To find out PID for mysqld process, enter: pidof mysqld #pidof命令是找出进程的id号,如pidof java找到Java进程的id号
          =.List File Opened By a PID:lsof -p ${pid} #-p 参数是 --pid的意思, 如 lsof -p 10086是打印10086进程的所有open files
              或者 ls /proc/${pid}/fd #和上行一样,查看该进程打开的files
          =.List File Descriptors in Kernel Memory
              sysctl fs.file-nr #结果:fs.file-nr = 2688 0 379264
          => The number of allocated file handles
          => The number of unused-but-allocated file handles
          => The system-wide maximum number of file handles
                 sysctl fs.file-max #结果是能打开的最大files数量
          =.查看某个用户下打开的files: lsof -u jboss
          =.和计数器结合起来,计算打开的文件数量,如:lsof -p 10086|wc -l, ls -alt /etc/10086/fd|wc -l等等。
        这些分析方法大多是利用lsof配合参数和管道命令,或者是统计/proc/${pid}/fd目录,来分析你的目标的openfiles情况。

》困惑

=. lsof -u root |wc -l 结果是2223, 而ulimit -n 结果是1024, 为什么root用户当前的open files还要比limit大? 这个如果不清楚那
              分析就没意义了,因为你就是要解决open file limit问题的,结果root当前运行时就打开了比limit还多的files.
          =. lsof -p 54552|wc -l 结果是658,54552是我java的进程pid, 而ll /proc/54552/fd |wc -l,结果却是358,为什么统计同一个进程当前
              的open files数量却有如此大的差异? 以哪个为准,和ulimit -n的值有有什么关系?
          =. 先解释第2点,lsof will also give you memory mapped .so-files - which technically isn't the same as a file handle the
               application has control over. /proc/<pid>/fd is the measuring point for open file descriptors。 意思是说lsof的结果包含
               memory mapped .so-files,这些在原理上并不是一般的应用程序控制的fd。 而/proc/<pid>/fd目录很好的反映了fd的open情况。
               适当修改下lsof: lsof -p <pid> | grep -v mem | egrep -v '^COMMAND PID' | wc -l,这样就等同于/proc/<pid>/fd下统计情况。
          =. 是第2点的问题引起了第1点?使用lsof -u root |grep -v mem | egrep -v '^COMMAND PID' | wc -l, 结果是 1221,还是大于limit.
              就是说root用户当前open 1221 files是确定定, root 的 files limit是1024也是确定的, 而造成more than limit究竟为何:其实是
              limit这个限制针对的对象,最终找出是这样的:because the limit is on a per-process base and not per-user 。 limit限制是基于
              一个进程而言的(该用户拥有的进程)并非用户。 就是ulimit -n是1024的意思是由root用户执行的某个进程最多只能打开1024个文件,
              并非root总共只能打开1024个。
          =. sysctl fs.file-max 我的结果是379264,这个数字则是kenel内核总共能支持的open files数量。这个是不能改变的。

》解决

=. 至此可以解释为啥放大limit是碰运气式的,毕竟一个process正常情况下同时要打开超过1024个files还是比较少见的。
          =. 如果需分析leak或者查看open fiels的细节, 则应从pid粒度着手,而不要被user迷惑。
                 lsof -p <pid> | grep -v mem | egrep -v '^COMMAND PID'
                 或者对/proc/<pid>/fd 目录分析。
          =. uprize limit
               即使需要扩大limit限制,实际上大多是os上简单的“ulimit -n 4096”是行不通的,操作系统不允许。 以下两种方式供参考
                 Raising the Global Limit。Edit /etc/sysctl.conf and add the following line:fs.file-max = 65536
                                                     Apply the changes with:sudo sysctl -p /etc/sysctl.conf
                 Raising the per-User Limit.
                     &Edit as root the following system configuration file: % sudo vi /etc/security/limits.conf
                     &Modify the values for nuxeo user (we assume here JBOSS is launched with the sytem user "nuxeo")
                               nuxeo soft nofile 4096
                               nuxeo hard nofile 8192
                        If you want to raise the limits for all users you can do instead:
                               * soft nofile 4096
                               * hard nofile 8192
                     &Edit /etc/pam.d/su: sudo vi /etc/pam.d/su
                     &Uncomment the line:
                            session required pam_limits.so
                     &Once you save file, you may need to logout and login again

d.总结

扩大open files数量限制的操作可以起效,但在此之前相比你应该也对为何出错会感兴趣吧,不妨先分析一下喽。

以上总结中的观点是网上各处搜罗及个人理解所得,如有误,请谅解指正。

Too many open files解决方案及原理的更多相关文章

  1. 转发 win7+iis7.5+asp.net下 CS0016: 未能写入输出文件“c:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files 解决方案

    win7+iis7.5+asp.net下 CS0016: 未能写入输出文件“c:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NE ...

  2. Zookeeper- Error contacting service. It is probably not running解决方案和原理

    搭建启动Zookeeper集群出现Error contacting service. It is probably not running解决方案和原理 1.关闭防火墙  [root@srv01 bi ...

  3. 线程间操作无效: 从不是创建控件“”的线程访问它~~~的解决方法~ 线程间操作无效: 从不是创建控件“Control Name'”的线程访问它问题的解决方案及原理分析

    看两个例子,一个是在一个进程里设置另外一个进程中控件的属性.另外一个是在一个进程里获取另外一个进程中控件的属性. 第一个例子 最近,在做一个使用线程控制下载文件的小程序(使用进度条控件显示下载进度)时 ...

  4. (转)win7+iis7.5+asp.net下 CS0016: 未能写入输出文件“c:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files 解决方案

    本文转载自:http://www.cnblogs.com/finesite/archive/2011/01/28/1946940.html 网上搜的解决方案但在我的环境下仍旧没有解决,我的方法如下: ...

  5. CS0016: 未能写入输出文件“c:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files 解决方案

    1 设置c:windows\temp 目录访问权限 temp--> 属性-->安全-- > 添加network service -->并赋予其权限为 读 和 写--> 确 ...

  6. win7+iis7.5+asp.net下 CS0016: 未能写入输出文件“c:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files 解决方案

    http://www.cnblogs.com/finesite/archive/2011/01/28/1946940.html 给C:\Windows\temp 文件夹赋予完全控制权限,如图:

  7. mina高并发短连接导致java.io.IOException: Too many open files解决方案

    http://marsvaadin.iteye.com/blog/1698924 mina性能测试 http://hi.baidu.com/rendong/item/bb5d2b0e4563c76dd ...

  8. WebApi中跨域请求的解决方案和原理

    跨域请求仅发生在JavaScript发起Ajax请求时,浏览器对请求的限制,通常只允许访问同一个域中的资源,或者目标服务器明确的通知浏览器允许该域访问资源. 那么什么叫跨域的:主机地址或者ip地址或者 ...

  9. Atitit.js跨域解决方案attilax大总结 后台java php c#.net的CORS支持

    Atitit.js跨域解决方案attilax大总结 后台java php c#.net的CORS支持 1. 设置 document.domain为一致  推荐1 2. Apache 反向代理 推荐1 ...

随机推荐

  1. UNP学习笔记(第十八章 路由套接字)

    路由套接字上支持3种类型的操作 1). 进程能通过写路由套接字向内核发消息. 2). 进程能通过路由套接字从内核读消息. 3). 进程可以用sysctl函数得到路由表或列出所有已配置的接口. 数据链路 ...

  2. struts2获取ServletContext对象

      CreateTime--2017年9月7日09:24:40 Author:Marydon struts2获取ServletContext对象 需要导入: import javax.servlet. ...

  3. JS批量获取参数构建JSON参数对象

    在做系统的时候,往往查询条件是被严格指定的,大量的查询条件,一两个页面还可以通过dom去一个一个获取,再构建参数对象,请求后台接口. 这里给大家讲一个批量获取前端参数,构建参数对象. <form ...

  4. centOS 7中上网以及网卡的一些设置

    在VMWare中安装LinuxOS是个非经常见的事情. 可是,关于虚拟机的上网问题.想在这里总结一下,里面还有不懂的问题.希望能够得到前辈的解惑. 一.VMWare网卡的设置的三种选项: Bridge ...

  5. 最短路 uva12661 Funny Car Racing

    传送门:点击打开链接 题意:给你有向图,每条边呈周期性开放,即开放a时间,再关闭b时间.再开放a时间以此类推 假设时间不足以穿过这条路则不能走.你能够在节点等待时间,问从s走到t所须要的最小时间 细致 ...

  6. ExtJs4学习(二):Dom操作

    如今主流的JS框架要数ExtJs和JQuery应用的比較广泛.JQuery属于轻量级的,一般做站点应用比較常见.可见块头小的优势. ExtJs比較庞大,它除了对主要的JS语法和HTML DOM操作方式 ...

  7. Centos内核版本升级

  8. JBoss AS 7之域名直接訪问配置(The Return Of The King)

    1.6域名直接訪问配置 部署JBoss的时候,默认情况下訪问是须要加项目名字才可以訪问的. 可是怎样才可以"IP+port"訪问呢?以下将解说怎样配置. 配置域名訪问须要在项目以下 ...

  9. linux 改动rootpassword以及忘记rootpassword

    改动rootpassword: $ passwd root 或者sudo passwd root $password:  (要求输入旧的密码) $new  password:(输入两遍新密码) 忘记r ...

  10. 开源监控系统Prometheus介绍

    前言 Prometheus是CNCF的一个开源项目,Google BorgMon监控系统的开源版本,是一个系统和服务的监控系统.周期性采集metrics指标,匹配规则和展示结果,以及触发某些条件的告警 ...