tcp_nopush生效必须满足四条件:sendfile on启用零拷贝路径;响应头含明确content-length(非chunked);禁用gzip/proxy_pass等用户态处理;搭配output_buffers 2 128k防过早冲刷。

要让 tcp_nopush 在 Nginx 静态资源服务中真正起效,不能只写一行 tcp_nopush on;,它必须和几个关键条件协同工作——否则参数形同虚设,网络包该碎还是碎。
必须开启 sendfile 才能激活 tcp_nopush
tcp_nopush 只在 sendfile on; 启用时才参与数据发送流程。因为它的作用机制依赖内核零拷贝路径:Nginx 把文件 fd 直接交给内核,由内核决定何时把响应头+完整响应体“攒成一个满包”再发出去。如果没开 sendfile(比如用了 proxy_pass 或需要 gzip 处理),Nginx 就得自己读文件、拼响应、走用户态发送,tcp_nopush 就完全不生效。
- 确保配置中包含:
sendfile on; - 静态服务推荐用
root+try_files方式,天然适配sendfile - 避免在该 location 中混用
proxy_pass或gzip on(除非你确认后端返回的是完整 Content-Length 且已全缓存)
响应长度必须明确,不能是 chunked
tcp_nopush 要“攒包”,就得知道整个响应有多大。Nginx 必须能提前拿到准确的 Content-Length,否则无法判断是否收齐了全部数据,只能边收边发,退化为普通流式行为。
- 静态文件服务(如
root /var/www;)自动计算并设置Content-Length,满足条件 - 若通过
proxy_pass拉取对象存储或 CDN 回源,后端响应必须带Content-Length,且不能是Transfer-Encoding: chunked - 检查响应头:用
curl -I http://yoursite/style.css确认有Content-Length: 12480这类字段
建议搭配 output_buffers 提升大文件表现
默认的输出缓冲区(output_buffers 2 32k)对小文件够用,但遇到 500KB 以上的 JS/CSS/图片时容易提前冲刷,导致 tcp_nopush 来不及攒满就发了。
- 在对应
location块中加:output_buffers 2 128k; - 这个值不是越大越好,需结合典型资源大小调整;128k 覆盖绝大多数前端资源
- 配合
tcp_nopush on;和sendfile on;三者一起启用
验证是否真正生效
别靠猜,用工具看真实 TCP 行为:
- 用
tcpdump -i any port 80 -w test.pcap抓包,对比同一 CSS 文件开启/关闭tcp_nopush时的包数量和大小——有效时,MSS=1448 的小包应明显减少,出现更多接近 1448 字节的满包 - 用
ss -i state established '( dport = :80 )'查看连接的retrans和unacked,数值下降说明传输更稳、效率更高 - 注意:对 favicon.ico、robots.txt 这类极小文件,
tcp_nopush几乎无意义,反而应靠tcp_nodelay on保首字节延迟











