sendfile与tcp_nopush如何协同实现超大文件分发的零拷贝技术?
- 内容介绍
- 相关推荐
本文共计1010个文字,预计阅读时间需要5分钟。
使用`sendfile`和`tcp_nopush`功能时,必须同时启用,并且仅在满足以下三个硬件条件时才能生效:
为什么单独开 sendfile 或 tcp_nopush 都没用
tcp_nopush 不是“延迟发送开关”,它只是告诉内核:等响应头写完、且后续数据(比如文件开头)能凑满一个 TCP 段(MSS ≈ 1448 字节)时,再一起发出去。这个“后续数据”必须来自 sendfile 路径——即内核直接从磁盘页缓存搬进 socket 发送队列,不经过用户态缓冲区。
若 sendfile off,Nginx 先 read() 到用户空间 buffer,再 write() 到 socket,此时 tcp_nopush 完全被忽略,Nginx 日志里会出现 tcp_nopush is ignored 警告。
常见误判点:
- 看到配置里写了
tcp_nopush on就以为生效了 - 在 proxy_pass 场景下全局开了
sendfile on,但后端返回的是 chunked 编码或没带Content-Length - 启用了
gzip on,哪怕只压缩 JS/CSS,也会导致整个请求链路禁用 sendfile
必须满足的三个运行时前提
配置写了不算数,Nginx 在每次响应时都会动态判断是否走零拷贝路径。
本文共计1010个文字,预计阅读时间需要5分钟。
使用`sendfile`和`tcp_nopush`功能时,必须同时启用,并且仅在满足以下三个硬件条件时才能生效:
为什么单独开 sendfile 或 tcp_nopush 都没用
tcp_nopush 不是“延迟发送开关”,它只是告诉内核:等响应头写完、且后续数据(比如文件开头)能凑满一个 TCP 段(MSS ≈ 1448 字节)时,再一起发出去。这个“后续数据”必须来自 sendfile 路径——即内核直接从磁盘页缓存搬进 socket 发送队列,不经过用户态缓冲区。
若 sendfile off,Nginx 先 read() 到用户空间 buffer,再 write() 到 socket,此时 tcp_nopush 完全被忽略,Nginx 日志里会出现 tcp_nopush is ignored 警告。
常见误判点:
- 看到配置里写了
tcp_nopush on就以为生效了 - 在 proxy_pass 场景下全局开了
sendfile on,但后端返回的是 chunked 编码或没带Content-Length - 启用了
gzip on,哪怕只压缩 JS/CSS,也会导致整个请求链路禁用 sendfile
必须满足的三个运行时前提
配置写了不算数,Nginx 在每次响应时都会动态判断是否走零拷贝路径。

