场景:一个多线程服务器,每个线程执行一个事件循环。在事件循环开始前,调用
socket/bind/listen
监听端口,然后将监听句柄(
fd
)添加到
epoll
,然后开始事件循环,执行
epoll_wait
。
epoll_wait
返回有效事件时,对于监听事件,调用
accept
建立新连接,将该连接句柄添加到
epoll
;对于普通连接,调用
read/write
进行网络
IO
及其他处理逻辑。
现象:服务器进程 CPU 占用彪高,几乎每个事件循环都在 accept ,客户端出现超时。
原因: ulimit -n 为 65535 , 进程打开的 fd 已经超过该数值,导致 accept 时无法取得 fd 而失败,而此时 TCP 连接的三次握手已经建立。又因为 epoll 使用的 LT 触发模式,该连接事件会不停地由 epoll 上报,于是产生了所谓的『死循环』,其实是事件循环闲不下来了,即使没有实际的 网络 IO。
现象:服务器进程 CPU 占用彪高,几乎每个事件循环都在 accept ,客户端出现超时。
原因: ulimit -n 为 65535 , 进程打开的 fd 已经超过该数值,导致 accept 时无法取得 fd 而失败,而此时 TCP 连接的三次握手已经建立。又因为 epoll 使用的 LT 触发模式,该连接事件会不停地由 epoll 上报,于是产生了所谓的『死循环』,其实是事件循环闲不下来了,即使没有实际的 网络 IO。