sendfile 是 nginx 吞吐量优化最直接有效的机制,通过零拷贝减少内核态与用户态间无效搬运,降低 cpu 开销、延迟并提升并发能力;需配合内核版本(≥2.4)、sg-dma 网卡及合理系统参数调优才能发挥全部潜力。

sendfile 是 Nginx 吞吐量优化中最直接有效的机制之一,它的核心价值在于减少数据在内核态与用户态之间的无效搬运,从而释放 CPU、降低延迟、提升并发服务能力。
零拷贝大幅降低 CPU 开销
传统文件传输需经历“磁盘 → 内核缓冲区 → 用户空间 → socket 缓冲区”两次内存拷贝;而 sendfile 启用后,数据由内核直接从磁盘 DMA 到 socket 发送队列,仅保留一次内核内拷贝(Linux 2.4+ 配合 SG-DMA 网卡甚至可完全规避 CPU 拷贝)。实测中,小文件(
- 必须显式开启:
sendfile on; - 默认已启用零拷贝路径,无需额外编译选项(Nginx ≥ 1.3.0)
- 对静态资源(CSS/JS/图片/视频)效果最显著,动态响应不生效
与 tcp_nopush 协同放大吞吐收益
sendfile 本身只解决“怎么发”,tcp_nopush 解决“什么时候发”。两者联用才能避免小响应被拆成多个 TCP 小包:
-
tcp_nopush on;让内核攒够一个 MTU(通常 1460 字节)再发,减少报文数量和 ACK 往返 - 特别适合 sendfile 场景:HTTP 响应头 + 文件内容一次性推入发送队列
- 若同时启用
tcp_nodelay on;,会与 tcp_nopush 冲突,应按场景取舍——大文件/下载类选tcp_nodelay off,API 类选on
注意适用边界与常见误配
sendfile 不是万能加速器,错误使用反而拖慢性能:
- gzip 压缩与 sendfile 互斥:启用
gzip on会强制走用户态读取,使 sendfile 失效——静态资源服务务必关 gzip - 文件过大(如 >1GB)时,部分旧内核可能因 sendfile_max_chunk 限制导致分段调用,建议设为
sendfile_max_chunk 0;(不限大小) - 涉及代理或内容改写(如 sub_filter、add_header 动态插入)的 location,sendfile 自动禁用,需检查是否意外落入该路径
搭配系统级配置才能发挥全部潜力
sendfile 效果依赖底层支持,单靠 Nginx 配置不够:
- 确认内核支持:Linux ≥ 2.4(基础),≥ 4.18 更佳(支持 aio threads + sendfile 异步协同)
- 网卡需支持 SG-DMA:
ethtool -k eth0 | grep scatter-gather显示scatter-gather: on - 必要时调大 TCP 缓冲区(
net.ipv4.tcp_wmem最大值 ≥ 1MB),防止 sendfile 发送速率受限于 socket 队列满











