应重点检查upstream_response_time日志值及fail_timeout机制,确认max_fails是否仅统计连接失败而非响应慢,需结合slow_start或调低proxy_read_timeout触发淘汰,再用nginx-upstream-check-module或vts模块实时监控节点状态,并排查后端自身性能瓶颈。

直接看 upstream 的健康状态和各节点响应时间,重点查慢节点的 upstream_response_time 和是否触发了 fail_timeout 机制。
检查 Nginx 日志里的 upstream 响应详情
Nginx 默认不记录每个 upstream 节点的耗时,需在 log_format 中显式加入变量:
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time uct="$upstream_connect_time" '
'uht="$upstream_header_time" urt="$upstream_response_time"';
其中 upstream_response_time 是关键——它会按请求经过的节点顺序输出多个值(如 0.002, 0.154, 2.891),最后一个值对应最终成功返回的节点耗时。若某节点频繁出现在末尾且数值明显偏高(比如 >1s),就极可能是拖慢源头。
确认 upstream 配置是否启用了被动健康检查
轮询本身不自动剔除慢节点,必须配合 max_fails 和 fail_timeout 才能实现“慢即失效”:
upstream backend {
server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.12:8080 max_fails=3 fail_timeout=30s;
}
注意:
- max_fails 统计的是「连接失败或超时」次数,不是响应慢;
- 单纯响应慢(如 5s 返回 200)不会触发踢出,除非加 slow_start 或用商业版/第三方模块(如 nginx-plus 的 slow_start 或开源的 upstream_check_module);
- 若想让慢响应也参与淘汰,可临时把 proxy_read_timeout 设低(如 1s),让慢节点主动超时,从而被 max_fails 捕获。
用 stub_status 或第三方模块实时观察节点状态
启用 stub_status 只能看到总请求数、活跃连接等,看不到各节点权重和失败数。更实用的方式是:
- 编译安装 nginx_upstream_check_module,开启心跳检测,暴露 JSON 接口查看每个节点的
status(up/down)、rise、fall、check_count; - 或使用 nginx-module-vts(Virtual Host Traffic Status),通过网页或 API 查看每个 upstream server 的请求量、响应时间 P95/P99、失败数;
- 简单验证:用
curl http://localhost/status(vts)或curl http://localhost/check(check_module),对比各节点的response_time和failed字段。
排除后端自身问题的常见动作
即使 Nginx 已将慢节点隔离,也要确认是不是后端服务真有问题:
- 登录该节点,用
curl -w "@format.txt" -o /dev/null -s http://127.0.0.1:8080/health测真实响应时间(format.txt包含 time_namelookup/time_connect/time_starttransfer/time_total); - 检查该节点 CPU、内存、磁盘 I/O 是否打满,特别是慢查询或 GC 频繁;
- 比对该节点与其他节点的配置差异:JVM 参数、连接池大小、DB 连接串、缓存策略;
- 临时将流量全切到该节点(weight=10),复现并抓取其 access log + error log,看是否有特定路径或参数触发慢响应。


















