
如何判断 Nginx 响应慢到底是 worker 进程不够、缓冲区配置不合适,还是 keepalive 连接没有复用?很多站长会先想到加 CDN(内容分发网络,通过全球节点缓存内容来缩短访问距离)或升级 [VPS](https://cn.hostease.com/vps/)([虚拟专用服务器](https://cn.hostease.com/vps/),在[物理服务器](https://cn.hostease.com/dedicated-server/)上划分出的独立虚拟环境),但如果 Nginx 本身已经在高并发下排队,外层加速只能缓解一部分症状,无法解决核心瓶颈。
这篇指南的重点不是重复一份通用参数清单,而是教你从日志、压测和资源曲线里定位问题。 你会看到 worker、缓冲区与 keepalive 三类配置分别适合解决什么问题,哪些指标需要先确认,修改后又该用什么命令验证。
先做基线:不要在没有证据时调参数
Nginx(高性能 Web 服务器和反向代理软件)调优最怕“看到配置就改”。同一个 worker_connections 参数,在 2 核 2GB 的博客站、4 核 8GB 的外贸站、前端静态资源网关上的意义完全不同。正确顺序应该是先记录基线,再改一组配置,最后用同一组压测命令复测。
建议先收集 3 类证据:访问日志中的状态码分布、错误日志中的关键报错、系统层面的 CPU(中央处理器)与内存曲线。比如 499 增多常见于客户端等待超时,502/504 更可能指向后端或代理链路,worker_connections are not enough 则直接说明 Nginx 连接上限触顶。关于 TTFB(首字节时间)与主机层优化的关系,可以先参考 TTFB 优化指南,再回到本文做 Nginx 侧排查。
grep 'worker_connections are not enough' /var/log/nginx/error.log | tail -20
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head
vmstat 1 10
如果这些命令显示 CPU 长时间低于 40%、内存仍有余量,但请求排队明显,优先看连接数和文件描述符。如果 CPU 已接近 90%,却没有连接上限报错,优先看 gzip、TLS(传输层加密协议)和后端响应。这样做能避免把所有慢请求都归咎于 Nginx 参数。
worker 饱和:先看连接上限,再看进程数量
worker 进程是 Nginx 处理请求的基本执行单元。它采用事件驱动模型,一个 worker 可以同时维护大量连接,但它仍受 CPU 核心、文件描述符和 worker_connections 限制。出现连接排队时,不要只把 worker_processes 改成很大的数字。
worker_processes auto;
worker_rlimit_nofile 65535;
events {
use epoll;
worker_connections 2048;
multi_accept on;
}
worker_processes auto 会按 CPU 核心数启动 worker。对大多数 Linux 服务器来说,这是安全起点。真正经常被忽略的是 worker_rlimit_nofile 与系统 nofile 限制。如果 Nginx 配置里允许 8192 个连接,但系统仍把单进程文件描述符限制在 1024,连接上限会提前触顶。
- 2 核 2GB 小型站点可以从
worker_connections 1024起步,总并发约 2048。 - 4 核 8GB 业务站点可以测试
2048,并同步确认ulimit -n不低于 65535。 - 如果单连接平均占用约 128KB-256KB 内存,把连接数从 4096 提到 16384 前要先算内存余量。
- 出现
EMFILE或too many open files时,先修系统限制,再谈 Nginx 参数。
这里的关键是“连接容量”和“CPU 并行度”分开看。前者由 worker 连接数和文件描述符决定,后者才和 worker 进程数强相关。我们在排查中见过 4 核机器把 worker_processes 设为 32,错误日志没有减少,CPU 上下文切换却明显上升;改回 auto 并提高 nofile 后,连接报错才消失。

缓冲区瓶颈:看后端响应大小和磁盘临时文件
如果错误日志没有连接上限报错,但页面在高峰期 TTFB 波动很大,下一步要看缓冲区。Nginx 作为反向代理时,会先读取后端响应,再把数据发送给客户端。缓冲区过小会让大响应频繁写入临时文件;缓冲区过大又会让每个连接占用更多内存。
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 8 16k;
proxy_busy_buffers_size 32k;
proxy_temp_file_write_size 64k;
一个可操作的判断方法是检查错误日志里是否出现 an upstream response is buffered to a temporary file。偶尔出现并不一定是故障,但如果高峰期大量出现,说明后端响应体超过内存缓冲区,Nginx 正在频繁写磁盘。对 WordPress、图片较多的内容页或接口返回较大的站点,这类问题会直接拖慢响应。
调缓冲区时建议按响应大小分层:普通 HTML 页面可从 128KB 总缓冲开始;如果页面包含大量动态片段,可测试 256KB;下载、视频、超大 JSON(轻量数据交换格式)接口不应单纯靠放大代理缓冲解决,而应该优化输出或走专门的静态资源路径。更多站点性能分析思路,可延伸阅读 WordPress 速度优化指南。
grep 'buffered to a temporary file' /var/log/nginx/error.log | tail -20
sudo iostat -xz 1 5
如果 iostat 里磁盘 await 长时间升高,同时 Nginx 临时文件日志增多,就说明瓶颈不在 worker 数量,而在响应缓存与磁盘 I/O(输入/输出)。这时盲目增加 worker 只会让更多请求同时写盘,问题可能更明显。
keepalive 失效:高并发下最容易被误判的慢
keepalive 的作用是复用连接,减少重复建立 TCP(传输控制协议)连接的握手成本。对浏览器到 Nginx 的连接如此,对 Nginx 到后端服务的连接也一样。如果 keepalive 没配置好,Nginx 看起来并不忙,后端却会因为短连接洪峰而耗尽连接池。
upstream backend {
server 127.0.0.1:9000;
keepalive 32;
keepalive_requests 1000;
keepalive_timeout 60s;
}
server {
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
这里最容易漏的是 proxy_http_version 1.1 和 proxy_set_header Connection ""。只在 upstream 里写 keepalive 32 不够,如果代理请求仍按短连接方式转发,后端连接复用不会真正生效。PHP-FPM、Node.js、Java 应用在高峰时段出现连接数暴涨时,优先检查这一组配置。
客户端侧也要设置合理的空闲时间:
keepalive_timeout 65;
keepalive_requests 100;
对页面资源较多的站点,单个页面加载 60-120 个请求并不少见。keepalive_requests 100 能覆盖大多数页面加载过程,避免每个 CSS、JS 和图片都重新握手。若站点面向跨境访问,单次握手多出的 100ms-300ms 延迟会被放大,keepalive 的收益更明显。若你还在评估服务器网络与应用性能的整体关系,可以结合 服务器配置专题 一起排查。

压测验证:每次只改一组配置
修改配置后,验证比配置本身更重要。建议把测试分成“低并发基线”和“接近真实峰值”两组。低并发用于确认配置没有明显错误,高并发用于观察瓶颈是否改善。不要一次改 worker、gzip、buffer、keepalive 四类参数,否则结果变好或变差都无法归因。
nginx -t && systemctl reload nginx
wrk -t4 -c100 -d30s https://example.com/
wrk -t8 -c500 -d60s https://example.com/
复测时至少记录 4 个指标:QPS(每秒查询数)、平均延迟、P95 延迟、失败请求数。比如 QPS 从 3000 提到 4200,但 P95 从 180ms 拉高到 700ms,说明吞吐上去了,尾延迟却变差,线上体验未必更好。配合 htop、vmstat 和 Nginx 错误日志一起看,才能判断是不是把压力转移到了 CPU、内存或后端服务。
如果你使用云服务器(基于虚拟化技术提供的弹性计算资源),还要确认实例的 CPU 积分、磁盘 IOPS(每秒输入输出次数)和网络带宽(单位时间内可传输的数据量)是否有平台限制。Nginx 参数只能提升软件层效率,不能突破底层资源上限。Hostease 的相关主机方案适合需要稳定资源和运维支持的业务站点,但具体规格仍应以压测结果和业务峰值为依据。
常见误区:这些改法看起来勤快,实际容易反噬
完成基线和压测后,再回头看很多“调优建议”,你会发现它们只有在特定条件下才成立。下面几类改法尤其需要谨慎:
- 把
worker_processes设得远高于 CPU 核心数:容易增加上下文切换,4 核机器设 32 通常没有收益。 - 无限放大
worker_connections:如果系统文件描述符和内存没有同步调整,只会制造新的限制点。 - 把 gzip 等级直接设为 9:相比等级 4,压缩率通常只多 2%-5%,CPU 开销却可能明显增加。
- 只看平均响应时间:平均值会掩盖 P95/P99 尾延迟,线上用户更容易感受到尾部慢请求。
- 忽略后端连接池:Nginx 正常不代表 PHP-FPM、数据库或应用层没有排队。
更稳妥的做法是把 Nginx 排障当成一条链路:入口连接容量、代理缓冲、后端连接复用、系统资源上限逐段确认。这样即使问题不在 Nginx,也能快速排除它,避免在同一组参数上反复试错。
总结:按证据调优,而不是按模板调优
Nginx 高并发排障的核心建议很简单:先看日志和资源曲线,再改参数;先确认 worker 是否触顶,再检查缓冲区是否写盘,最后验证 keepalive 是否真正复用。每次只修改一组配置,用相同压测命令记录 QPS、P95 延迟和失败请求数,才能判断改动是否有效。
如果你需要给线上站点做一次稳妥的优化,可以按本文顺序建立基线,并把测试结果保存成版本记录。对于访问量增长明显、资源已经接近上限的网站,可以考虑把 Nginx 调优与主机规格评估一起做:先优化配置,确认软件层没有明显浪费,再根据峰值流量选择更合适的 云服务器 或其他托管方案。这样既能避免过早升配,也能减少高峰期临时救火。