现象先分类,再动手查

NG 性能调优与 FAQ

把连接数、代理超时、缓存命中与响应耗时常出现的故障点整理成问答对照,配置片段均适合在 CentOS 上的 Nginx 环境里直接复核。

6 类常见告警对照
4 步 reload 验证法
12+ 组配置片段示例
问题对照区

按错误日志找入口,不慌调大连接数

以下条目先描述常见现象,再给配置方向和复核命令。每项内容都避免“直接拉到最大”的粗放做法,以便你在变更后能说清修改原因。

Q1

连接数上不去,调整 worker_processes 和 worker_connections 就够了吗?

首先要看进程是否真的需要更多连接。通常把 worker_processes 设为 auto,再把 worker_rlimit_nofile 打开,并通过连接状态确认 TIME_WAIT 与 ESTABLISHED 的比例。若只是等待中的请求很多,需要看 upstream 处理速度与后端应用线程,不能只依赖前端排队。

worker_processes auto;
worker_rlimit_nofile 65535;

events {
    worker_connections 4096;
    multi_accept on;
    use epoll;
}

修改后用 nginx -s reload 加载,并检查错误日志是否仍出现 worker_connections are not enough。若仍然出现,再考虑 worker_connections 与单连接内存占用之间的平衡。

nginx 官方文档建议 worker_connections 不要直接设置到约等于最大文件描述数,要结合每个连接的 buffer 开销与 ulimit 一起验证。
Q2

反向代理反复出现 upstream timeout,超时时间应该设多长?

日志中出现 upstream timed out 时,先确认是针对单次慢请求,还是一段时间内普遍超时。若属于应用正常处理需超过默认 60 秒的场景,可把 read 超时放宽;若大量请求都在连接阶段失败,则应观察后端健康状态与连接队列。

location /api/ {
    proxy_connect_timeout 5s;
    proxy_read_timeout  30s;
    proxy_send_timeout  30s;
    proxy_next_upstream error timeout http_504;
}

设置完可用 curl -I http://127.0.0.1/ 测试连通与首包时间。真正的慢接口建议在前端看耗时分布,而不是用同一组超时覆盖全部请求。

Q3

静态资源已经配置了缓存,为什么响应里还是 no-cache?

常用 proxy_cache 前,需要确认上游返回的 Cache-Control 是否允许缓存。Nginx 不会把带 no-cache、Set-Cookie 或私有标记的响应写入共享缓存。可以先查看静态资源响应头,确认是否有较长 max-age,再检查 proxy_cache_path 的空间与 key 是否匹配。

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=imgcache:64m max_size=2g inactive=60m;

location /static/ {
    proxy_cache imgcache;
    proxy_cache_valid 200 60m;
    proxy_set_header Host $host;
}

验证缓存命中时,可关注响应头中的 HIT / MISS 状态,并检查 /var/cache/nginx 下是否产生实际缓存文件。

很多“缓存失效”问题不是 Nginx 配置写错,而是后端响应头没有满足缓存条件,优先看 proxy_cache_valid 之外的 Cache-Control 字段。
Q4

access.log 里的 499 和 504 分别代表什么?

499 是客户端在 Nginx 收到完整响应前主动断开连接,常见原因为客户端超时或请求被取消;504 是 Nginx 在设定的 proxy_read_timeout 内没有等到上游响应。两者处理路径不同:499 优先查客户端等待时长与负载均衡策略;504 优先查上游应用耗时与健康检查。

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                '$status $body_bytes_sent "$http_referer" '
                '"$http_user_agent" "$upstream_response_time"';

access_log /var/log/nginx/access.log main;

若同一上游频繁 504,可在 upstream 配置中加入 max_fails 与 fail_timeout,让临时不健康节点尽快被切出,而不是在单台机器上反复等待。

Q5

已经开启 Gzip,为什么返回的 JS、CSS 体积还是很大?

开启 gzip 还要注意 gzip_types 是否包含目标 MIME 类型,以及客户端请求是否携带 Accept-Encoding: gzip。代理场景下,Nginx 需要与被代理端协商压缩来源,否则上游可能已经输出未压缩内容。

gzip on;
gzip_comp_level 5;
gzip_min_length 1024;
gzip_types text/plain text/css text/js
           application/javascript application/json
           application/xml image/svg+xml;

用一条命令就能确认当前响应内容编码:

curl -I -H 'Accept-Encoding: gzip' http://127.0.0.1/static/app.js

返回头中出现 Content-Encoding: gzip,说明压缩生效。图片、音视频等已压缩格式通常不在 Gzip 收益范围内。

Q6

修改配置后必须 restart 吗?如何确认 reload 真正生效?

绝大多数配置变更不需要 restart,使用 nginx -t 校验后执行 nginx -s reload 即可完成平滑加载。reload 会让 worker 进程逐个更新,master 进程 PID 保持不变,连接不会全部中断。

nginx -t && nginx -s reload

# 用 -T 查看当前真正生效的配置
ps -ef | grep nginx
nginx -T 2>/dev/null | grep -E 'worker_|proxy_'

若不放心,可以在 reload 后立刻观察 error.log 是否出现正常加载记录,再用 curl 访问一个受影响的 URL,确认状态码与耗时没有异常。

restart 会造成短暂断连,只有修改了 listen 端口或编译模块等少数场景才需要谨慎重启。
STEP 01 加载前校验语法 nginx -t
STEP 02 平滑加载配置 nginx -s reload
STEP 03 基础请求检查 curl -I http://127.0.0.1/
STEP 04 读取异常记录 tail -n 30 /var/log/nginx/error.log
常用速查区

命令写进交接文档,排障不靠记忆

以下三段分别用于请求耗时、连接状态和配置现状检查,在 CentOS 终端中可直接运行。

request-time.sh
curl -o /dev/null -s -w 'DNS:%{time_namelookup}
连接:%{time_connect}
首包:%{time_starttransfer}
总计:%{time_total}\n' http://127.0.0.1/
state-check.sh
ss -s
ss -tan state time-wait | wc -l
ss -tan state established | wc -l
nginx-status.sh
nginx -T 2>/dev/null | grep -E \
'worker_processes|worker_connections|proxy_cache|gzip_|server_name' || true
实用资源

领取《Nginx 性能排查核对表》

把本页的连接数检查、超时对照、缓存验证与 reload 步骤整理为一张核对表,适合放进交接文档或维护窗口执行记录。

ng官方网站 Nginx 性能排查核对表封面
更多 FAQ 速读

还没有查到答案?再试这几组口径

这部分保留短问答,便于你很快决定下一步。

当并发连接数提高后,需要关注文件描述符限制。可将 worker_rlimit_nofile 65535; 写在 main 上下文,再通过 nginx -T 核对当前值。没有调整 ulimit 时只改 worker_connections,可能无法真正生效。

建议先看 error.log 里的 warn/error,再用 ss -s 观察连接状态。curl 分阶段耗时能区分 DNS、TCP 连接、等待首包与传输时间。不要在只看总耗时的情况下直接调大 worker 数。

高 QPS 场景下每次请求写日志都会消耗磁盘 IO 与进程调度开销。压测时可临时关闭 access_log,或使用 buffer 与日志轮转策略,观察吞吐是否明显变化。生产环境不建议长期全量关闭访问审计。

JPEG、PNG、WebP 等二进制资源自身已完成压缩,Gzip 通常不会继续显著压缩。需要关注 SVG、CSS、JavaScript、JSON 等文本资源,并确认请求头中携带 Accept-Encoding: gzip

反向代理需要即时透传流媒体或被代理端输出不适合缓冲时,可关闭代理缓冲。其余场景建议保留缓冲,避免上游响应速度与客户端接收速度不一致时长时间占用 worker 连接。

先运行 nginx -t 检查语法,再执行 nginx -s reload 平滑加载。可通过 nginx -T 查看当前生效配置,并观察 error.log 是否出现正常加载记录。

仍有未覆盖的问题?前往公开问答区继续查看