Nginx 用 sendfile 加速静态资源的核心是内核直接搬运磁盘数据至网络缓冲区,跳过用户态拷贝;必须同时启用 sendfile on、tcp_nopush on 和 tcp_nodelay off 三指令,且避开 gzip、代理、无 Content-Length 等失效条件,否则自动退化为 read()+write() 模式。

Nginx 用 sendfile 加速静态资源,核心不是“把文件读进内存”,而是让内核直接把磁盘数据搬进网络发送缓冲区,跳过用户态拷贝。真正起效必须成套配置、避开干扰项,否则会悄悄退化为低效的 read() + write() 模式。
必须同时启用的三个基础指令
单独开 `sendfile on` 没用,三者缺一不可:
- sendfile on;:激活内核零拷贝路径,仅对真实静态文件(非代理、非动态生成)生效
- tcp_nopush on;:配合 `sendfile`,攒满 TCP 包再发,避免小包泛滥,提升吞吐
- tcp_nodelay off;:关闭 Nagle 算法;若设为 `on`,会强制立即发包,破坏 `tcp_nopush` 的攒包逻辑
按资源类型精细化配置 location
不建议在全局 `http` 块盲目开启,应针对不同后缀做差异化控制:
- 图片类:
location ~* \.(jpg|png|webp|svg)$ { sendfile on; tcp_nopush on; tcp_nodelay off; gzip off; } - 大文件类(视频、安装包):
location ~ \.(mp4|zip|iso)$ { sendfile on; tcp_nopush on; tcp_nodelay off; sendfile_max_chunk 512k; }(防止单次传输阻塞事件循环) - 文本类(CSS/JS):若已由构建工具预压缩为 `.gz`,可配
gzip_static on;,仍能走 `sendfile` 路径
避开常见失效场景
以下任一情况都会导致 `sendfile` 自动禁用,回退到普通读写流程:
- 启用了 `gzip on`(未用 `gzip_static`)、`sub_filter`、`add_before_body` 等内容改写功能
- 配置了 `proxy_pass`、`fastcgi_pass` 或 `X-Accel-Redirect` 返回非本地路径
- 文件位于 NFSv3、FUSE 或某些容器存储驱动挂载点(内核不支持 `sendfile()`)
- 响应缺少 `Content-Length` 头(如使用 `chunked` 编码)
配套优化提升整体效率
`sendfile` 是核心,但需其他配置协同才能释放全部性能:
-
关闭日志:在静态 `location` 中加
access_log off;,避免高并发下 I/O 成瓶颈 -
缓存元数据:用
open_file_cache max=10000 inactive=60s; open_file_cache_valid 60s; open_file_cache_min_uses 2; open_file_cache_errors on;减少 `stat()` 和 `open()` 系统调用 -
文件系统挂载参数:确保静态目录所在分区启用
noatime,避免每次读取更新访问时间戳


















