这周做了一个项目,为ios客户端提供稳定的数据源,这是一个服务端进程,运行在linux环境中,做完后,自己来了一次压力稳定性测试,一天过后,发现程序突然不工作了,但是服务端进程并没有停掉,通过查看日志发现epoll_wait返回的fd,errno = 24, 对比errorno.h的第24号错误码,发现是 too many open files。在网上翻了一会儿,明白原因了,但也综合了大家的内容,记下给大家分享一下。
在linux系统中,每个进程启动后,相应的都会有一个open files table,在这个表中记录了该进程打开的文件,它包括:一般文件、socketfd等,在每个进程中,它能打开的文件是有限的,这就是为什么在编程中打开文件之后,当不用时一定要关上。
我们可以通过命令:ulimit -a 查看当前环境的对资源的限制, 通过ulimit -n 可以直接查看 open files 的大小
root>root>ulimit -a
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 32816
max locked memory (kbytes, -l) 32
max memory size (kbytes, -m) unlimited
open files (-n) 1024
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) 32816
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
在上面显示中,可以看到 open files 被限制为1024的大小,如果在一个进程中要再多打开文件时,就打不开了,如果是网络进程,出现的结果就是客户端永远连不上服务器,但是服务器却又一直在运行。当然了,我们更改这个值的大小,让自己的进程能够打开更多的文件,通过命令:ulimit -n value,这儿的value一般建议为2的n次幂。在这是这个值之前,我们可以通过查看/proc/sys/fs/file-max 这个文件看看系统支持的最大值。
当出现这个问题时,一般系统默认的1024能满足我们的需求,除非是在特别大并发的访问量下,可能会出现。所以绝大部分时候出现这个问题,可能是由于我我们打开文件之后忘记关闭了,特别是socketfd, 作为服务端的程序,socket 在正常情况下是要等待客户端关闭后,服务端才能关闭,所以当客户端忘记了关,可能服务端也关闭不了了。可以通过命令 lsof -p processID查看某个进程打开的所有文件进行进一步的分析。