Nginx 调优别只盯着 worker_connections,这几个参数才是瓶颈
服务器上跑着 Nginx,平时访问量不大,一切正常。等到某个活动或者爬虫集中来一波,502 和超时就开始冒出来,CPU 看着也没跑满,内存还剩一半。这种时候多数人第一反应是加配置,其实先该看的是 Nginx 的 worker 配置和内核参数有没有和机器规格对上。
下面按 4 核 8G 和 16 核 32G 两档常见机型来讲,能直接改的参数、改了之后省下什么、哪些改动其实没必要,我分开说。
worker_processes 和 worker_connections 到底怎么配
worker_processes 设成 auto,Nginx 会自动跟随 CPU 核心数,这一条基本没有争议。真正容易配错的是 worker_connections。
很多人看到教程写 10240 就跟着填,但 worker_connections 是单个 worker 能同时处理的连接数,理论上限还要乘 worker 数量。4 核机器填 10240,理论并发是 40960,可实际能不能撑住,取决于文件描述符够不够。
worker_rlimit_nofile 必须跟着一起放开。系统默认单进程 1024,Nginx 开到 10240 也会被内核拦住,日志里会出现「too many open files」。
- worker_processes auto;
- worker_connections 10240;
- worker_rlimit_nofile 65535;
按我的经验,4 核 8G 的机器跑静态资源加反向代理,单机稳定支撑几千到一万出头的并发连接是合理的,再往上就该考虑加机器而不是继续压参数。
keepalive 与内核参数:省下的钱和换回的性能
keepalive_timeout 设太长,空闲连接会一直占着 worker 的连接槽。设太短,客户端频繁重建 TCP,握手开销又上来了。多数场景 30 到 65 秒之间比较平衡,静态站点可以偏短,API 网关可以偏长。
真正影响大的是内核层面的几个值。net.core.somaxconn 决定 accept 队列长度,默认 128,高并发下会直接丢连接。net.ipv4.tcp_max_syn_backlog 同理,管的是半连接队列。
还有 time_wait 状态。短连接多的业务,net.ipv4.tcp_tw_reuse 打开能明显减少端口耗尽的情况,但不要开 tcp_tw_recycle,这个参数在新内核里已经移除,老内核上开它反而会误伤 NAT 后面的客户端。
这些改动的收益是实打实的:不加一台机器,把 somaxconn 从 128 提到 65535,突发流量下的连接失败率通常能降下来一大截。代价是要重启服务或者重新加载内核参数,属于计划内操作。
gzip 和缓存:别把 CPU 浪费在压缩上
gzip 能省带宽,但压缩本身吃 CPU。静态资源已经被压缩过的(图片、视频、woff2 字体)再开 gzip 没有意义,纯属白烧 CPU。
gzip_comp_level 开到 6 以上,压缩率提升有限,CPU 开销却陡增。多数情况下 4 到 6 之间够用。gzip_min_length 设成 1k 以下,小响应体压不压缩差别不大,反而多一次 CPU 调用。
open_file_cache 这一项容易被忽略。它把静态文件的文件描述符缓存起来,命中率高的时候能省掉大量 open 系统调用。max 设 10000,inactive 设 60s,是静态站点比较稳的一组值。
如果站点本身是动态请求为主,open_file_cache 收益有限,别在这上面花时间。
机器选不对,参数调到头也没用
Nginx 调优的上限是硬件。CPU 主频低、内存带宽窄的机器,参数怎么改都到不了理想并发。反过来,一台核数够、内存带宽宽的机器,Nginx 默认配置往往就能跑得不错。
做反向代理和静态分发的场景,我更看重单核性能和内存带宽,而不是堆核心数。跑高并发长连接的业务,比如 WebSocket 网关,那核心数和文件描述符上限就更关键。
如果站点面向华南或者东南亚用户,香港机房的物理服务器在延迟上有天然优势,香港大带宽服务器 XXII 是 E5-2630L*2 加 32G 内存、G 口带宽的配置,跑 Nginx 做前端分发比较合适,延迟低,带宽也够。
面向欧美用户的站点,可以看美国硅谷大带宽服务器 XI,E3-1230 配 16G 内存和 G 口,单核性能好,做 Nginx 反代和静态分发够用,价格上比堆核心的机型更划算。
调优和选型是两件事,先把参数和内核对齐,再看机器够不够。4 核 8G 的机器配好参数,跑中小流量的站点没有问题;真要上到十万级并发,参数救不了单机,该分布式就分布式。别把预算全砸在参数折腾上。