非阻塞I/O是Nginx高并发静态服务的底层机制,依赖epoll/kqueue实现高效事件通知,配合sendfile零拷贝、open_file_cache元数据缓存及合理连接超时控制,共同保障单worker处理数万连接的性能。

非阻塞 I/O 本身不是“开关”,而是 Nginx 静态文件服务高并发的底层运行方式——它让单个 worker 进程能同时盯住数万连接,哪个 socket 有数据可读、哪个磁盘文件已缓存就绪、哪个客户端 TCP 缓冲区空了可写,内核就通知哪个,Nginx 就处理哪个,全程不卡、不等、不轮询。
epoll/kqueue 是非阻塞生效的前提
Linux 下 Nginx 默认用 epoll,FreeBSD/macOS 用 kqueue。这些机制不是“辅助选项”,而是让非阻塞真正高效的关键:它们允许一个 worker 同时监听成千上万个 socket 和文件句柄的状态变化,只在真正就绪(比如客户端发来 HTTP GET、内核 page cache 已加载完 index.html)时才唤醒处理逻辑。没有它,非阻塞就退化成低效忙等。
sendfile 实现零拷贝传输
静态小文件(CSS/JS/图标)响应快,核心不在“读得快”,而在“拷贝少”:
- sendfile on;:让内核直接从文件 page cache 复制到 socket 发送缓冲区,跳过用户态内存,省两次数据拷贝 + 两次上下文切换
- tcp_nopush on;:配合 sendfile,把数据攒满 TCP 报文段再发,减少小包数量
- 注意:一旦启用 gzip、sub_filter 或任何需修改响应体的模块,Nginx 就自动退回到 read()+write() 模式,零拷贝失效
open_file_cache 减少元数据开销
每秒几万次请求若每次都做 stat() 和 open(),内核会成为瓶颈,甚至引发短暂阻塞:
- open_file_cache max=10000 inactive=60s;:缓存文件是否存在、是否可读、inode 等元数据
- open_file_cache_valid 60s;:每分钟检查一次缓存有效性
- open_file_cache_min_uses 2;:至少被访问两次才进缓存,过滤冷门路径
合理控制连接生命周期与缓冲
非阻塞不等于无限容忍慢连接。静态服务尤其要防资源堆积:
- keepalive_timeout 15s;:长连接空闲超时后及时释放 fd,避免数万空闲连接占满 worker_connections
- client_header_timeout 10s; 和 send_timeout 30s;:防 Slowloris 类攻击或弱网客户端拖住连接
- client_header_buffer_size 1k;:静态资源请求头极简,无需大缓冲;过大反而浪费内存、增加延迟


















