Nginx 调不好,多半是这几个参数在拖后腿
流量涨到某个点之后,很多人第一反应是加机器。可打开监控一看,CPU 才跑到 30%,内存还剩一大半,Nginx 的响应时间却从 20ms 爬到了 200ms 以上。这时候加机器基本是白花钱——瓶颈根本不在硬件上,而在几个从没动过的配置项里。下面说的是我在实际调优里最常改的几处,以及改完之后为什么有效。
worker 进程数和连接数,先算清楚再动手
默认配置里 worker_processes 是 1,也就是不管你有几个核,Nginx 只用一个核干活。4 核机器上这就等于浪费了 75% 的算力。改成 auto 让 Nginx 自己读 CPU 核数,是最省事的做法。
worker_connections 更常被误解。它指的是单个 worker 进程能同时处理的连接数,不是整台机器的上限。所以真实并发上限大致是 worker_processes × worker_connections。4 核配 1024,理论上能到 4096 个连接,但反向代理场景下每个客户端请求会占用两个连接(一个对客户端、一个对后端),实际能扛的并发要打个对折。
- 纯静态站:worker_connections 设 1024 到 2048 足够
- 反向代理站:同样数值下实际并发减半,需要时提到 4096
但别一味往上堆。每个连接都会占内存,10240 的连接数在 8G 内存的机器上就可能触发 swap,反而让响应变慢。我一般会先看机器有多少内存,再决定这个值。
keepalive_timeout 不是越长越好
这个参数默认 65 秒,意思是客户端连接保持 65 秒不关。对普通网页访问来说,65 秒偏长——用户看完一个页面可能就走了,连接却还占着 worker 的资源。
对内的 upstream keepalive 又是另一回事。如果 Nginx 到后端应用服务器之间没有开 keepalive,每个请求都要重新建一次 TCP 连接,高并发下光是三次握手就吃掉不少时间。这部分要在 upstream 块里单独配 keepalive 32 之类的数值,并加上 proxy_http_version 1.1 和 proxy_set_header Connection "",少一个都不生效。
取舍在这里:对外的 keepalive_timeout 我通常压到 15 到 30 秒,对内的 upstream keepalive 则要开着。前者省连接资源,后者省握手时间,方向刚好相反,配错一边就白调。
gzip 和缓存头,改对了省的是带宽钱
gzip 默认是关的。打开之后,HTML、CSS、JS 这类文本资源通常能压到原体积的 30% 左右,一个 300KB 的页面变成 90KB,用户首屏时间能明显缩短。
但不是所有文件都该压。图片、视频本身就是压缩格式,再过一遍 gzip 只会白烧 CPU,压缩比几乎为零。所以 gzip_types 里只列文本类型就够了,别图省事写个 *。
gzip_comp_level 也不用开到 9。级别从 6 提到 9,压缩率大概只多 1% 到 2%,CPU 占用却翻倍。我一般停在 5 或 6,性价比最高。
静态资源的 expires 头同样值得配。给图片、字体这类不常变的文件设 30 天缓存,用户第二次访问直接走本地缓存,服务器这边连请求都收不到。省下的带宽和连接数,比调任何参数都直接。
如果站点本身跑在大带宽机器上,带宽不是瓶颈,那缓存头的优先级可以往后放;但如果是 40M 这类带宽,压缩和缓存带来的收益会很直观,比如 日本原生IP物理服务器 ③ 这种 40M 带宽的配置,把 gzip 和 expires 配好,能顶不少事。
调完之后怎么验证有没有效果
改完配置别急着 reload 完就走。用 ab 或 wrk 压一轮,对比改之前和改之后的每秒请求数和平均响应时间,两个数字放在一起看才有意义。
还要盯一下 error.log 和 access.log 的增长速度。如果日志文件几分钟就涨几百 MB,说明有大量 4xx 或 5xx 在刷,那问题就不在性能参数上,得回去查应用层。
按我的经验,一台 4 核 8G 的机器,把 worker_processes 设成 auto、worker_connections 设 2048、对外 keepalive_timeout 压到 30 秒、gzip 开在 level 6,静态站扛住几千并发不成问题。真要再往上走,那就是带宽和磁盘 IO 的事了,跟配置无关。
最后一句实在话:别抄网上的配置模板直接覆盖。每台机器的核数、内存、带宽都不一样,参数得跟着硬件走。先算清楚自己的并发上限在哪,再决定改哪一项。