Nginx 调优别急着改配置,先把这几个观测点跑通
站点刚上线那阵子,访问量不大,Nginx 用默认配置跑得好好的。等到日活上来,或者做了一次推广,同样的机器开始出现请求排队。页面加载从原来的 80ms 变成 600ms,后台看 CPU 和内存都没打满,问题就出在连接处理和配置参数没对齐上。调优不是把所有参数往大了改,而是先弄清楚瓶颈在哪个环节。
先看两个数:worker_connections 和系统文件描述符上限
Nginx 的并发能力受 worker_connections 和 Linux 的 ulimit -n 共同限制。默认 worker_connections 是 512,如果开了 4 个 worker 进程,理论并发连接上限是 2048。但系统默认的 nofile 限制往往只有 1024,实际能撑住的连接数会被压到 1024 以内。
这两个值必须同时放大才有意义。只改 Nginx 配置文件里的 worker_connections,不改 /etc/security/limits.conf 里的 nofile,进程在 1024 个连接时就开始报「too many open files」。反过来只放大系统限制,Nginx 自己还是 512 的池子,一样卡住。
我一般会先用 ulimit -n 确认当前 shell 的限制,再看 nginx -V 确认编译时有没有带 --with-file-aio。这两步花不到两分钟,但能省掉后面反复重启的功夫。
keepalive_timeout 调长还是调短,取决于你的流量形态
默认 keepalive_timeout 是 65 秒。对于 API 服务,客户端复用连接的意愿强,适当延长到 75 秒可以减少 TCP 握手次数。但如果是静态资源站,大量短连接来自不同 IP,保持长连接反而占用 worker 的处理槽位。
这里有个取舍:调长 keepalive 能降低新建连接的 CPU 开销,但每个空闲连接仍然占着内存和文件描述符。一台 4G 内存的机器,如果并发连接数到 8000,每个连接按 10KB 估算,光连接状态就吃掉 80MB,加上缓存和缓冲区,内存压力不小。换我我会先看 ss -s 里的 estab 连接数,如果空闲连接占比超过 40%,就适当缩短 keepalive_timeout。
gzip 也是类似的逻辑。开启 gzip 能省带宽,但压缩本身消耗 CPU。gzip_comp_level 从 5 调到 9,压缩率提升有限,CPU 占用却可能翻倍。通常 level 5 已经能压掉 70% 左右的文本体积,再往上加不划算。
静态资源和动态请求分离,效果比调参数明显
把图片、CSS、JS 这类静态文件交给 Nginx 直接返回,动态请求才转发给后端,这是最直接的提速手段。Nginx 处理静态文件的效率远高于应用服务器,一台 2 核 4G 的机器用 Nginx 扛静态资源,跑到几千 QPS 不稀奇。
- 用 location ~* \.(jpg|png|css|js)$ 匹配静态文件,设置 expires 30d,让浏览器缓存。
- 开启 sendfile on 和 tcp_nopush on,减少文件传输时的系统调用次数。
- 对于大文件下载场景,考虑加 aio on 和 directio 4m,避免大文件读写阻塞 worker 进程。
如果静态资源量特别大,单机磁盘 IO 成为瓶颈,可以考虑把静态资源放到独立的大带宽服务器上。比如香港大带宽服务器 XXV,E5-2630L*2 配 32G 内存和 100M 带宽,月付 $808.50,适合做静态资源分离的节点,Nginx 只负责回源和缓存。
缓存和限流是兜底,别等被打爆才加
proxy_cache 能把后端重复请求挡在 Nginx 层。设置 proxy_cache_path 时,keys_zone 给 10m 到 20m 就够存几万个 key,max_size 根据磁盘空间定,通常给 1G 到 5G。缓存有效期用 proxy_cache_valid 按状态码分别设置,200 的页面可以缓存 10 分钟,404 缓存 1 分钟就行。
限流方面,limit_req_zone 和 limit_conn_zone 是最常用的两个模块。单 IP 限制连接数可以防爬虫,限制请求速率可以防突发流量。但限流阈值不能设得太死,否则正常用户的并发请求也会被误伤。我一般会先开 log 观察一周,看正常用户的峰值请求频率,再按峰值的 1.5 倍设阈值。
说到底,Nginx 调优的顺序应该是:先确认系统层面的限制有没有卡住,再调 Nginx 自身的连接和超时参数,然后做动静分离和缓存,最后才是限流兜底。反过来先加限流,可能把正常流量也限掉了,排查起来更麻烦。
如果你现在跑的是 1 核 1G 的入门机器,先把 worker_connections 和 ulimit 对齐,开启 gzip level 5,静态资源加 expires 头,这三步做完就能看到响应时间下降。等并发稳定超过 2000 再考虑上缓存和限流。机器配置不够时,换一台带宽和内存更充裕的独立服务器比调参数见效快,比如香港大带宽服务器 XVIII,Platinum-8168*2 配 64G 内存和 30M 带宽,月付 $418.50,适合中等规模的 Web 业务直接跑 Nginx 加后端应用。