加权轮询权重未生效的根本原因在于配置规范性、健康检查干扰、后端响应行为及日志验证缺失;必须确保weight紧随server地址、禁用ip_hash等冲突策略、配max_fails/fail_timeout防误剔除,并通过≥100次去缓存请求和upstream_addr日志字段验证真实分发。

加权轮询配置看似简单,但实际运行中常出现“权重没生效”“流量倾斜严重”“请求分配不按预期”等问题。根本原因往往不在权重数字本身,而在配置细节、健康检查干扰、或后端响应行为影响了Nginx的调度逻辑。下面从配置、验证、干扰项、日志四个维度帮你系统定位问题。
确认配置写法是否规范
加权轮询依赖upstream块内server指令的weight参数,但很多问题源于格式或位置错误:
-
weight必须紧跟server地址,不能换行或加空格分隔:正确写法是
server 192.168.1.10:8080 weight=3;,而不是server 192.168.1.10:8080<br>weight=3;
- 权重值只能是正整数(1–65535),不支持小数或负数;设为0等同于临时下线该节点
- 所有server必须在同一upstream块中定义,跨块或嵌套引用会导致权重被忽略
- 若同时启用了
ip_hash或least_conn等其他算法,weight将完全失效——Nginx只认当前启用的调度策略
用可复现方式验证真实分配比例
仅靠肉眼curl几次看不出权重效果,需批量+去缓存+隔离客户端来验证:
- 用
curl -H "Cache-Control: no-cache" http://nginx-ip/避免浏览器或代理缓存干扰 - 在单台测试机执行循环请求(如
for i in {1..100}; do curl -s http://nginx-ip | grep server; done),统计各后端返回标识频次 - 注意:Nginx的加权轮询不是严格按比例实时切分,而是基于“加权轮询队列”的周期性调度,总请求数较少时偏差明显;建议测试≥100次再看比例是否接近理论值(如weight=3:2:1 → 理论占比50% : 33% : 17%)
- 若使用
keepalive连接复用,同一TCP连接内的多个HTTP请求会落到同一后端,干扰统计——测试时可加proxy_http_version 1.1;+proxy_set_header Connection '';强制关闭复用
排查健康检查对权重的隐性干扰
Nginx默认开启被动健康检查(max_fails/fail_timeout),一旦某节点因超时或5xx被标记为unavailable,它就彻底退出调度队列,权重再高也收不到请求:
- 检查
error.log中是否有类似upstream server temporarily disabled的记录 - 用
nginx -T 2>/dev/null | grep -A 10 "upstream backend"确认各server是否带max_fails参数;若未显式配置,Nginx默认max_fails=1 fail_timeout=10s,极易误判 - 临时禁用健康检查验证:把
server ... max_fails=0;,观察权重是否恢复;确认后再调整合理的失败阈值 - 主动健康检查(需商业版或OpenResty)不在默认范围内,普通Nginx不支持HTTP级探针,别误以为配置了
health_check就生效
查日志确认实际转发路径
当流量分配异常,最直接证据在access日志里。需确保日志格式包含后端地址信息:
- 在
http块中定义日志格式:log_format upstream_log '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$upstream_addr" "$upstream_response_time"'; - 在
server块中应用:access_log /var/log/nginx/upstream_access.log upstream_log; - 请求后查看日志,
$upstream_addr字段会明确写出最终转发到哪台IP:PORT,比猜更可靠 - 若该字段为空或显示
none,说明请求根本没进upstream(可能被location匹配拦截、rewrite重定向、或proxy_pass指向错误)


















