sendfile 是降低 nginx 静态资源传输延迟最直接有效的机制,需与 tcp_nopush on 和 tcp_nodelay off 协同启用,并避开 gzip、内容改写、非本地存储等退化场景,按资源类型精细化配置才能真正生效。

sendfile 是降低 Nginx 静态资源传输延迟最直接有效的机制,它让内核绕过用户态内存拷贝,直接将磁盘文件内容送入网卡缓冲区。真正起效不靠单开 sendfile on,而是一整套协同配置与避坑策略。
必须成套启用的三个核心指令
单独开启 sendfile 没用,需三者同时存在且位置一致(通常放在 server 或 location 块中):
- sendfile on;:激活零拷贝路径,数据从磁盘到 socket 全程在内核态流转
- tcp_nopush on;:依赖 sendfile 生效,把响应头和文件数据合并进一个 TCP 包,减少小包数量
- tcp_nodelay off;:关闭 Nagle 算法,避免破坏 tcp_nopush 的攒包逻辑;静态资源重吞吐而非首字节延迟
避开常见退化场景
即使配置正确,以下情况会让 sendfile 自动失效,回退到 read()+write() 四次拷贝模式:
- 启用了
gzip on(运行时压缩必须进用户态)——改用gzip_static on;+ 预压缩文件(如style.css.gz) - 使用了
sub_filter、add_before_body等内容改写功能 - 文件位于 NFSv3、CIFS 或某些容器存储卷上(不支持 sendfile 系统调用)
- 响应中含
Range请求头(如视频拖拽),Nginx 需切片处理 - 通过
proxy_pass、fastcgi_pass等代理转发,不再是直读本地文件
按资源类型精细化配置
全局开启易误伤,推荐在 location 中按后缀控制:
- 图片/字体/图标:
location ~* \.(jpg|png|webp|woff2|ico)$ { 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; }(防止单次传输阻塞事件循环) - HTML 文件:
sendfile on仍有效,但需搭配gzip_static on和预压缩.html.gz,否则 gzip 会禁用 sendfile
配套优化进一步释放性能
这些不改变零拷贝路径,但能减少干扰、提升稳定性:
-
open_file_cache max=10000 inactive=60s;:缓存文件句柄和元信息,大幅减少高并发下的
open()和stat()系统调用 - access_log off;:在静态资源 location 中关闭日志,避免 I/O 成瓶颈
- expires 1y; add_header Cache-Control "public, immutable";:强缓存减少重复请求,间接降低服务端压力











