水平触发和边缘触发
epoll既支持水平触发也支持边缘触发,默认是水平触发。
水平触发(LT)
当被监控的文件描述符上有可读写事件发生时,会通知用户程序去读写,他会一直通知用户,如果这个描述符是用户不关心的,它每次都返回通知用户。
读缓冲区不为空时, 读事件触发。写缓冲区不为满时, 写事件触发。
水平触发时,逻辑简单,不太容易出bug。
写数据时,LT模式需要先打开EPOLLOUT,当没有数据需要写出时,再关闭EPOLLOUT(否则会一直返回EPOLLOUT事件)。
边缘触发(ET)
当被监控的文件描述符上有可读写事件发生时,会通知用户程序去读写,它只会通知用户进程一次,这需要用户一次把内容读取完。如果用户一次没有读完数据,再次请求时,不会立即返回,需要等待下一次的新的数据到来时才会返回,这次返回的内容包括上次未取完的数据。
读缓冲区状态变化时, 读事件触发。写缓冲区状态变化时, 写事件触发。(只会提示一次)
边缘触发时,业务上层处理的逻辑较为复杂,处理不当存在丢失事件的风险。
写数据时,ET模式可以便捷地处理EPOLLOUT事件,省去打开与关闭EPOLLOUT的epoll_ctl(EPOLL_CTL_MOD)调用。
区别
水平触发和边缘触发的区别:实质上是调度策略。
例如,两条线分别有数据ABC、DEF,水平触发的处理顺序ADBECF,边缘触发的处理顺序ABCDEF。
选择
nginx使用边缘触发。redis使用边水平触发。为什么?
如果server的响应通常较小,不会触发EPOLLOUT,那么适合使用LT,例如redis等。
而nginx作为高性能的通用服务器,网络流量可以跑满达到1G,这种情况下很容易触发EPOLLOUT,则使用ET。
listenfd建议使用LT,connfd看情况选择,一般用LT即可,流量大的场景使用ET。