Nginx 调优别只改 worker_connections:从静态缓存到 keepalive 的取舍
很多人第一次碰 Nginx 调优,是因为网站突然变慢:访问量翻了一倍,CPU 占用却先飙到 100%,页面加载从 200ms 涨到两秒。登上去一看,配置文件还是装完系统时的默认值。默认配置不是错,它只是按「单机跑个小站」的假设写的。真到了每天几万 PV,几个关键参数就得按实际负载重新算一遍。
下面按「先改什么、再改什么」的顺序讲。每一处我都会说清楚改了能换回多少,乱改会付出什么代价。最后给一套可以直接落地的配置片段。
worker_connections 不是越大越好,先算清楚并发怎么来的
Nginx 默认 worker_connections 是 1024。这个数字的意思是每个 worker 进程同时能处理的连接数,注意是连接不是请求。一个浏览器打开页面,可能同时建立 6 到 8 个连接拉 CSS、JS 和图片。1024 个连接,撑不住 200 个真实并发用户。
但把它直接改成 65535 也不对。连接数受文件描述符限制,worker_rlimit_nofile 得跟着调;每个连接还要占内存,连接数堆太高,内存先撑不住。我一般按这个顺序算:先看机器能开多少 fd,再倒推 worker_connections。
- 先查系统上限:ulimit -n 和 /proc/sys/fs/file-max
- worker_rlimit_nofile 设成 fd 上限的 80% 左右,留余量给系统其它进程
- worker_connections 再按 worker_rlimit_nofile 除以 worker 数量来定
举个例子:一台 4 核机器,fd 上限开到 65535,配 4 个 worker,每个 worker_connections 给到 10240 就够。再往上加,CPU 先成为瓶颈,连接数堆着也没用。
静态文件交给 sendfile 和 open_file_cache
图片、CSS、JS 这类静态资源占的请求量往往超过一半,但它们根本不需要 Nginx 去读磁盘再进用户态。sendfile 让内核直接把文件送到网卡,省掉一次内存拷贝。
open_file_cache 更值得开。它缓存的是文件描述符和文件元信息,请求来了不用每次去 stat 磁盘。对图片站、下载站效果明显,命中率高的时候磁盘 IO 能降一大截。
代价是文件更新后缓存不会立刻失效,得等 open_file_cache_valid 设的秒数过去。如果你的站点文件一天改不了一次,这个代价可以忽略;如果文件频繁变动,把 valid 时间调到 10 秒以内。
这里有个取舍:open_file_cache 占内存,文件数特别多(几十万个)的时候,max 设太大反而拖慢。我一般从 10000 起步,看命中率再往上加。
keepalive 和 gzip 的取舍:省了握手,可能多占内存
keepalive_timeout 默认 65 秒。意思是连接用完还挂着 65 秒等下一个请求。对短连接密集的 API 服务,这个值偏大,连接池被占满,新请求排队。我一般调到 15 到 30 秒。
调小的代价是客户端可能频繁重连,移动网络下体验会差一点。所以静态资源站可以留长一些,API 站调短。
gzip 也是同理。开 gzip 能省带宽,文本类响应压到原来的三分之一很常见。但压缩本身吃 CPU,高并发下 CPU 先满就是它干的。我的做法是只对 text、json、js、css 这几类压缩,图片视频本来压不动,别浪费 CPU。gzip_comp_level 给 4 到 5 就够,6 以上收益递减。
如果后端是动态应用,upstream 里的 keepalive 也别忘。Nginx 到后端默认是短连接,每次请求重新握手,后端压力大。加一段 upstream keepalive 32,能省下不少 TIME_WAIT。
落到配置:先改这五行,再谈进阶
把上面几处合起来,一份能直接用的核心片段大致是这样:worker_processes auto; worker_rlimit_nofile 65535; events 里 worker_connections 10240; http 块里开 sendfile on 和 open_file_cache; keepalive_timeout 20。
改完别急着重启,先 nginx -t 测配置,再 reload。上线后盯两个指标:active connections 和 requests per second。如果 active 一直贴着 worker_connections 上限,说明还得加 worker 或换机器。
真到单机扛不住的时候,与其继续在参数上抠,不如看看是不是该上独立物理服务器。共享环境下 CPU 和 IO 被别人抢,参数调得再细也白搭。像 香港服务器9 这类 Gold-6133*2 / 64G 的配置,双路 CPU 加 64G 内存,跑高并发 Nginx 前端会比小内存 VPS 稳得多。
我的建议是:日 PV 一万以内,先把上面几个参数改对,不用换机器;日 PV 十万以上且经常 CPU 打满,再考虑从云主机换到独立物理服务器,那时候瓶颈早就不在 Nginx 配置上了。