要让nginx的sendfile真正发挥内核态零拷贝效能,必须协同配置sendfile on、tcp_nopush on、tcp_nodelay off,关闭gzip/etag/动态expires等退化项,适配≥3.10内核、ext4/xfs文件系统,并绑定worker与cpu核心。

要让 Nginx 的 sendfile 真正发挥内核态零拷贝效能,不能只开一个配置项,必须从 Nginx 配置、内核行为、文件访问模式三方面协同调优。核心目标是:确保数据全程在内核空间搬运,不落入用户态读写路径。
确保 sendfile 路径畅通的 Nginx 配置要点
sendfile 不是“开了就高效”,它极易被其他配置意外禁用:
- 必须显式启用:
sendfile on;,且仅对真实磁盘静态文件生效(不支持管道、内存映射文件或动态生成内容) - 搭配
tcp_nopush on;:它对应 TCP_CORK,让内核攒满一个 MSS 再发包,避免小报文泛滥;注意不是tcp_nodelay,后者会破坏大文件传输的包合并效果 - 关闭所有导致响应体/头变更的功能:包括
gzip off;、etag off;、避免使用expires动态计算(如expires -1;),可设为固定值如expires max; - 慎用
sendfile_max_chunk:默认为 0(不限制),若设为非零值(如 512k),超长文件会被拆分并退化为普通 read/write,反而失去零拷贝优势
适配 sendfile 的内核与系统级设置
Linux 内核版本和参数直接影响 sendfile 效果:
- 推荐内核 ≥ 3.10:支持更稳定的 splice 机制和 DMA gather copy,实现真正 0 次 CPU 拷贝
- 检查并调优关键网络参数:
net.core.somaxconn和net.ipv4.tcp_max_syn_backlog建议设为 65535,防止高并发下连接队列溢出 - 避免干扰页缓存:不要对小文件启用
directio或O_DIRECT,因为 sendfile 依赖内核 page cache;大文件(≥4MB)才考虑配合directio 4m;减少内存压力 - 确认文件系统支持 mmap 语义:ext4、xfs 均满足,但某些网络文件系统(如 NFSv3)可能不兼容
worker 进程与 CPU 绑定的协同优化
sendfile 的高效依赖底层调度稳定性:
- 设置
worker_processes auto;或精确匹配物理 CPU 核心数(如 8 核设为 8),避免过度创建进程引发上下文切换开销 - 启用 CPU 绑定:
worker_cpu_affinity auto;或手动指定(如worker_cpu_affinity 0001 0010 0100 1000;),让每个 worker 独占核心,减少 cache miss 和迁移延迟 - 提升单进程资源上限:
worker_rlimit_nofile 100000;,同时在系统层配置/etc/security/limits.conf中同步提高 soft/hard nofile 限制 - 事件模型固定为 epoll:
use epoll;,这是 Linux 下最适配高并发 + sendfile 场景的 I/O 多路复用机制
按场景选择是否启用 aio 与 directio
并非所有文件都适合同一套策略:
- 海量小文件(图标、JS/CSS):专注
sendfile + tcp_nopush,禁用aio和directio;小文件随机访问频繁,绕过页缓存反而降低性能 - 大文件连续读取(视频、安装包):可启用
aio threads;(需 nginx ≥ 1.15.9 + kernel ≥ 4.18),配合directio 4m;减轻内存压力,但需验证是否仍走 sendfile 路径(可通过strace -e trace=sendfile观察) - 混合静态资源站点:建议按 location 分离配置,例如
/static/large/启用 directio,/static/small/保持默认页缓存路径











