1) linux系统设计里面遵循'一切都是文件'的原则
2) 即: 磁盘文件、目录、'网络套接字(socket)'、磁盘、'管道(pipe)',所有这些都是'文件'
3)在我们打开'文件'的时候会返回一个'fd',即是'文件句柄'
② 文件句柄泄漏
1) 文件句柄泄漏,也叫'文件描述符泄漏'
2) 当我们'打开一个文件',操作系统就会给程序'分配'一个文件描述符
3) 如果在'使用完'成之后,'没有及时的关闭文件',就会造成文件句柄泄漏的问题
遗留: 什么'原因'导致没有及时关闭文件? '表象'是什么?
③ Too many open files报错解读
1) '错误通'常也可以叫做句柄数'超出'系统限制
"Too manay open files" 问题很'明显',文件描述符超出限制导致'无法打开'文件或创建网络连接
表象: 句柄数'不足'导致业务进程'无法打开更多'的文件进而导致进程启动失败
2) 思考: 超出的'原因'?
[1]、初始设置的'小',导致'超限'
[2]、'句柄'泄露,导致'异常'增加,超限 --> "分析是难点"
3) 常见现象
[1]、如果'频繁'的打开文件,但是没有'close'关闭文件流
[2]、打开'网络套接字(socket)'而'忘记释放'就会有句柄泄露的现象
④ 相关内核参数 sysctl
1) 系统'最大打开'文件描述符数:/proc/sys/fs/file-max
备注: 是系统所有'用户'所有'进程'所允许打开的'上限'
2) 临时修改'方式1'
echo 6000000 > /proc/sys/fs/file-max
3) 临时修改'方式2'
sysctl -w fs.file-max = 6000000
4) '永久'生效 -->在/etc/sysctl.conf中设置
fs.file-max = 6000000
+++++++++++++++++++ "分割线" +++++++++++++++++++
/proc/sys/fs/file-nr --> 表示当前时刻'整个系统内核的文件句柄'统计数据,'只读的'
⑤ /etc/security/limits.conf 解读
* - nofile 65536
1) '*'表示: 所有的'用户'限制都一样,可指定'某个用户';'单个进程'可以打开的最大文件句柄数
2) '-'表示: soft和hard
备注: nproc表示'单个用户'创建的'进程数'
nofile 值大于内核设置的 fs.nr_open 参数值导致登录系统'云服务器'失败
⑥ lsof相关命令
lsof -n | awk '{print $2}' | sort | uniq -c | sort -nr | head -n 20
lsof -i :port --> 查看'占用port'的进程
lsof -c 进程名 --> 列出进程所打开的文件
lsof -p pid --> 获取的是当前'pid进程'文件句柄数
lsof -u user | wc -l --> 查看当前用户总共打开'多少'文件,确定'是否'超限
lsof:WARNING:can't stat() fuse.gvfsd-fuse file system
⑦ ulimit命令
ulimit -a --> 常看'所有'配置
ulimit -n --> 查询当前用户'open files'的上限值
备注: 系统'默认'对文件句柄是有限制,不可能'让进程'无限制的调用句柄
ulimit -n 60000 --> 历临时'设置'当前用户的
ulimit – HSn 60000 --> 'soft'和'hard'设置相同
⑧ Java常见的报错
1) java.io.IOException: Too many open files
原因: 操作了'大量的文件',并且在操作后'没有关闭'文件流
2) java.net.SocketException: Too many open files
原因: 建立socket连接时,由于最大句柄数受限,'没有可用的'文件句柄导致报错
详细解读:
[1]、linux在'默认'情况下每个进程可以调用的最大句柄数是1024个
[2]、如果超过了这个限制,进程将'无法获'取新的句柄
[3]、而从导致不能打开新的文件或者'网络套接字',对于线上服务器即会出现服务'被拒绝'的情况
3) 报错一般体现在'业务'日志和/var/log/messages等'系统'日志
创建一个关于TCP的socket会获取一个socket文件的句柄
⑨ 排查思路
1) 查看pid
ps -ef | grep program
2) 根据'pid'查看进程'打开'的文件数
ll /proc/pid/fd | wc -l
lsof -p pid | wc -l
目的: 确定当前进程打开的文件数是否'超过'系统上限
3) 查询进程'具体'打开了哪些文件
ll /proc/pid/fd > open.log
lsof -p pid > open.log
目的: 辅助查找'异常代码'的文件
⑩ 相关参考
netstat -n | \
awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'
java.io.IOException: Too many open files
java.net.SocketException: Too many open files
java.io.IOException: Too many open files问题
nofile 值大于内核设置的 fs.nr_open 参数值导致登录系统'云服务器'失败
/proc/$pid/fd 展示的socket的inode号
How to Fix "java.io.FileNotFoundException Too many open files" Error