To many open files 问题分析及解决方案

To many open files 问题分析及解决方案

十二月 21, 2020

首先记录几个命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#查看当前系统打开的文件数
lsof | wc -l
watch "lsof | wc -l"

#可以用lsof -p <pid of process>看打开的文件句柄数.查看某个进程的打开文件数
#-K 在输出的结果中显示文件描述符对应的线程号
lsof -p 1234|wc -l

#查看Linux系统打开的文件句柄数:
#第一列:进程打开的文件句柄数
#第二列:PID
lsof -n | awk '{print $2}'| sort | uniq -c | sort -nr

#查看系统打开句柄最大数量
more /proc/sys/fs/file-max

修改linux单进程最大文件连接数
修改linux系统参数。vi /etc/security/limits.conf 添加
*  soft  nofile  65536
*  hard  nofile  65536
修改以后保存,注销当前用户,重新登录,执行ulimit -a ,ok ,参数生效了:

#查看系统句柄数信息
ulimit -a

#修改系统最大句柄数
ulimit -n

#查一下当前已有的连接数,再来判断open files 为1024 是不是小
lsof -p $java_pid | wc -l

#系统级设置对所有用户有效。
#可通过两种方式查看系统最大文件限制
cat /proc/sys/fs/file-max
#修改配置/etc/sysctl.conf文件
fs.file-max=2048
#通知系统启用这项配置
sysctl -p

#strace
套接字泄露确实在发生,但是却没有办法能明确定位到问题在哪里。如果能直接看到进程调用 socket 和 close 系统调用的记录,就可以知道在哪里发生了套接字泄露。

于是找到了 strace 工具,该工具可以跟踪进程的系统调用记录。

1
strace -t -T -f -p 23345 -e trace=network,close -o strace.out

选项 -t 表明在输出结果中加上时间戳信息,-T 表示在输出结果中加上系统调用的耗时信息,-f 表示在输出结果中加上关联的线程号信息 (Trace child processes as they are created by currently traced processes as a result of the fork(2), vfork(2) and clone(2) system calls. Note that -p PID -f will attach all threads of process PID if it is multi-threaded, not only thread with thread_id = PID.),-p 输出指定进程的结果,-e 表示只输出网络相关和 close() 系统调用的日志,-o 表示将输出结果存储到指定文件中。

说明,上述输出经过了整理,过滤了无关的输出并按照线程分组按时间排序。

可以直接从输出结果中发现未成对的 socket()/close() 调用,这表明出现了套接字泄露。同时也可以看到发生泄露的线程号 (904)。

在网络服务出现 Too many open files 类似的异常之后,可以考虑排查服务是否存在网络套接字文件描述符泄露 的 BUG。

首先使用 jps 工具获取到目标服务的进程号
使用 lsof 工具查看目标进程打开的文件描述符的类型和特征
使用 jstack 工具查看目标进程的线程堆栈是否有异常
使用 strace 工具查看目标进程的系统调用,考虑添加 -f 参数显示对应的线程号
使用 jstack 工具找到目标进程中对应线程号的堆栈信息
查看对应代码,最终定位问题