Nginx 默认使用epoll边缘触发(ET)模式,并非因性能显著优于水平触发(LT),而是因其更契合事件驱动设计——ET强制一次性读写至EAGAIN,提升逻辑确定性;LT虽容错性高但可能增加重复事件开销;实测QPS差异仅1%~3%,且Nginx硬编码启用ET,用户不可配置。

在 Nginx 中,epoll 的边缘触发(ET)和水平触发(LT)模式对性能影响有限,实际差异远小于常见误解。Nginx 默认使用 ET 模式,但并非因为 LT 性能差,而是 ET 更契合其事件驱动、非阻塞 I/O 的设计逻辑——关键不在“快多少”,而在“如何避免重复通知”和“是否需主动读写到 EAGAIN”。
ET 模式:一次就绪,只通知一次
边缘触发下,内核仅在文件描述符状态发生**变化**(如从不可读变为可读)时通知一次。Nginx 必须在该次通知中尽可能多地执行 I/O(比如循环 read/write 直到返回 EAGAIN),否则可能错过后续数据或连接事件。
- 需要配合非阻塞 socket 使用,否则容易阻塞事件循环
- Nginx 已内置完整处理逻辑:recv/recv_chain/send/send_chain 均会持续操作直到 EAGAIN
- 减少了 epoll_wait 的调用次数,尤其在高并发、小包场景下略微降低内核开销
LT 模式:只要就绪,持续通知
水平触发下,只要 fd 处于就绪状态(例如接收缓冲区仍有数据),每次 epoll_wait 都会返回它。Nginx 即使只读取部分数据,下次仍会被通知,行为更“宽容”。
- 对编程容错性更高,不强制要求一次性读完
- 在低并发或大包传输场景下,LT 和 ET 的吞吐量几乎无差别
- 但频繁就绪的 fd 可能导致 epoll_wait 返回大量重复事件,轻微增加用户态遍历开销
为什么 Nginx 默认用 ET?不是因为更快,而是更可控
Nginx 的事件模型基于单线程多路复用,每个 worker 处理成千上万连接。ET 强制开发者(或框架)显式管理 I/O 边界,避免因“以为读完了”而漏处理,从而提升确定性和可预测性。
- LT 容易掩盖逻辑缺陷(比如忘记判断 EAGAIN,误以为数据已收完)
- ET 促使 Nginx 在 accept、read、write 等环节统一采用 while 循环 + 非阻塞 + EAGAIN 检查,结构更一致
- 实测中,相同配置下 ET 与 LT 的 QPS 差异通常在 1%~3% 内,远低于网络抖动或后端延迟的影响
你不需要也不应该手动切换触发模式
Nginx 源码中 epoll 初始化时硬编码使用 EPOLLET;没有配置项开放给用户修改。强行 patch 或替换底层 event 模块不仅破坏稳定性,还可能引发连接泄漏、请求截断等隐蔽问题。
- nginx.conf 中的 use epoll; 仅表示启用 epoll 作为事件驱动机制,不控制 ET/LT
- Linux 2.6+ 内核中 epoll 默认支持 ET,且 Nginx configure 脚本会自动检测并启用
- 真正影响性能的是 keepalive、buffer 大小、tcp_nodelay、worker_connections 等参数,而非触发模式


















