Nginx 调优别急着改配置:先看这三层瓶颈在哪
上线三个月就变慢,问题往往不在配置文件里
一个站刚上线时跑得好好的,日活涨到几千、接口调用量翻了几倍,运维就开始收到 502 和超时告警。这时候多数人的第一反应是打开 nginx.conf 改 worker 数、调 buffer,改完重启,发现指标没动多少。真正的原因通常在更下面一层。
Nginx 的性能瓶颈分三层。最上面是配置层,中间是系统内核层,最下面是硬件和线路层。配置层改起来最快,但能压榨的空间也最小。我一般会先确认瓶颈到底在哪一层,再决定动手方向,不然调了半天只是心理安慰。
下面按这个顺序拆开说,每一层都给出判断方法和实际代价。
配置层:worker 进程数和连接数先算清楚
worker_processes 设成 auto 基本够用,Nginx 会自动匹配 CPU 核心数。真正容易设错的是 worker_connections 和 worker_rlimit_nofile 这两个值。
一个 worker 能处理的连接数上限由 worker_connections 决定,但系统对单进程能打开的文件描述符数量也有限制。两者取小值才是实际上限。比如 4 核机器,worker_connections 设 10240,理论上限是 4×10240=40960,但如果 ulimit -n 只有 1024,那实际能用的连接数远低于这个数。
检查方法很简单:
- cat /proc/sys/fs/file-max 看系统级上限
- ulimit -n 看当前 shell 的限制
- nginx.conf 里的 worker_rlimit_nofile 要设成和 ulimit 一致或更大
keepalive_timeout 别设太长。长连接能省握手开销,但每个空闲连接也占着 worker 的处理槽位。静态资源站设 30 到 65 秒之间比较合适,API 网关可以更短。设成 300 秒看着省事,高峰期连接池很快被占满,新请求只能排队。
gzip 这块有个常见误区:压缩级别开到 9 并不会比 6 快多少,但 CPU 占用明显上升。静态文件提前压好存成 .gz 让 Nginx 直接发,比每次请求现压划算得多。
内核层:CPU 绑核和文件描述符才是大头
配置层调完,如果 QPS 还是上不去,就该看内核参数了。这一步是多数人容易忽略的地方,也是效果最明显的。
CPU 亲和性绑核在多核机器上收益很大。Nginx 的 worker 进程会被操作系统在核心之间调度,上下文切换带来额外开销。开启 worker_cpu_affinity 让每个 worker 固定在一个核上,能减少缓存失效。4 核机器可以写成 0001 0010 0100 1000,八核就继续往后排。
这个设置对静态资源站提升明显,但对 IO 密集型的动态请求效果有限。如果你的瓶颈在数据库查询,绑核带来的提升可能还不到 5%。
网络相关参数里,这几个值得调:
- net.core.somaxconn 从默认 128 提到 65535,应对突发连接
- net.ipv4.tcp_tw_reuse 开启,让 TIME_WAIT 状态的连接能被复用
- net.ipv4.tcp_max_syn_backlog 提到 65535,防止半连接队列溢出
文件描述符上限要同时改三处:/etc/security/limits.conf、systemd 的 LimitNOFILE、以及 Nginx 自己的 worker_rlimit_nofile。只改一处等于没改。
如果机器是 32G 内存、跑 100M 带宽的香港物理服务器,这些内核调优能让你在同等硬件下多扛 30% 到 50% 的并发。但前提是瓶颈真的在内核层,而不是后端应用自己太慢。
硬件和线路层:什么时候该停手换机器
调优有个边界。当 CPU 使用率长期超过 70%、内存开始频繁 swap、或者网络带宽跑满,继续调参数就是在跟物理极限较劲。
先看 CPU。Nginx 处理静态请求时 CPU 占用很低,但处理 SSL 握手和 gzip 压缩时 CPU 消耗会上去。如果开了 HTTPS 且并发高,CPU 很容易成为瓶颈。这种情况换更高主频的 CPU 比加核心数有用,因为 Nginx 单 worker 是单线程模型,主频决定单请求处理速度。
内存方面,Nginx 本身吃内存不多,但缓存和缓冲区会占。proxy_cache 开大了能减少回源,但内存要给够。32G 内存的机器,留 4G 给系统,剩下的可以大胆分给缓存。
带宽是最容易被忽略的一层。100M 带宽理论峰值是 12.5MB/s,如果页面平均大小 2MB,那同时只能服务 6 个用户下载。带宽跑满时,调什么参数都没用,只能升级带宽或者上 CDN。
我一般会建议:静态资源为主的站,优先保证带宽充足,CPU 反而不用太强;动态 API 为主的站,CPU 主频和内存更重要。
如果判断下来确实需要换机器,香港机房里 香港自营物理服务器(100M) 这种配置——金牌 6138 二十核四十线程、32G 内存、100M 带宽——适合并发量中等偏上、同时要兼顾线路质量的业务。月付 3750 元这个价位,比同配置的云主机便宜不少,代价是没有云平台那种弹性伸缩能力。
带宽需求没那么大的话,香港自营物理服务器(20M) 配的是 E5-2696V4 双路、64G 内存,月付 2150 元,跑高并发 API 更划算,就是 20M 带宽得省着用。
先定位再动手,别把调优当玄学
Nginx 调优不是把所有参数往大了设就完事。worker_connections 设成 100 万不会让性能变好,只会让内存被白白吃掉。
我的习惯是先用 top、vmstat、ss 这几个工具看五分钟,确认 CPU、内存、网络、磁盘哪个先到瓶颈,再决定调哪一层。配置层的改动通常只能带来个位数百分比的提升,内核层能到 20% 到 30%,硬件层的提升最直接但要花钱。
静态资源站和 API 网关的调优侧重点完全不同。前者盯着带宽和文件描述符,后者盯着 CPU 主频和 upstream 连接池。搞清楚自己的业务类型,比背参数表有用得多。
如果调完内核参数、CPU 还是长期跑满,那就别再折腾配置了,该换机器换机器。继续在软件层面找空间,投入产出比会越来越低。