零拷贝是内核直接在内核空间完成“磁盘页缓存→socket缓冲区”搬运,不经过用户内存,省去两次CPU拷贝和上下文切换;需满足源文件为常规文件、禁用gzip/动态处理、配合tcp_nopush等条件才能生效。

零拷贝不是“不搬运”,而是绕过用户态的高效搬运
在高清视频分发场景中,Nginx 的零拷贝并非让数据凭空从磁盘飞到网卡,而是通过 sendfile() 系统调用,让内核直接在内核空间完成“磁盘页缓存 → socket 缓冲区”的搬运。整个过程不经过用户内存,省掉两次 CPU 拷贝和两次上下文切换。这对大文件(如百MB级 MP4)尤其关键——一次 1080p 视频请求若走普通 read/write,CPU 要反复搬运数十甚至上百 MB 数据;而 sendfile 可将这部分开销几乎归零。
真正启用零拷贝的硬性条件
仅在 nginx.conf 中写 sendfile on; 远不够。以下任一不满足,Nginx 就会自动降级为传统拷贝路径:
- 源文件必须是常规文件(regular file),不能是符号链接、加密文件系统(如 ecryptfs)、NFSv3 挂载点(部分旧内核不支持 splice)
- 不能开启 gzip on 或 gzip_static on —— 压缩必须在用户态做,强制退出零拷贝
- 不能启用 proxy_buffering、subrequest(如 access_by_lua_block 修改 header)、或任何 Lua/SSI 动态干预响应体的行为
- 需配合 tcp_nopush on;(Linux 默认开启),确保 TCP 包合并发送,避免小包泛滥抵消零拷贝收益
视频服务中零拷贝的典型生效组合
面向点播类高清视频(MP4/FLV),推荐如下最小可行配置:
- 使用 ext4/xfs 文件系统存储视频文件(保障 mmap/splice 支持)
- 启用 ngx_http_mp4_module(支持 MP4 快速 seek)并搭配 sendfile on;
- 关闭所有压缩:注释掉 gzip 相关指令,禁用 brotli
- 静态 location 中避免 rewrite、add_header、lua_code 等可能污染响应流的操作
- 确认内核版本 ≥ 2.6.33(splice 支持完善),且文件未被其他进程加锁或处于只读挂载状态
为什么视频场景特别受益于零拷贝
高清视频文件体积大、并发连接多、I/O 密集度高。Nginx 工作进程在处理数千个同时播放的 MP4 请求时,若每个请求都触发两次 CPU 拷贝,CPU 很快成为瓶颈。而零拷贝将单位请求数的 CPU 时间压至微秒级,使单机 QPS 提升 3–5 倍,同时显著降低内存带宽压力。实际生产中,一个 4 核 8G 的 Nginx 实例,在零拷贝全开且无干扰条件下,可稳定支撑 8000+ 并发视频流(1080p,平均码率 4Mbps)。











