Nginx调优别乱改参数:先把worker和连接数这两件事做对
不少人碰到的情况是这样:业务刚上线时用一台2核4G的机器跑Nginx,一切正常;访问量涨上来之后CPU单核跑满、响应时间从几十毫秒爬到几百毫秒,第一反应是加机器,加完发现单机还是那个样子。问题往往不在硬件,而在配置里几个默认值从来没动过。
我一般先把Nginx的瓶颈拆成两层看:一层是进程和连接数这类「入口」参数,决定了它能同时接住多少请求;另一层是超时、缓冲、压缩这类「过程」参数,决定了接住之后处理得快不快。多数人直接从第二层开始调,其实是顺序反了。先把入口做对,后面才有意义。
worker_processes 设成 CPU 核数就够了吗
默认配置里 worker_processes 常常是 1,这是最容易被忽略的一处。它决定 Nginx 开几个工作进程,每个进程独立处理请求。设成 1 的时候,8 核机器也只有 1 个核在真正干活,剩下 7 个核在旁边看着。
常规做法是设成 auto,让 Nginx 自己读 CPU 核数。不过有几个例外值得注意:如果这台机器同时还跑着数据库或应用服务,把 Nginx 吃满所有核反而会跟它们抢资源,这时候留出 1 到 2 个核更稳。
另一个细节是 worker_cpu_affinity。开启之后可以把每个 worker 绑定到固定的核上,减少进程在核之间迁移带来的缓存失效。CPU 核数不多的时候收益有限,核数到 16 以上、又是高并发短连接的场景,绑核带来的稳定性提升能感觉到。
改完这两项记得 reload,别直接 restart,前者不丢连接。看是否生效用 ps -ef | grep nginx 数一下 worker 进程数就行。
连接数不够用,问题出在 worker_connections 和系统上限
worker_connections 默认常见是 512 或 1024,意思是每个 worker 进程最多同时处理这么多连接。单机理论并发上限大致是 worker_processes 乘以 worker_connections,比如 8 个 worker、每个 1024,理论上限约 8192。
但这里有个容易算错的地方:作为反向代理时,Nginx 对客户端是一条连接,对后端又是一条连接,一个请求占用两条。所以实际能承载的客户端并发大约只有一半。按我的经验,代理场景下把 worker_connections 设到 10240 甚至 20480 更符合预期,前提是内存跟得上。
光改 Nginx 还不够。Linux 单进程能打开的文件描述符有上限,默认常常是 1024,Nginx 进程数一多就顶到天花板。需要同步调整系统层面的限制,否则 Nginx 报「too many open files」的时候你会以为是配置写错了。
- 确认当前上限:ulimit -n
- Nginx 配置里加 worker_rlimit_nofile,数值跟系统上限对齐
- 高并发短连接场景开启 multi_accept,让一个 worker 一次多接几个新连接
为什么强调这两个参数要一起改?因为只改 Nginx 不改系统,等于把水管的进口开大、出口还堵着;只改系统不改 Nginx,则是白留了余量。两边对齐之后,单台 8 核 16G 的机器扛住万级并发连接在多数业务里是够的。
超时和缓冲:省下的资源比想象中多
入口调好之后,再看过程参数。keepalive_timeout 默认 65 秒,对静态资源站点偏长。长连接本身是好事,能省掉反复握手的开销,但空闲连接一直占着 worker_connections 的名额。如果站点的请求间隔普遍很短,把超时压到 15 到 30 秒,能空出不少连接位。
与之配套的是 keepalive_requests,控制一条长连接上最多处理多少个请求,默认 100 在高压下偏低,调到 1000 可以减少连接重建次数。这两项一起改效果才明显。
缓冲相关的 client_body_buffer_size、proxy_buffers 这些,多数场景用默认值就行,除非你明确知道自己在传大文件或者上游响应体特别大。乱调缓冲区反而会吃内存。
真正值得花时间的是 gzip。开启 gzip 之后,文本类响应体积通常能压到原来的三分之一左右,带宽省下来,客户端加载也快。但要注意别对图片、视频这类已经压缩过的内容再压一遍,纯属浪费 CPU,用 gzip_types 只挑文本类型即可。
如果站点是面向海外用户、后端又放在国内,光靠 Nginx 调参解决不了跨境延迟,这时候更实际的做法是把静态资源和反向代理层放到离用户近的机房里。比如面向东南亚业务的,可以考虑马来西亚大带宽服务器,吉隆坡机房,AMD EPYC 7742 双路、256G 内存、100M 带宽,月付 $1408.50,适合代理层和静态资源分发这类吃带宽的场景。
调完之后怎么验证
参数改完不能凭感觉说快了。压测工具跑一遍,重点看两个指标:一是错误率,二是响应时间的分布,别只看平均值。平均值好看、P99 很差,说明还有长尾请求卡在某一层。
我一般会先压到明显出错的量,找到拐点,再退回来留 30% 左右余量。这个余量是给业务波峰和突发流量用的,不留的话平时看着没问题,一到大促就露馅。
最后给个可以直接执行的结论:小站先用 auto 加 worker_connections 10240 这套组合,多数情况够用;单机 8 核 16G 配置能覆盖大部分中小业务,再往上就该考虑拆代理层而不是继续堆参数。如果你的业务分布在全球多个区域,与其把单机参数调到极限,不如按区域分散部署,代理层就近接入,这样延迟和稳定性都比死磕单机划算。