今天某個服務(wù)的日志中出現(xiàn)了大量的異常:
[WARN ] 2018-06-15 16:55:20,831 --New I/O server boss #1 ([id: 0x55007b59, /0.0.0.0:20880])-- [org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink] [DUBBO] Failed to accept a connection., dubbo version: 2.8.3.2, current host: 127.0.0.1
java.io.IOException: Too many open files
at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method) ~[na:1.7.0_09-icedtea]
at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:226) ~[na:1.7.0_09-icedtea]
at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink$Boss.run(NioServerSocketPipelineSink.java:244) ~[netty-3.2.5.Final.jar:na]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) [na:1.7.0_09-icedtea]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) [na:1.7.0_09-icedtea]
at java.lang.Thread.run(Thread.java:722) [na:1.7.0_09-icedtea]
Too many open files這個問題主要指的是進(jìn)程企圖打開一個文件囚聚,或者叫句柄粥惧,但是現(xiàn)在進(jìn)程打開的句柄已經(jīng)達(dá)到了上限,已經(jīng)無法打開新句柄了。
網(wǎng)上一提到這個問題就要增加句柄上限简珠,而往往這種情況的發(fā)生是因?yàn)殄e誤的使用了句柄猜揪,可以稱作句柄泄漏惭墓,找到句柄達(dá)到上限的原因才是王道。
以下是Linux中句柄的介紹
Linux中所有的事物或資源都是以文件的形式存在而姐,比如消息腊凶、共享內(nèi)存、連接等拴念,句柄可以理解為指向這些文件的指針钧萍。
對于這些句柄,Linux是有數(shù)量限制的政鼠,單個進(jìn)程默認(rèn)可以打開的句柄數(shù)上限风瘦,可以用以下命令來查看:
ulimit -a
執(zhí)行結(jié)果如下:
其中的open files一項(xiàng)就是默認(rèn)的句柄數(shù),此時默認(rèn)的句柄數(shù)是1024
還可以設(shè)置某個進(jìn)程的句柄數(shù)上限公般,命令是:
ulimit -a PID
執(zhí)行結(jié)果如下:
也是看open files一項(xiàng)万搔,可以看到,該進(jìn)程的句柄上限也是1024
這個句柄數(shù)是可以改的官帘,修改默認(rèn)的句柄數(shù)蟹略,命令如下:
ulimit -n 2000
這個命令可以把默認(rèn)的句柄數(shù)改為2000,但系統(tǒng)重啟后會恢復(fù)默認(rèn)值
這個文件在系統(tǒng)中的默認(rèn)值配置在/etc/security/limits.conf文件中遏佣,加入以下配置:
- soft nofile 2000
- hard nofile 2000
或者 - nofile 2000
其中hard的設(shè)置是實(shí)際的默認(rèn)值挖炬,也就是上限,而soft的配置只是用來警告的状婶,如果超過了soft的值意敛,會有warn,而第三種用短橫線– 的配置膛虫,則是hard和soft同時配置的方式草姻。
- nofile 2000
下面看一下如何查詢系統(tǒng)中進(jìn)程占用的句柄數(shù)
使用的命令是:
lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr|more
lsof命令是Linux中的一個系統(tǒng)監(jiān)視命令,可以查看進(jìn)程打開的文件稍刀、端口等撩独,功能強(qiáng)大敞曹,上面的命令通過一串的管道后只保留了句柄數(shù)和PID,執(zhí)行結(jié)果如下:
第一列是句柄數(shù)综膀,第二列是進(jìn)程id
可以看到前兩個進(jìn)程的句柄數(shù)已經(jīng)超過上限了澳迫,這正是這兩個進(jìn)程的日志正在報文章最上方的異常。
下面查詢某個進(jìn)程都占用了一些什么樣的句柄
比如查詢PID為25950的進(jìn)程剧劝,使用的命令是
lsof |grep 25950
執(zhí)行結(jié)果如下:
這里是截取的一部分橄登,每列的含義如下:
1,進(jìn)程名稱
2讥此,PID
3拢锹,進(jìn)程所有者
4,文件描述符
5萄喳,文件類型
文件類型有以下幾種:
DIR:表示目錄卒稳。
CHR:表示字符類型。
BLK:塊設(shè)備類型他巨。
UNIX: UNIX 域套接字展哭。
FIFO:先進(jìn)先出 (FIFO) 隊(duì)列。
IPv4:網(wǎng)際協(xié)議 (IP) 套接字闻蛀。
DEVICE:指定磁盤的名稱
SIZE:文件的大小
NODE:索引節(jié)點(diǎn)(文件在磁盤上的標(biāo)識)
NAME:打開文件的確切名稱
在我查看的這個進(jìn)程中,有異常大量的IPv4類型文件被打開您市,以此為線索可以分析出具體的句柄超限的原因觉痛。在文章最開始的例子中,是因?yàn)槌绦虿煌5膶α硪慌_服務(wù)器發(fā)起連接茵休,導(dǎo)致句柄超上限(從異常信息中其實(shí)也能分析出來)薪棒。