程序架构背景:
n个业务线程。接收从网络线程传递过来的请求,按业务逻辑处理,最后将处理结果形成bytes回传给网络线程,让网络将处理结果按原路返回。
1个网络线程。网络线程负责listen、accept、send、recv等底层网络操作。该线程判断fd上是否有完整的请求,如果已经完整,直接传递给业务线程处理。
问题现象描述:
1.业务没有接到任何请求;
2.参看网络线程的/proc/fd目录,使用命令 “l -l | wc -l”,发现文件描述符达到20480个,且一直没有变动;
3.使用“strace -p 网络线程PID”命令,发现如下问题:
accept(8, 0x7ffff42743f0, [16]) = -1 EMFILE (Too many open files) accept(8, 0x7ffff42743f0, [16]) = -1 EMFILE (Too many open files) accept(8, 0x7ffff42743f0, [16]) = -1 EMFILE (Too many open files) accept(8, 0x7ffff42743f0, [16]) = -1 EMFILE (Too many open files) accept(8, 0x7ffff42743f0, [16]) = -1 EMFILE (Too many open files) accept(8, 0x7ffff42743f0, [16]) = -1 EMFILE (Too many open files)
据此可判断,server目前维持的链接已经超过进程资源限制。
Linux服务器默认的文件描述符是1024个,查看方式是执行ulimit -n命令。
对于大规模网络服务器来说,1024个文件描述符,意味着最大可接受1024个客户端,显然是不够的。后台程序员需要适当增大该值,具体方法请参考博客中的其他文章。
在查找问题的时候,我们可能想知道当前进程被允许的最大文件描述符个数,或者验证修改最大文件描述符后是否已经生效。我们采用如下的办法:
cat /proc/PID/limits | grep “Max open files”
在实际环境中运行,得结果如下:
[email protected]:/home/motadou> cat /proc/22706/limits | grep "Max open files" Limit Soft Limit Hard Limit Units Max open files 204800 204800 files
由此得知,PID为22706的进程最多可以打开204800个文件。
[email protected]:/home/motadou> cat /proc/22706/limits Limit Soft Limit Hard Limit Units Max cpu time unlimited unlimited seconds Max file size unlimited unlimited bytes Max data size unlimited unlimited bytes Max stack size 8388608 unlimited bytes Max core file size 419430400 419430400 bytes Max resident set 7011418112 unlimited bytes Max processes 62929 62929 processes Max open files 204800 204800 files Max locked memory 65536 262144 bytes Max address space 8322990080 unlimited bytes Max file locks unlimited unlimited locks Max pending signals 62929 62929 signals Max msgqueue size 819200 819200 bytes Max nice priority 0 0 Max realtime priority 0 0 Max realtime timeout unlimited unlimited us