今天某個服務的日志中出現了大量的異常:
[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這個問題主要指的是進程企圖打開一個文件,或者叫句柄,但是現在進程打開的句柄已經達到了上限,已經無法打開新句柄了。
網上一提到這個問題就要增加句柄上限,而往往這種情況的發生是因為錯誤的使用了句柄,可以稱作句柄泄漏,找到句柄達到上限的原因才是王道。
以下是Linux中句柄的介紹
Linux中所有的事物或資源都是以文件的形式存在,比如消息、共享內存、連接等,句柄可以理解為指向這些文件的指針。
對於這些句柄,Linux是有數量限制的,單個進程默認可以打開的句柄數上限,可以用以下命令來查看:
ulimit –a
執行結果如下:
其中的open files一項就是默認的句柄數,此時默認的句柄數是1024
還可以設置某個進程的句柄數上限,命令是:
ulimit –a PID
執行結果如下:
也是看open files一項,可以看到,該進程的句柄上限也是1024
這個句柄數是可以改的,修改默認的句柄數,命令如下:
ulimit –n 2000
這個命令可以把默認的句柄數改為2000,但系統重啟后會恢復默認值
這個文件在系統中的默認值配置在/etc/security/limits.conf文件中,加入以下配置:
* soft nofile 2000
* hard nofile 2000
或者
* - nofile 2000
其中hard的設置是實際的默認值,也就是上限,而soft的配置只是用來警告的,如果超過了soft的值,會有warn,而第三種用短橫線– 的配置,則是hard和soft同時配置的方式。
下面看一下如何查詢系統中進程占用的句柄數
使用的命令是:
lsof -n|awk '{print $2}'|sort|uniq -c|sort-nr|more
lsof命令是Linux中的一個系統監視命令,可以查看進程打開的文件、端口等,功能強大,上面的命令通過一串的管道后只保留了句柄數和PID,執行結果如下:
第一列是句柄數,第二列是進程id
可以看到前兩個進程的句柄數已經超過上限了,這正是這兩個進程的日志正在報文章最上方的異常。
下面查詢某個進程都占用了一些什么樣的句柄
比如查詢PID為25950的進程,使用的命令是
lsof |grep 25950
執行結果如下:
這里是截取的一部分,每列的含義如下:
1,進程名稱
2,PID
3,進程所有者
4,文件描述符
5,文件類型
文件類型有以下幾種:
DIR:表示目錄。
CHR:表示字符類型。
BLK:塊設備類型。
UNIX: UNIX 域套接字。
FIFO:先進先出 (FIFO) 隊列。
IPv4:網際協議 (IP) 套接字。
DEVICE:指定磁盤的名稱
SIZE:文件的大小
NODE:索引節點(文件在磁盤上的標識)
NAME:打開文件的確切名稱
在我查看的這個進程中,有異常大量的IPv4類型文件被打開,以此為線索可以分析出具體的句柄超限的原因。在文章最開始的例子中,是因為程序不停的對另一台服務器發起連接,導致句柄超上限(從異常信息中其實也能分析出來)。
————————————————
版權聲明:本文為CSDN博主「lkforce」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/lkforce/article/details/80710459