- 问题起因
在生产环境出现一个TCP网络连接的异常,socket accept()时返回错误,错误码errno=24,strerror=”Too many open files”,线程占用CPU接近100%,即死循环。查明直接原因是,进程的open files数量太小,当连接数超时该数目时即会返回上述错误。(这要提醒一句:要注意父子进程的limits参数,也许系统配置参数已修改,但父进程是在修改前启动的,再去fork子进程时,子进程的limits参数也许就不如本意。通过cat /proc/<pid>/limits 查看进程的limits参数。)
上述问题提供给用户连接服务的是子进程,而其父进程的open files却是1024,即便系统设置了open files为1,000,000,也阻止不了其共享父进程的参数,所以触发了上述的问题。为修复该问题,当然第一步要重启父进程,让其参数与系统配置的一致,再让其fork子进程。
然而还要问,为何进程占用CPU会接近100%?这就是底层网络实现涉及的问题。熟知IO多路复用模型epoll的人知道,其有两种触发模式,水平触发(EPOLLLT)和边缘触发(EPOLLET),默认为EPOLLLT模式。水平触发模式相对容易操作,只要内核socket读写缓冲区仍有数据就会触发epoll。对边缘触发模式,man手册推荐的正确用法:
(i) with non-blocking