Nginx 高并发依赖内核 epoll 的红黑树管理监听 fd,而非自研;其通过 epoll_ctl 注册 fd、epoll_wait 遍历就绪队列实现 O(1) 事件响应,并采用 ET 模式、非阻塞 I/O 和 master-worker 模型优化性能。

Nginx 高并发能力的核心之一,是它在 Linux 下高效使用 epoll 机制,而 epoll 内部确实借助红黑树来管理大量监听的文件描述符(fd),但这并非 Nginx 自己实现的红黑树,而是内核 epoll 的设计特性。
epoll 使用红黑树管理就绪与监听 fd
Linux 内核中,epoll 实例(epoll_create 返回的 fd)内部维护两套关键数据结构:
- 一颗红黑树:用于存储所有通过
epoll_ctl(EPOLL_CTL_ADD)注册的监听 fd 及其事件配置(如 EPOLLIN、EPOLLET 等)。红黑树提供 O(log n) 时间复杂度的插入、删除和查找,适合频繁增删大量连接场景。 - 一个就绪队列(通常是双向链表):当某个 fd 就绪(如 socket 收到数据),内核将其节点加入该队列,供
epoll_wait()快速返回,避免遍历全部监听 fd。
这种分离设计使 Nginx 在十万级并发连接下,仍能以接近 O(1) 的平均开销响应 I/O 事件 —— 增删监听项走红黑树,获取就绪事件走队列。
Nginx 如何利用这一机制
Nginx 并不直接操作红黑树,而是通过标准 epoll 系统调用与内核协作:
- 启动时,对每个监听端口(如
listen 80)调用socket()+bind()+listen()得到监听 socket fd,再用epoll_ctl(ADD)注册到 epoll 实例,关注EPOLLIN事件。 - 收到新连接(accept)后,新 client fd 同样用
epoll_ctl(ADD)加入同一 epoll 实例,通常启用边缘触发(ET)模式,配合非阻塞 I/O。 - 事件循环中反复调用
epoll_wait(),只遍历就绪队列中的少量 fd,而非全量检查,极大降低 CPU 开销。
为什么不是自己实现红黑树?
Nginx 专注应用层逻辑,不重复造轮子:
- 内核已提供稳定、高性能、经过验证的 epoll 红黑树实现,用户态无需也难以超越。
- 若 Nginx 自己维护 fd 管理结构(如哈希表或自研树),还需同步处理内核事件通知、内存生命周期、多线程/多进程安全等问题,复杂度陡增且易出错。
- 实际瓶颈不在数据结构选择,而在事件分发策略、内存池复用、零拷贝优化等整体设计。Nginx 的 master-worker 模型 + 单线程事件循环,正是为了最大化利用 epoll 这一原语。
注意:红黑树只是 epoll 的实现细节
开发者无需关心红黑树的具体旋转或节点布局。真正影响性能的是:
- 是否启用
epoll ET 模式(Nginx 默认开启,需搭配非阻塞 socket) - 是否合理设置
worker_connections,避免超出系统ulimit -n - 是否关闭不必要的日志、缓冲或模块,减少事件循环负担
- 内核参数调优(如
net.core.somaxconn、fs.file-max)
理解 epoll 背后有红黑树,有助于明白“为何添加/删除监听 fd 不随连接数线性变慢”,但调优重点仍在 Nginx 配置与系统协同上。










