java.io.IOException: Too many open files
今天開發(fā)一個(gè)AOP接口需求協(xié)議,在Linux上啟動(dòng)tomcat應(yīng)用的時(shí)候,日志打印出如下錯(cuò)誤:
java.lang.IllegalStateException: failed to create a child event loopat io.netty.util.concurrent.MultithreadEventExecutorGroup.<init>(MultithreadEventExecutorGroup.java:68)at io.netty.channel.MultithreadEventLoopGroup.<init>(MultithreadEventLoopGroup.java:49)at io.netty.channel.nio.NioEventLoopGroup.<init>(NioEventLoopGroup.java:61)at io.netty.channel.nio.NioEventLoopGroup.<init>(NioEventLoopGroup.java:52)at io.netty.channel.nio.NioEventLoopGroup.<init>(NioEventLoopGroup.java:44)at com.hollycrm.hollyuniproxy.server.socket.nio.NettyServer.<init>(NettyServer.java:28)at com.hollycrm.hollyuniproxy.server.http.SocketServerConfigListener.contextInitialized(SocketServerConfigListener.java:44)at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:5003)at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5517)at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652)at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1263)at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1978)at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)at java.util.concurrent.FutureTask.run(FutureTask.java:262)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) Caused by: io.netty.channel.ChannelException: failed to open a new selectorat io.netty.channel.nio.NioEventLoop.openSelector(NioEventLoop.java:128)at io.netty.channel.nio.NioEventLoop.<init>(NioEventLoop.java:120)at io.netty.channel.nio.NioEventLoopGroup.newChild(NioEventLoopGroup.java:87)at io.netty.util.concurrent.MultithreadEventExecutorGroup.<init>(MultithreadEventExecutorGroup.java:64)... 19 more Caused by: java.io.IOException: 打開的文件過多at sun.nio.ch.IOUtil.makePipe(Native Method)at sun.nio.ch.EPollSelectorImpl.<init>(EPollSelectorImpl.java:65)at sun.nio.ch.EPollSelectorProvider.openSelector(EPollSelectorProvider.java:36)at io.netty.channel.nio.NioEventLoop.openSelector(NioEventLoop.java:126)... 22 more查了一些資料,經(jīng)分析發(fā)現(xiàn)原因如下:
原因:
打開的文件過多,一般來說是由于應(yīng)用程序?qū)Y源使用不當(dāng)造成的,比如沒有及時(shí)關(guān)閉socket或數(shù)據(jù)庫連接等。但也可能應(yīng)用確實(shí)需要打開比較多的文件句柄,而系統(tǒng)本身的設(shè)置限制了這一數(shù)量。
操作系統(tǒng)中打開文件的最大句柄數(shù)會(huì)受到系統(tǒng)設(shè)置的限制,常常發(fā)生在很多個(gè)并發(fā)用戶訪問服務(wù)器的時(shí)候。因?yàn)閳?zhí)行每個(gè)用戶的應(yīng)用服務(wù)器都要加載很多文件(new一個(gè)socket就需要一個(gè)文件句柄),這就會(huì)導(dǎo)致打開文件的句柄缺乏。
解決辦法:
盡量把類打成jar包,因?yàn)橐粋€(gè)jar包只消耗一個(gè)文件句柄。如果不打包,一個(gè)類就要消耗一個(gè)文件句柄。java的垃圾回收不能關(guān)閉網(wǎng)絡(luò)連接打開的文件句柄。如果沒有執(zhí)行close()(例如:java.net.Socket.close())則文件句柄將一直存在,而不能被關(guān)閉。你也可以考慮設(shè)置socket的最大打開數(shù)來控制這個(gè)問題。對操作系統(tǒng)做相關(guān)的設(shè)置,增加最大文件句柄數(shù)量。
服務(wù)器端修改:
1、查看系統(tǒng)允許打開的最大文件數(shù)
#cat /proc/sys/fs/file-max2、查看每個(gè)用戶允許打開的最大文件數(shù)
ulimit -a
3、發(fā)現(xiàn)系統(tǒng)默認(rèn)的是open files (-n) 1024,問題就出現(xiàn)在這里。在系統(tǒng)文件/etc/security/limits.conf中修改這個(gè)數(shù)量限制,在文件中加入內(nèi)容(該項(xiàng)操作需要管理員權(quán)限):
* soft nofile 65536 * hard nofile 65536另外方法:
1.使用ps -ef |grep java (java代表你程序,查看你程序進(jìn)程) 查看你的進(jìn)程ID,記錄ID號(hào),假設(shè)進(jìn)程ID為12
2.使用:lsof -p 12 | wc -l 查看當(dāng)前進(jìn)程id為12的 文件操作狀況
執(zhí)行該命令出現(xiàn)文件使用情況為 1052
3.使用命令:ulimit -a 查看每個(gè)用戶允許打開的最大文件數(shù)(針對當(dāng)前session有效,用戶退出或者系統(tǒng)重新后恢復(fù)默認(rèn)值)
4.然后執(zhí)行:ulimit -n 4096
將open files (-n) 1024 設(shè)置成open files (-n) 4096
這樣就增大了用戶允許打開的最大文件數(shù)。問題得以解決。
在這次問題排查中,涉及到的有關(guān)查詢文件句柄以及網(wǎng)絡(luò)連接數(shù)的Linux命令總結(jié)如下:
// 查看服務(wù)器的各種信息 # free -m total used free shared buffers cached Mem: 15901 15742 158 0 127 12784 -/+ buffers/cache: 2830 13070 Swap: 8015 2 8013 // 查看打開的文件數(shù) # lsof -n | wc -l 70091 // 查看網(wǎng)絡(luò)相關(guān)的文件句柄數(shù) # lsof -n -i | wc -l 62548 // 查看網(wǎng)絡(luò)連接數(shù) # netstat -ant | wc -l 63777 // 查看端口為54104的連接數(shù) # netstat -ant | grep ":54104" | wc -l 61101 // 查看端口為54104的各種狀態(tài)的連接數(shù) # netstat -ant | grep ":54104" | awk '{print $6}' | sort | uniq -c | sort -nr 54166 CLOSE_WAIT 6920 ESTABLISHED 10 SYN_RECV 1 LISTEN // 所有網(wǎng)絡(luò)連接數(shù),按狀態(tài)排序 # netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print S[a],a}' | sort -nr 54184 CLOSE_WAIT 8239 ESTABLISHED 926 FIN_WAIT2 207 FIN_WAIT1 64 TIME_WAIT 46 LAST_ACK 31 SYN_RECV 1 CLOSING // 所有打開文件數(shù),按進(jìn)程PID排序 # lsof -n | awk '{print $2}' | sort -n | uniq -c | sort -nr | more 65605 18374 741 1348 313 1349 236 1350 149 18407總結(jié)
以上是生活随笔為你收集整理的java.io.IOException: Too many open files的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【JVM性能调优】使用jstack找出最
- 下一篇: 【Apache JMeter】JMete