近几个月公司我所在组负责的系统一直出现“too many open files” 错误,报错如下:
因为我们负责的系统是处理公司的一些对接业务,系统中使用了大量的webservice ,和http连接操作,所以一般使用了xfire,axis,httpclient等等远程调用框架,一些遗留的大批老的代码都存在未关闭的情况,网上找了一些原因:
程序经常访问的文件、socket在Linux中都是文件file,httpclient是基于socket进行做的封装,所以系统需要记录每个当前访问file的name、location、access authority等相关信息,这样的一个实体被称为file entry。“open files table”(图中橙色标识)存储这些file entry,以数组的形式线性管理。文件描述符(file descriptor)作为进程到open files table的指针,也就是open files table的下标索引,将每个进程与它所访问的文件关联起来了。
每个进程中都有一个file descriptor table管理当前进程所访问(open or create)的所有文件,文件描述符关联着open files table中文件的file entry。细节不表,对于open files table能容纳多少file entry。Linux系统配置open files table的文件限制,如果超过配置值,就会拒绝其它文件操作的请求,并抛出Too many open files异常,这种限制有系统级和用户级之分。
系统级设置对所有用户有效。可通过两种方式查看系统最大文件限制
1 cat /proc/sys/fs/file-max
2 sysctl -a 查看结果中fs.file-max这项的配置数量
如果需要增加配置数量就修改/etc/sysctl.conf文件,配置fs.file-max属性,如果属性不存在就添加。
配置完成后使用sysctl -p来通知系统启用这项配置
用户级:
Linux限制每个登录用户的可连接文件数。可通过 ulimit -n来查看当前有效设置。如果想修改这个值就使用 ulimit -n <setting number> 命令。
对于文件描述符增加的比例,资料推荐是以2的幂次为参考。如当前文件描述符数量是1024,可增加到2048,如果不够,可设置到4096,依此类推。
一 、排查第一步,排查使用HTTPclient框架的对接服务商,例如以下程序:
在关闭一些打开的文件流未进行关闭的情况,代码如下:
private static String outputSingleLine(String s) throws IOException{
StringBuffer sb = new StringBuffer();
BufferedReader br = null;
try{
br = new BufferedReader(new StringReader(s));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line.trim().replaceAll("\\t", ""));
}
}catch(IOException e){
throw e;
}finally{
if(br!=null){
br.close();
}
}
return sb.toString();
}
二,查询linux, 查看系统当前连接数是多少?使用命令ulimit –a查看
[root@server30-116 ~]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 62820
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 262144 (可以看出当前用户可打开数量为262144)
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 62820
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
查看所有进程打开的文件数
[root@server30-116 ~]# lsof |wc -l
4672
查看当前用户打开了多少文件句柄:
lsof -n |awk '{print $2}'|sort|uniq -c |sort -nr|more
131 24204
57 24244
57 24231
56 24264
这里我只截取了部分输出信息。其中第一行是打开的文件句柄数,第二行是进程号。执行ps -ef | grep 进程号 可查看进程的详细信息。
查找文件句柄问题的时候,还有一个很实用的程序 lsof,可以很方便看到某个进程开了哪些句柄 :
lsof -p pid
某个进程开了几个句柄 :
lsof -p pid |wc -l
这样可以分析出某个进程打开文件的具体内容,
我们还可以分析,查看当前系统TCP链接处于何种状态的文件数量:
[root@server30-116 ~]# netstat -nat | awk '{print $6}' | sort | uniq -c | sort -n
1 established)
1 Foreign
12 LISTEN
33 ESTABLISHED
37 TIME_WAIT
2266 CLOSE_WAIT
查看某进程处于CLOSE_WAIT 的状态(要先查看某进程的ID)
[root@server30-116 ~]# lsof -np 17185 |grep CLOSE_WAIT |wc -l
2266
发现很多打开的TCP连接一直处于等待状态。
让后找打webservice连接的失效时间,设置一小段失效时间,
通过以上基本可以解决一些问题,具体还需有观察一段时间
参考文章:http://zhumeng8337797.blog.163.com/blog/static/1007689142012428104618670/