nginx高并发能力源于非阻塞i/o与epoll深度协同:socket设为非阻塞后,recv/send遇阻立即返回eagain,worker不等待;epoll则精准通知就绪事件,避免轮询,单worker即可高效调度数万连接。

非阻塞 I/O 和 epoll 不是各自独立运行的两套机制,而是深度咬合、互相成就的一体化设计。Nginx 的高并发能力,正来自这两者在每个连接处理环节上的紧密配合——非阻塞让 worker 不停步,epoll 让 worker 只做该做的事。
非阻塞 I/O 是“不等”的前提
每当新连接建立,Nginx 立即调用 fcntl() 将其 socket 设为非阻塞模式。这意味着:
- 调用
recv()时若无数据可读,立刻返回EAGAIN,而不是挂起进程 - 调用
send()时若发送缓冲区满,同样返回EAGAIN,不阻塞后续逻辑 - 每个 I/O 操作都变成“尝试一次、立即反馈”,把控制权牢牢握在 worker 手中
Epoll 是“知道何时再试”的眼睛
非阻塞操作返回 EAGAIN 后,连接并未被丢弃,而是被挂起并注册到 epoll 监听列表中:
- 等待读就绪时,注册
EPOLLIN事件;等待写就绪时,注册EPOLLOUT事件 - 内核通过红黑树管理所有监听 fd,
epoll_wait()只返回真正就绪的那些,避免轮询开销 - Nginx 默认使用边缘触发(ET)模式,确保状态变化时只通知一次,减少重复唤醒
事件循环把两者串成一条流水线
worker 进程的主循环不是忙等,而是一个精准调度器:
- 调用
epoll_wait()阻塞等待(但超时极短,通常毫秒级),拿到一批就绪事件 - 对每个就绪 fd,执行对应 handler:可能是 accept 新连接、recv 解析请求头、send 返回响应
- 每次 handler 内部都做非阻塞 I/O;若中途遇
EAGAIN,就重新注册事件,交还给 epoll 等待下一次通知 - 整个过程无锁、无跨进程共享,靠单 worker 独立闭环完成连接全生命周期
协同带来的实际收益
这种组合直接改变了资源使用方式:
- 10 万个并发连接,不再需要 10 万个线程,8 个 worker 进程即可承载
- 内存占用从线程栈(每线程 MB 级)压缩为连接结构体(每个连接仅 KB 级)
- CPU 不再浪费在上下文切换和空轮询上,90% 以上时间用于真实业务处理
- 慢连接(如 Slowloris)不会拖垮整体,靠
client_header_timeout等机制及时清理











