sendfile 能提升带宽利用率:需用 strace 验证生效,关闭 gzip/etag 等干扰项,压测对比 QPS、CPU 和延迟;实测常见 QPS↑2倍、CPU↓40%、延迟↓50%,并需排除磁盘、网卡 offload 等瓶颈。

直接测 sendfile 对带宽利用率的影响,不能只看网卡流量数字——因为无论开不开 sendfile,千兆网卡满打满算也就 125 MB/s 的理论上限。真正要验证的是:在同等请求压力下,sendfile 是否让 Nginx 更高效地“喂饱”这条链路,同时降低 CPU 和内存搬运开销。
确认 sendfile 确实生效(避免配置假象)
很多人的配置写了 sendfile on;,但实际没走零拷贝路径。必须用运行时观测手段验证:
- 用
strace -p $(pgrep -f "nginx: worker") -e trace=sendfile持续观察,有稳定、高频的sendfile系统调用输出,才说明走通了 - 如果同时看到大量
read+write调用,说明已被 gzip、range、etag 或文件未对齐等条件强制退化到传统路径 - 临时关闭所有干扰项:
gzip off; etag off; expires off; add_header Accept-Ranges none;,再测
对比测试带宽利用效率(不是单纯跑满)
带宽利用率 ≠ 网卡吞吐量。重点看单位 CPU 时间能撑起多少有效数据传输:
- 用
ab -n 10000 -c 1000 http://your-server/1mb-file.bin发起固定并发压测 - 同时监控三组指标:网卡收发速率(
iftop -P 80或cat /proc/net/dev)、Nginx worker 进程 CPU 使用率(top -p $(pgrep nginx | head -n1))、平均响应延迟(ab输出中的Time per request) - 分别开启/关闭 sendfile,保持其他配置完全一致,对比 QPS、CPU 占用、延迟三者的组合变化——实测中常见:开启后 QPS 提升 2 倍,worker CPU 降 40%,延迟减半,这才说明带宽被更干净地利用了
排除链路瓶颈干扰(确保测的是 sendfile,不是别的)
千兆环境容易掩盖问题,也容易误判瓶颈:
- 确认磁盘不拖后腿:用
dd if=/dev/zero of=test bs=1M count=1024 oflag=direct测 SSD 写入,应 ≥ 300 MB/s;读取用hdparm -t /dev/nvme0n1 - 禁用 TCP offload 功能(如 TSO、GSO),防止网卡硬件加速干扰内核路径判断:
ethtool -K eth0 tso off gso off - 检查是否启用了
tcp_nopush on;—— 它配合 sendfile 把多个小响应合并成一个 TCP 包发出,减少协议开销,否则即使 sendfile 开了,小文件场景仍可能因包数过多拉低有效带宽
观察内核级数据流向(进阶验证)
想确认是否触发了终极优化(DMA gather copy,即内核缓冲区直送网卡,跳过 socket 缓冲区):
- 启用
perf工具跟踪系统调用:perf record -e 'syscalls:sys_enter_sendfile' -p $(pgrep nginx),然后压测并分析 - 查内核日志是否有警告:
dmesg | grep -i "sendfile",某些老旧内核或 ext4 文件系统未对齐时会 fallback - 用
/proc/<pid>/io</pid>查看 worker 进程的rchar和wchar:开启 sendfile 后,rchar(内核态读字节数)应接近请求总量,而wchar(写入用户态字节数)应极低甚至为 0


















