sendfile 高效需三指令协同生效:sendfile on、tcp_nopush on、tcp_nodelay off;必须避开gzip、代理、内容改写及非本地文件等退化条件,且仅对真实静态文件生效。

sendfile 不是单开一个开关就能提速的机制,它要真正高效,必须三要素齐备、退化条件全避开、配套设置不干扰。
必须同时启用的三个核心指令
单独写 sendfile on; 几乎没用。只有三者协同,才能让内核走零拷贝路径:
- sendfile on;:激活内核直送能力,数据从磁盘到 socket 全程在内核态流转
- tcp_nopush on;:依赖 sendfile 生效,把响应头和文件数据合并进尽可能少的 TCP 报文段,减少小包
- tcp_nodelay off;:关闭 Nagle 算法,避免破坏 tcp_nopush 的攒包逻辑;静态资源重吞吐而非首字节延迟
哪些情况会让 sendfile 自动失效
即使配置全对,只要出现以下任一情形,Nginx 就会悄悄回退到 read()+write() 模式,失去零拷贝优势:
- 启用了 gzip on 或 gunzip on(压缩必须进用户态)——建议改用 gzip_static on + 预生成 .gz 文件
- 用了 proxy_pass、fastcgi_pass 等代理指令
- 配置了 sub_filter、add_before_body 等内容改写功能
- 文件位于 NFSv3、CIFS、FUSE 或某些容器存储卷上(不支持 sendfile 系统调用)
- 响应中含 Range 请求头(如视频拖拽),或缺少 Content-Length(如 chunked 编码)
按资源类型做 location 级精准控制
不建议在全局 http 块盲目开启所有功能,应结合后缀精细化配置:
-
图片/字体/图标:
location ~* \.(jpg|png|webp|woff2|ico)$中启用 sendfile + tcp_nopush,同时关闭 gzip -
大文件(视频/安装包):
location ~ \.(mp4|zip|iso)$可加 sendfile_max_chunk 512k,防止单次传输阻塞事件循环 - HTML/JS/CSS:若用 gzip_static on 提供预压缩版本(如 index.html.gz),仍可走 sendfile 路径
配套优化进一步释放性能
这些设置不改变零拷贝路径,但能消除瓶颈、提升整体稳定性:
- open_file_cache max=10000 inactive=60s;:缓存文件句柄与元信息,大幅减少高并发下的 open()/stat() 开销
- access_log off;:在静态资源 location 中关闭访问日志,避免 I/O 成瓶颈
- expires 1y; add_header Cache-Control "public, immutable";:强缓存减少重复请求,间接降低服务端压力


















