Nginx 调优别只改 worker_connections:连接数、缓存与内核参数的取舍
刚上线那几天跑得好好的,流量一涨就发现 Nginx 的响应时间从几十毫秒跳到几百毫秒。这时候多数人的第一反应是加机器,但加完发现带宽利用率还是上不去,CPU 也没打满。问题往往不在硬件,而在配置和内核参数没对齐。调优这件事有顺序,顺序错了就是白折腾。
先搞清楚瓶颈在哪,别上来就改参数
Nginx 的瓶颈通常分三层:CPU 处理能力、磁盘 I/O、网络吞吐。三层里哪一层先到顶,决定了该往哪个方向调。判断方法不复杂,用 top 看 CPU 的 wa(等待 I/O)占比,用 iostat 看磁盘的 %util,再用 sar -n DEV 看网卡的实际吞吐。
如果 wa 长期超过 10%,说明磁盘跟不上,这时候调 worker_connections 没有意义。如果网卡已经跑满,但 CPU 还有余量,那是带宽买少了,不是配置问题。
我一般会先跑一轮压测,拿到基线数据再动手。没有基线的调优等于盲调,改完也不知道是变好了还是变差了。
连接数与文件描述符:最容易踩的坑
worker_connections 这个参数被讲得最多,但它不是孤立的。一台机器能同时处理多少连接,取决于三个值里的最小值:
- Nginx 配置里的 worker_connections 乘以 worker_processes
- 系统级的 fs.file-max(内核允许打开的最大文件数)
- 进程级的 ulimit -n(单个进程能打开的文件描述符数)
常见的坑是只改了 Nginx 的配置,没动 ulimit。默认 ulimit -n 很多发行版是 1024,Nginx 配了 10240 也白搭,因为进程根本开不了那么多文件描述符。改 ulimit 要在 /etc/security/limits.conf 里加 nofile 项,并且确认 systemd 服务文件里没有覆盖。
worker_processes 设成 auto 通常够用,但如果是 CPU 密集型场景(比如大量 SSL 握手),可以设成等于物理核心数。超线程出来的逻辑核不一定带来线性提升,这点我没实测过所有型号,只能说是多数情况下的经验。
缓存与压缩:省带宽还是省 CPU,得选一个
静态资源多的站点,开缓存是性价比最高的一步。proxy_cache 可以把后端返回的内容缓存在本地,减少回源次数。但缓存要设对 key,否则命中率上不去。
gzip 压缩能省 50% 到 70% 的文本传输量,代价是 CPU。如果 CPU 已经有压力,gzip 反而会拖慢响应。我一般会先看 CPU 余量再决定开不开,以及压缩级别设多少。级别 1 到 3 的压缩率已经接近级别 9 的八成,但 CPU 开销小很多。
有一个取舍要提前想清楚:省下的是带宽钱,花出去的是 CPU 时间。如果你的机器 CPU 本来就在 70% 以上跑,开高压缩级别就是给自己找麻烦。
内核参数调优:不是越多越好
内核参数这块,网上流传的「一键优化脚本」往往塞了几十行,但真正有影响的就那么几个。改多了反而可能引入问题。
比较关键的几项:net.core.somaxconn 决定 accept 队列长度,高并发下设小了会丢连接;net.ipv4.tcp_tw_reuse 让 TIME_WAIT 状态的连接可以被复用,短连接多的场景有用;net.ipv4.tcp_max_syn_backlog 影响半连接队列,防御 SYN flood 时有意义。
这些参数改完要重启网络服务或者用 sysctl -p 生效。改之前建议记录原值,出问题能回滚。
如果调优之后单机还是扛不住,说明该考虑换硬件或者加机器了。秀米云香港物理服务器 VII(E5-2678V3 Dual / 32G / 10M,月付 $410)这类配置适合中等流量的站点,具体可以看 产品页 确认参数。
调优的终点是够用,不是跑分
我见过不少配置调得很漂亮但业务没起色的情况。调优的目是让机器在预期流量下稳定运行,不是把压测数字刷到最高。
判断标准很简单:在峰值流量下,CPU 不超过 70%,磁盘 %util 不超过 80%,响应时间的 P99 在可接受范围内。达到这个状态就可以停了,继续调收益递减。
如果机器本身规格不够,比如内存只有 2G 还要跑数据库和 Nginx,那再怎么调参数也是拆东墙补西墙。这种情况换一台内存更大的机器比调优更直接。