Nginx 调优别只盯着 worker 数:几个决定吞吐的隐藏参数
很多人第一次调 Nginx,都是被监控面板上那条卡住的 QPS 曲线逼出来的。机器配置不算差,8 核 16G,跑一个反向代理加静态资源,压测到 3000 左右就上不去了,CPU 还只用了三成。这时候去翻配置文件,多半会发现 worker_connections 还是默认的 512,keepalive_timeout 也只有 65 秒。改完这两个值,同一台机器通常能翻一倍以上。下面把几个真正影响吞吐的参数拆开讲,顺便说清楚哪些改动是白费力气。
worker 进程数不是越多越好,绑定 CPU 才是关键
worker_processes 设成 auto,让 Nginx 自己按核数起进程,这一步基本没争议。真正容易被忽略的是 worker_cpu_affinity,也就是把每个 worker 绑到固定的核上。不绑的话,操作系统会在核之间来回调度,缓存命中率下降,高并发下抖动明显。8 核机器写成 00000001 到 10000000 这样的掩码,每个 worker 独占一核,实测延迟曲线会平很多。
但核数不是越多越好。我见过 32 核的机器起 32 个 worker,结果上下文切换开销把收益吃掉了。多数情况下 worker 数等于物理核数就够,超线程出来的逻辑核可以先不用。
连接数、文件句柄、keepalive 三者的联动关系
worker_connections 决定单个 worker 能同时处理多少连接,但这个值受系统级 ulimit -n 限制。改了 Nginx 配置没改系统限制,等于白改。通常要把 /etc/security/limits.conf 里的 nofile 提到 65535 以上,再确认 worker_rlimit_nofile 跟它对齐。
keepalive 这块分两个方向。对客户端,keepalive_timeout 设太长会占着连接不放,设太短又会让浏览器频繁重连。一般 30 到 65 秒之间比较稳。对上游后端,upstream 块里的 keepalive 才是重点,不开的话每个请求都要重新建 TCP,后端压力会大很多。
- worker_connections 建议 10240 起步,配合 ulimit 一起调
- upstream keepalive 通常设 32 到 64,视后端数量调整
- keepalive_requests 默认 100,静态资源多的站点可以提到 1000
sendfile、gzip、缓存:开了不一定快
sendfile on 配合 tcp_nopush on,能让静态文件走零拷贝路径,这个组合在图片、视频这类大文件场景收益明显。但如果是纯 API 转发,body 很小,开不开差别不大,反而 tcp_nopush 会引入额外延迟。
gzip 是最容易开错的一项。文本类响应压缩后能省一半以上带宽,但图片、视频、已经压缩过的包再压就是浪费 CPU。gzip_min_length 设成 1024,太小的响应压了不划算;gzip_comp_level 用 5 就够,调到 9 压缩率只多几个点,CPU 却翻倍。
代理缓存 proxy_cache 是另一个分水岭。后端生成一次要 200ms 的页面,缓存命中后能压到 20ms 以内。但缓存策略没配好,容易把用户相关的数据也缓存出去,这点上线前一定要用带 cookie 的请求验一遍。
调优之前先确认瓶颈在哪
把上面这些参数都拉满,QPS 还是上不去,那多半问题不在 Nginx。用 top 看 si 和 wa 两个值,si 高说明软中断吃满了,得调网卡多队列;wa 高说明磁盘拖后腿,静态文件该上 SSD 或者干脆放 CDN。压测工具本身的并发也要确认,ab 单机跑不出几万 QPS,换 wrk 或者多台机器一起压才准。
如果后端是数据库或者应用服务器先到瓶颈,Nginx 这边再怎么调都是白搭。先定位再动手,比一股脑改配置省事得多。反代层真要扛量,机器本身的网络规格也得跟上,像香港高防独立服务器2*E5-2660这种 32G 内存加 10M 带宽的配置,适合中小规模的反向代理与静态分发,月付 $117.30,预算有限时比堆 CPU 更实际。带宽跑到 G 口级别的站点,则要看美国西雅图大带宽服务器 V,Gold-6133*2 加 64G 内存,G 口带宽月付 $703.50,静态资源量大的场景不容易被带宽卡住。
结论很直白:8 核以下的机器,先把 worker_connections、ulimit、upstream keepalive 这三处调到位,通常就能解决八成问题。gzip 和 sendfile 按业务类型决定开不开,别默认全开。真要往上冲吞吐,先确认瓶颈在不在 Nginx,不在的话换机器比改配置有效。