sendfile 与 tcp_nopush 必须协同生效:仅当 sendfile on 启用时,tcp_nopush 才通过 tcp_cork 合并响应头与体、减少小包;需关闭 gzip/etag/expires 等干扰模块,并按资源类型分 location 精准配置。

调整 sendfile 和 tcp_nopush 的核心,是让内核直接搬运文件、并把数据“装箱”发出去,减少拷贝和小包——但前提是二者必须协同生效,不能孤立配置。
先确认 sendfile 是否真正启用
这是所有优化的起点。只有 sendfile on 生效时,tcp_nopush 才起作用;否则 Nginx 会退回到用户态读写路径,tcp_nopush 完全无效。
- 检查是否被其他模块干扰:gzip、etag、expires、sub_filter、proxy_buffering 等都会强制关闭 sendfile
- 静态服务建议统一关闭干扰项:
gzip off; etag off; expires off; - 验证方式:用
strace -p $(pgrep nginx) -e trace=sendfile观察系统调用,看到 sendfile 调用即表示启用成功
tcp_nopush 必须与 sendfile 搭配使用
tcp_nopush on 的作用是启用 TCP_CORK,让内核把响应头和响应体攒在一起,等缓冲区满或连接关闭时再一次性发出——这能显著减少网络小包数量,提升吞吐。
- 仅在
sendfile on下有效;若 sendfile 关闭,该参数无实际影响 - 适合大文件传输(如视频、下载包),配合
sendfile_max_chunk 512k可避免单次 sendfile 阻塞 worker - 不要和
tcp_nodelay on在同一场景下强求“低延迟+高吞吐”——它们逻辑冲突,需按资源类型取舍
按资源类型分 location 精准配置
全局一刀切容易误伤。不同资源对延迟和吞吐的敏感度不同,应差异化启用:
- 大文件(.mp4、.zip、.iso):
sendfile on; tcp_nopush on; tcp_nodelay off;——专注吞吐,避免首包拆分 - 中小资源(JS/CSS/woff2/webp,≤500KB):
sendfile on; tcp_nopush on; tcp_nodelay on;——既合并主体,又确保末尾数据不等待 - 极小资源(favicon.ico、robots.txt):可只开
tcp_nodelay on,tcp_nopush无意义,延迟可降 100–200ms
配套必须同步落实的关键项
单独调这两个参数收益有限,以下三项需一并配置:
-
access_log off;:对大文件 location 关闭访问日志,避免磁盘 I/O 成为瓶颈 -
keepalive_timeout 60;:维持长连接,让高带宽链路持续跑满,减少建连开销 -
sendfile_max_chunk 512k;:限制单次 sendfile 最大数据量,防止单个大文件阻塞 worker 进程











