nginx动静分离中,sendfile需精准配置静态资源location块,配合tcp_nopush、tcp_nodelay off,并规避gzip、sub_filter、range等退化条件才能生效。

在动静分离架构中,Nginx 作为网关层,静态资源走内核级 sendfile 路径是提升吞吐最直接有效的手段——它把文件传输从“用户态搬运”变成“内核直通”,大幅降低 CPU 开销和延迟。关键不是简单打开开关,而是让 sendfile 在正确路径上稳定运行,同时避开所有退化条件。
只对静态资源启用 sendfile,动态请求自动绕过
sendfile 仅对真实磁盘上的静态文件生效(如 /var/www/images/logo.png),对 proxy_pass、fastcgi_pass、grpc_pass 等动态后端响应完全无效。因此必须按资源类型做 location 精准划分:
- 用正则匹配静态后缀:例如 location ~* \.(js|css|png|jpg|woff2|svg)$
- 确保 root 或 alias 指向本地 ext4/xfs 文件系统路径,避免 NFSv3、FUSE、Docker overlay2 等不支持 sendfile 的存储
- 动态接口(如 /api/、/admin/)不配 sendfile,也不受干扰——Nginx 会自然走 read/write 流程
三指令协同:sendfile + tcp_nopush + tcp_nodelay off
单开 sendfile on 不起作用。必须成套配置才能打通零拷贝链路:
- sendfile on;:激活内核直送能力
- tcp_nopush on;:让响应头 + 文件数据合并进一个或少数几个 TCP 包,减少 ACK 往返和小包数量
- tcp_nodelay off;:关闭 Nagle 算法,否则会与 tcp_nopush 冲突,导致攒包失败
这三项建议统一写在静态资源 location 块内,不放在 http 全局块,避免误影响代理场景。
堵住所有 sendfile 失效漏洞
即使配置全对,只要出现以下任一情况,Nginx 就会静默回退到低效的 read/write 路径:
- gzip on; 或 gunzip on;:压缩必须进用户态,强制绕过 sendfile;应改用 gzip_static on; 配合预压缩 .gz 文件
- 启用了 sub_filter、add_header(含动态变量)、etag、expires:涉及响应头重写或计算,触发用户态介入
- 客户端发起 Range 请求(如视频拖拽):需切片处理,无法整块直传
- 文件被其他进程加锁,或以 O_DIRECT 方式打开:内核无法安全直送
配套优化进一步释放吞吐潜力
这些配置不改变 sendfile 路径,但能消除瓶颈、提升稳定性:
- open_file_cache max=10000 inactive=60s;:缓存文件句柄和元信息,避免高并发下反复 open/stat
- access_log off;:静态资源 location 中关闭日志,防止 I/O 成为瓶颈
- sendfile_max_chunk 512k;:防止单次大文件传输阻塞事件循环,适合图片、短视频首段加载
- expires 7d; 或 add_header Cache-Control "public, max-age=604800";:减轻重复请求压力
不复杂但容易忽略











