分享好友 最新动态首页 最新动态分类 切换频道
java.io.IOException: Too many open files问题
2024-12-26 21:01

在开发linux在线服务器的时候经常会遇会句柄泄露的问题。因为在linux系统设计里面遵循一切都是文件的原则,即磁盘文件、目录、网络套接字、磁盘、管道等,所有这些都是文件,在我们进行打开的时候会返回一个fd,即是文件句柄。如果频繁的打开文件,或者打开网络套接字而忘记释放就会有句柄泄露的现象。在linux系统中对进程可以调用的文件句柄数进行了限制,在默认情况下每个进程可以调用的最大句柄数是1024个,如果超过了这个限制,进程将无法获取新的句柄,而从导致不能打开新的文件或者网络套接字,对于线上服务器即会出现服务被拒绝的情况。

查看句柄

在linux系统中可以通过ulimit–n查看每个进程限制的最大句柄数,通过ulimit –HSn 10240修改进程的最大句柄数。当句柄数目达到限制后,就回出现”too many files open”。

查看进程占用的句柄数有几种办法

1) 通过cat/proc/pid/fd可以查看线程pid号打开的线程,cat   /proc/pid/fd |wc -l

2) 通过lsof命令,需要root账号权限

查看当前系统的打开文件数

# lsof | wc -l  

# watch "lsof | wc -l"

可以用lsof -p <pid of process>看打开的文件句柄数.查看某个进程的打开文件数

#lsof -p  1234|wc -l

 

查看Linux系统打开的文件句柄数

# lsof -n | awk '{print $2}'| sort | uniq -c | sort -nr 

   3009 31312
     15 7364
     14 8002
     14 7777
     14 7382
     14 665
     14 6308
     ...
第一列:进程打开的文件句柄数
第二列:PID

 

应用日志报java.io.IOException: Too many open files

打开的文件过多,一般来说是由于应用程序对资源使用不当造成,比如没有及时关闭Socket或数据库连接等。但也可能应用确实需要打开比较多的文件句柄,而系统本身的设置限制了这一数量。

 

异常 1 
java.net.SocketException: Too many open files

    at java.net.PlainSocketImpl.accept(Compiled Code)
    at java.net.ServerSocket.implAccept(Compiled Code)
    at java.net.ServerSocket.accept(Compiled Code)
    at weblogic.t3.srvr.ListenThread.run(Compiled Code)

异常 2
java.io.IOException:打开的文件过多

    at java.lang.UNIXProcess.forkAndExec(Native Method)
    at java.lang.UNIXProcess.(UNIXProcess.java:54)
    at java.lang.UNIXProcess.forkAndExec(Native Method)
    at java.lang.UNIXProcess.(UNIXProcess.java:54)
    at java.lang.Runtime.execInternal(Native Method)
    at java.lang.Runtime.exec(Runtime.java:551)
    at java.lang.Runtime.exec(Runtime.java:477)
    at java.lang.Runtime.exec(Runtime.java:443)

...

第一个异常在错误影响到基础 TCP 协议时抛出,而第二个异常则在错误影响到 I/O 操作时抛出,这个是由于交换分区不足造成的。

文件打开数过多最坏的情况可以使系统崩溃,到时候只能是重起服务器了。 

 

原因:  

 1、大多数情况是程序没有正常关闭一些资源引起的,所以出现这种情况,请检查io读写,socket通讯等是否正常关闭。

  操作系统的中打开文件的最大句柄数受限所致常常发生在很多个并发用户访问服务器的时候。因为为了执行每个用户的应用服务器都要加载很多文件(new一个socket就需要一个文件句柄),这就会导致打开文件的句柄的缺乏。 

       主要方向:在源码项目中查找所有引用了InputStream或者其他流的地方,查看其是否在使用完后,正常close掉,此处建议将流的close放到finally块中,这样异常时也会去close流。

       次要方向:session或者其他有用到socket的代码处,仔细查询看是否有没有释放资源的地方

 
   2、 如果检查程序没有问题,那就有可能是linux默认的open files值太小,不能满足当前程序默认值的要求,比如数据库连接池的个数,tomcat请求连接的个数等。。。 

         限制:有时是linux系统的参数的限制,需要修改内核参数。有时是中间件(weblogic、nginx)中启动文件参数限制,尤其是默认1024,在修改linux后若中间件有涉及也要同步修改。

      

 

解决:

尽量把类打成jar包,因为一个jar包只消耗一个文件句柄,如果不打包,一个类就消耗一个文件句柄.
java的垃圾回收不能关闭网络连接打开的文件句柄,如果没有执行close()(例如:java.net.Socket.close())则文件句柄将一直存在,而不能被关闭.你也可以考虑设置socket的最大打开数来控制这个问题.
对操作系统做相关的设置,增加最大文件句柄数量。


Linux
在 Linux内核2.4.x中需要修改源代码,然后重新编译内核才生效。编辑Linux内核源代码中的 include/linux/fs.h文件,将 NR_FILE 由8192改为65536,将NR_RESERVED_FILES 由10 改为 128。编辑fs/inode.c 文件将MAX_INODE 由16384改为262144。或者编辑 /etc/sysctl.conf  文件增加两行 fs.file-max = 65536 和 fs.inode-max = 262144 。一般情况下,系统最大打开文件数比较合理的设置为每4M物理内存256,比如256M.

 

在linux下的fd是有限制的,一个是系统的限制,一个是用户进程限制。

 

服务器端修改

查看系统允许打开的最大文件数

#cat /proc/sys/fs/file-max

sysctl fs.file-max=655360可以调整内核的阈值,前提得有root权限。可参考/etc/sysctl.conf,用man sysctl.conf命令sysctl -a可以显示所有的能够调整参数。

 

查看每个用户允许打开的最大文件数

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

这样就增大了用户允许打开的最大文件数

 

同时查看ulimit实际是否生效,如果设置了但并未生效也不行。

运维实战案例之“Too many open files”错误与解决方法 

此文中就介绍了设置了参数,但并未生效引起的。

 

 

socket未关闭现象

1. 首先用lsof -p PID 查看一下打开文件的列表如果出现下图状况基本就两种可能,stream未关闭或者socket未关闭,出现can't identify protocol字样

2. 用netstat -anp | grep PID查看端口占用情况,若出现下图情况,证明Socket未关闭

原因

  是因为Socket协议本身,若正确关闭一个Socket需要往返消息4次,若中途有未接到的消息就会停留在某个状态下,比如当前的CLOSE_WAIT。

        如果close_wait状态过多,可能是socket未关闭引起。

解决办法

  客户端:主动关闭任何一个socket,尽量在finally中加入socket.close()语句。

  服务器:设置读取超时时间如:socket.setSoTimeout(3000);其次在用完之后主动关闭,做法同客户端方式。同时在任何的异常加入socket.shutdownInput();socket.shutdownOutput();

 

问题定位

问题定位步骤
1、   用root帐户 遍历 /proc/进程ID/fd目录,若该目录下文件数较大(如果大于10一般就属于socket泄漏,根据该进程ID,可以确认该进程ID所对应的名称。
2、   重启程序恢复服务,以便后续查找问题。
3、   strace 该程序并记录strace信息。strace –p 进程ID >>/tmp/stracelog.log 2>&1
4、   查看 /proc/进程ID/fd 下的文件数目是否有增加,如果发现有增加,记录上一个socket编号,停止strace
5、   确认问题代码的位置。打开/tmp/stracelog.log,从尾部向上查找close(socket编号)所在行,可以确认在该次close后再次创建的socket没有关闭,根据socket连接的server ip可以确认问题代码的位置。


另一种方法:判断是否有socket泄漏:
lsof | grep "can't identify protocol"
如果存在很多,则代表socket泄漏,同时会显示哪个进程使用的sock未关闭。

 

文件句柄泄露定位方法

1、使用lsof命令查出有哪些文件或者socket被打开。

2、根据文件名找到相应的模块,检查相关的代码.如果是socket,则根据端口号找到相应的模块,最后检查相关的代码。

 

 

 


 

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

  1.         //设置超时   
  2.         connector.setConnectTimeoutMillis(defaultConnectTimeOut);  
  3.         ConnectFuture connectFuture = connector.connect(address);  
  4.         connectFuture.awaitUninterruptibly();   //同步,等待,直到连接完成   
  5.         if  (connectFuture.isDone()) {  
  6.             if  (!connectFuture.isConnected()) {  //若在指定时间内没连接成功,则抛出异常   
  7.                 logger.info("fail to connect "  + logInfo);  
  8.   
  9.                 throw   new  Exception();  
  10.             }  
  11.         }  

 

         经过分析导致主机文件句柄泄露的原因为,客户端发起服务端连接时,会请求系统分配相关的文件句柄,在原代码中,仅仅判断是否连接成功,而未对连接失败进 行资源释放,从而造成文件句柄泄露。当总的文件句柄数超过系统设置值(ulimit -n 查看同一个进程允许的最大文件句柄数,则抛出异常“java.io.IOException: Too many open files",导致无法创建新的连接,服务器挂掉。

      更改后的代码如下

 

Java代码  

  1. final  NioSocketConnector connector =  new  NioSocketConnector();  
  2.         final  String[] result =  new  String[ 1 ];  
  3.         connector.getFilterChain().addLast("codec" ,  
  4.                 new  ProtocolCodecFilter( new  ObjectSerializationCodecFactory()));  
  5.         connector.setHandler(handler);  
  6.   
  7.         //设置超时   
  8.         connector.setConnectTimeoutMillis(defaultConnectTimeOut);  
  9.         ConnectFuture connectFuture = connector.connect(address);  
  10.         connectFuture.awaitUninterruptibly();   //同步,等待,直到连接完成   
  11.         if  (connectFuture.isDone()) {  
  12.             if  (!connectFuture.isConnected()) {  //若在指定时间内没连接成功,则抛出异常   
  13.                 logger.info("fail to connect "  + logInfo);  
  14.                 connector.dispose();    //不关闭的话会运行一段时间后抛出,too many open files异常,导致无法连接   
  15.   
  16.                 throw   new  Exception();  
  17.             }  
  18.         }  

 


 

from http://www.jianshu.com/p/2e6748c4c0b7

 

原因一:Linux 的open files 数不够

 

原因二:TCP 参数配置不对

常用的三个状态是:ESTABLISHED 表示正在通信,TIME_WAIT 表示主动关闭,CLOSE_WAIT 表示被动关闭
服务器保持了大量TIME_WAIT状态

配置生效后,观察结果,TIME_WAIT 明显减少。

原因三:Tomcat 配置不对

connectionTimeout - 网络连接超时,单位:毫秒。设置为0表示永不超时,这样设置有隐患的。通常可设置为30000毫秒。
当前配置connectionTimeout=0

根据公式:服务器端最佳线程数量=((线程等待时间+线程cpu时间)/线程cpu时间) * cpu数量

待测试验证

 

原因四:程序打开了许多文件,但未关闭连接

之前一直在找程序哪里打开了文件却未关闭连接,未果。
才想到连接打开后,多久可以关闭。

待解决的问题是
)如何定位到程序代码什么地方打开了文件
)打开的这些文件是不是都是必要的
)can't identify protocol的原因

 

 

参考资料

1、http://www.2cto.com/kf/201212/175863.html

2、http://marsvaadin.iteye.com/blog/1698924

3、MINA2 错误解决方法-- Linux下tomcat报错“java.net.SocketException: Too many open files”

4、tcp socket文件句柄泄漏

最新文章
天翼云盘电脑版官方正版2024最新版绿色免费下载安装
天翼云是中国电信旗下云存储产品,是基于云计算技术的个人/家庭云数据中心,能够提供文件同步、备份及分享等服务的网络云存储平台。您可以通过网页、PC客户端及移动客户端随时随地的把照片、音乐、视频、文档等轻松地保存到网络,无须担心
中共淄博市发展和改革委员会党组关于十三届市委第一轮巡察暨黄河流域生态保护和高质量发展专项巡察整改进展情况的通报
根据市委统一部署,2022年6月23日至8月31日,市委第五巡察组对市发展改革委党组开展了巡察。10月27日,市委第五巡察组向市发展改革委党组反馈了巡察意见。2022年10月31日至2023年2月1日,我单位对市委巡察组反馈的问题进行了认真整改,目前
蔬菜项目管理软件,让农业种植更高效
软件可以帮助用户根据气候条件、土壤类型、市场需求等因素,制定科学的种植计划。通过模拟种植周期和预测产量,用户可以更好地规划种植资源和时间安排。实时监测土壤湿度、温度、光照强度等关键环境因素,确保作物在最佳条件下生长。通过物
微博推广目的有哪些
微博是众多的具有影响力的社交媒体平台之一,拥有庞大的用户基础和活跃的社交氛围。对于企业和个人来说,利用微博进行推广可以获得广泛的曝光和增加品牌知名度。下面就和鱼爪网一起了解一下微博推广的目的有哪些吧。微博推广的目的有哪些1
喵趣漫画app官方版 v1.0.8
  喵趣漫画app官方版是一款免费的漫画阅读平台(曾用名:喵上漫画、喵呜漫画),全网国内外漫画免费阅读,国产漫画、日本漫画、韩国漫画、欧美漫画,耽美爱情、百合、真人漫画、少年漫画、少女漫画、青年漫画、玄幻科幻、冒险热血、修真
解剖十大电商平台付费会员设计“套路”
解剖十大电商平台付费会员设计“套路”「开氪」君 · 1分钟前划到文末,21天,带你构建一套「可持续增长」的会员体系。文/开氪君对于一个企业而言,怎么设计一个好的付费会员政策?根据我们的经验,设计付费会员政策是有一定套路的,我们
美拟对华芯片贸易实施更严厉管制;ASML卖百台光刻机,尼康同表态中国大陆为重要市场;大基金二期成立硅材料公司;存储超级周期回归
1.美向盟国施压拟就对华芯片贸易实施更严厉管制 外交部:希望相关国家坚决抵制胁迫2.大基金二期、沪硅产业等成立硅材料技术公司 注册资本55亿元3.存储超级周期回归 三大DRAM厂利润差距或拉大至千亿元4.库存改善叠加终端需求回暖,带动这些
百度竞价助理
*^__^*我们需要这样的你:1、理解能力强,有良好的沟通能力和不错的策划能力;2、性格阳光开朗、温和自信、与人为善,追求生活品质;3、有不错的创意能力和较好的文案撰写功底者优先;4、熟悉互联网,有百度竞价、今日头条等竞价广告经验者
搜狗收录、蜘蛛池与百度推广,深度解析与策略构建,搜狗蜘蛛池霸屏秒收录神器
搜狗收录、蜘蛛池与百度推广是提升网站排名和曝光度的有效工具。搜狗收录通过优化网站内容和结构,提高网站在搜狗搜索引擎中的排名;蜘蛛池则通过模拟搜索引擎爬虫行为,加速网站内容的抓取和收录;百度推广则通过投放广告,提高网站在百度
淘宝创建直播怎么弄?开通淘宝直播的条件是什么?(淘宝直播开通后怎么做)
现在想要做直播的商家可以说是越来越多了,商家们如果想要做淘宝直播的话,是一定要创建直播间的,淘宝创建直播也都有一定的技巧,那么具体如何去操作呢?下面的内容中为大家进行相关的介绍。淘宝创建直播怎么弄?1、下载“淘宝主播”APP2,
相关文章
推荐文章
发表评论
0评