nginx高效发送静态资源需同时启用sendfile on、tcp_nopush on、tcp_nodelay off,并避免gzip、range请求、nfs挂载等导致退化;推荐gzip_static预压缩+open_file_cache缓存+关闭日志等优化。

要让 Nginx 处理静态资源时真正高效发送文件,核心是激活并守住内核级零拷贝路径——不是简单打开 sendfile on,而是确保它不退化、不绕路、不被干扰。
必须成套启用的底层指令
单独配置任意一项都无效,三项需同时存在且语义协同:
- sendfile on;:启用内核直传能力,跳过用户态缓冲区
- tcp_nopush on;:配合 sendfile,攒满 TCP 报文段再发,避免小包洪流
- tcp_nodelay off;:显式关闭 Nagle 算法,防止与 tcp_nopush 冲突
坚决避开导致退化的配置
只要出现以下任一情况,Nginx 会自动回退到 read()+write() 模式,四次拷贝+四次上下文切换立刻拉高 CPU:
- 启用
gzip on或gunzip on(压缩/解压必须进用户态) - 使用
etag、expires动态计算头(如expires epoch;) - 客户端发起
Range请求(如视频拖拽),或gzip_static on但对应 .gz 文件缺失 - 静态文件存于 NFS/CIFS/FUSE 等不支持 sendfile 的挂载点
- location 中混用
proxy_pass、sub_filter或add_before_body
推荐替代方案:保留压缩又不破坏零拷贝
想压缩文本资源(JS/CSS/HTML)又不牺牲 sendfile,关键在“压缩前移”:
- 构建阶段为每个文件生成
.gz副本(如main.js→main.js.gz) - Nginx 配置:
gzip_static on;+gzip off; - 确保
mime.types已声明类型(如application/javascript),否则 .gz 不会被识别 - 确认编译时含
ngx_http_gzip_static_module,否则报unknown directive
配套加固项,堵住其他 CPU 泄漏点
零拷贝只是起点,还需收敛高频系统调用和日志开销:
-
open_file_cache max=10000 inactive=60s; open_file_cache_valid 60s; open_file_cache_min_uses 2;:缓存句柄与元数据,减少open()/stat()开销 -
access_log off;:纯静态 location 中彻底关闭日志;若需记录,禁用含$body_bytes_sent的字段(需等响应完成) - 静态资源 location 使用前缀匹配(如
location /img/),避免正则(location ~* \.png$)触发 PCRE 计算 - 大文件(≥4MB)可加
read_ahead 1m;,提示内核预加载页缓存(SSD 上效果明显)
验证是否真走零拷贝路径
不能只看配置语法正确,要观察运行时行为:
- 用
strace -p $(pgrep nginx) -e trace=sendfile64,read,write观察 worker 进程是否持续调用sendfile64,而非read+write - 压测对比:开启后系统态 CPU(sy%)应明显下降,QPS 提升 20%–50%
- 检查文件是否满足前提:本地 ext4/XFS 文件、大小 ≥4KB、未被锁、权限可读











