QPS 上不去的 Nginx,问题可能不在配置文件里
Requests per second 压不上去,很多人反复改 nginx.conf 却收效甚微。本文从一次真实排查出发,说明后端响应、连接复用、日志写入、带宽限制四个常被忽略的因素,并给出分层定位的思路。
帮朋友看一个站点,他说 Nginx 配置已经按网上最优方案改了三遍,ab 压测的 Requests per second 还是卡在几百。我上去一看,Nginx 本身没问题,瓶颈全在后端和周边。
QPS 低不等于 Nginx 慢,先分清是谁在拖后腿
最直接的判断方法:用 Nginx 直接返回静态文件压一次,再走 proxy_pass 到后端压一次。如果静态文件能跑到几千 QPS,走后端只有几百,那问题在后端,改 Nginx 配置纯属浪费时间。
后端慢的常见原因包括数据库没加索引、PHP-FPM 进程数不够、应用里有同步阻塞的远程调用。这些都要在应用层解决,Nginx 再优化也救不了。
连接复用没做好,握手开销吃掉一半性能
Nginx 到后端的 upstream 如果没开 keepalive,每个请求都要重新建 TCP 连接,三次握手加四次挥手,在高 QPS 下开销惊人。配置 upstream 的 keepalive 连接池,再用 keepalive_requests 控制复用次数,后端吞吐能明显提升。
客户端侧同理。如果站点是 API 服务,建议开启 HTTP/2,多路复用能减少连接数,尤其对移动端弱网环境提升明显。
access_log 写太勤,磁盘成了隐形瓶颈
默认配置下每个请求都写一条 access_log,QPS 高了之后磁盘 IO 会被日志吃满。压测阶段可以先关掉 access_log,或者用 buffer 参数批量写入,减少 syscall 次数。
如果业务必须保留日志,至少把日志盘和数据盘分开。物理机上这点很好处理,加一块盘专门写日志即可。像韩国首尔裸机云 III这类独立服务器,E5-2680 配 32G 内存,20M 带宽,硬盘和带宽都是独占的,不会因为邻居的日志风暴影响自己。
带宽跑满的表现,和 CPU 跑满完全不同
CPU 跑满时 QPS 会平稳下降,而带宽跑满时延迟会突然飙升,请求排队。用 iftop 或 nload 看一眼出口流量就知道。如果带宽是瓶颈,压缩传输内容是个办法,开启 gzip 能省不少流量,但注意别对已经压缩过的图片视频再压。
说到底,QPS 是整条链路的结果。Nginx、后端、数据库、磁盘、带宽,任何一环掉链子都会体现在数字上。与其反复调参数,不如先分层压测,找到真正的那一环。