一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

Nginx 中 sendfile 开启与禁用对服务器性能的对比测试

时间:2026-07-14 09:10:52 编辑:袖梨 来源:一聚教程网

开启 sendfile 可将静态文件传输从四次拷贝降为两次,仅需2次数据拷贝和2次上下文切换,显著降低CPU sys占用与延迟;禁用后回退至read/write模式,导致CPU搬运开销激增,高并发下QPS下降20%–40%。

开启 sendfile 能显著降低静态文件传输的 CPU 开销和延迟,禁用后则回归传统 read/write 模式,带来额外拷贝与上下文切换——性能差异在高并发下载或大量小资源请求场景下尤为明显。

核心性能差异:两次拷贝 vs 四次拷贝

启用 sendfile 后,Nginx 利用内核原生 sendfile() 系统调用,实现磁盘到网卡的内核直传:

  • 磁盘 → 内核缓冲区(DMA)
  • 内核缓冲区 → Socket 缓冲区(零 CPU 拷贝)
  • Socket 缓冲区 → 网卡(DMA)

整个过程仅需 2 次数据拷贝、2 次上下文切换。而禁用时,必须走用户态路径:

  • 磁盘 → 内核缓冲区(DMA)
  • 内核缓冲区 → 用户空间缓冲区(CPU 拷贝)
  • 用户空间缓冲区 → Socket 缓冲区(CPU 拷贝)
  • Socket 缓冲区 → 网卡(DMA)

CPU 时间大量消耗在搬运上,尤其在 100+ 并发静态请求时,sys(系统态)CPU 使用率可升高 3–5 倍,QPS 下降 20%–40%。

实测对比方法:不只看平均速度

真实评估需避开缓存干扰,并关注稳定性与系统负载:

  • 清空页缓存:echo 3 > /proc/sys/vm/drop_caches,避免 page cache 掩盖差异
  • 测吞吐稳定性:循环 20 次 curl -s -w "%{speed_download}n" -o /dev/null http://x/file.zip,统计下载速率标准差;开启 sendfile 后标准差通常降低 30% 以上
  • 看系统开销:用 pidstat -d 1 观察 worker 进程的 %iowaitkB_rd/s,sendfile 开启后 iowait 明显下降,说明 I/O 更高效
  • 压测并发影响:用 ab -n 200 -c 50 http://x/file.css 对比 QPS 与平均响应时间;禁用时响应时间抖动更大,长尾更明显

验证是否真生效:别信配置,要看系统调用

配置了 sendfile on 不代表一定走零拷贝路径,必须验证实际行为:

  • 追踪 worker 进程:strace -p $(pgrep nginx | head -1) -e trace=sendfile64,read,write 2>&1 | grep sendfile64,持续看到 sendfile64 调用才确认启用
  • 检查退化原因:若日志中频繁出现 gzip onRange 请求或 etag 指令,Nginx 会自动回退到 read/write,此时 strace 将显示 readwrite
  • 观察 fd 关系:通过 /proc/<pid>/fd/ 查看 socket fd 与文件 fd 是否被同一 sendfile64 调用串联,是零拷贝的关键证据

禁用 sendfile 的合理场景

不是所有情况都适合开启,以下情形建议关闭或无法启用:

  • 启用了 gzip on:运行时压缩必须进用户态,强制禁用 sendfile
  • 使用 NFS 或某些 FUSE 文件系统:底层不支持 sendfile() 系统调用,Nginx 自动 fallback
  • 提供带 Range 支持的视频服务:分片读取需用户态介入,无法走零拷贝
  • 配合 directio 优化大文件下载:二者冲突,必须 sendfile off

禁用后虽损失零拷贝优势,但换来内容可干预能力——比如动态加水印、按需转码或插入响应头。

热门栏目