Nginx 不支持运行时修改 upstream weight,生产中动态权重需依赖外部系统+热更新:OpenResty+Lua 实现内存级毫秒切换;nginx-upstream-dynamic-servers 模块提供 HTTP API 控制;nginx-upsync-module 对接 Consul/etcd 实现服务发现联动;所有方案均需结合指标诊断与日志验证。

Nginx 本身不支持运行时修改 upstream 中 server 的 weight 参数——这个值在启动时固化,无法直接“动态调整”。真正在生产中落地的动态权重,本质是“外部系统感知指标 + 内存或配置热更新”,而不是让 Nginx 自己算着改。
用 OpenResty + Lua 实现毫秒级内存权重切换
适合对延迟敏感、不能接受 reload 中断的场景。它绕过配置文件,在 worker 进程内存中实时控制转发逻辑:
- 启用
lua_shared_dict缓存各节点的响应时间、错误率等指标,避免多 worker 重复采集 - 用
ngx.timer.at每 2–5 秒调用健康检查接口或真实业务路径,记录$upstream_response_time - 在
balancer_by_lua_block中读取共享字典里的最新权重,调用balancer.set_current_peer()手动选定后端 - 加入熔断:某节点连续 3 次超时,临时将其权重设为 0,并标记状态写入共享字典
- 权重计算可采用公式如
weight = base × (ref_rt / actual_rt)²,让响应快的节点获得明显更高优先级
通过 nginx-upstream-dynamic-servers 模块 + HTTP API 控制
轻量、无需额外依赖,适合中小规模集群,靠标准 REST 接口驱动权重变更:
- 编译 Nginx 时加入该模块:
--add-module=/path/to/nginx-upstream-dynamic-servers - upstream 块中只写
dynamic_server on;,不写任何server指令 - 用 curl 发送 POST 请求实时增删改节点及权重:
curl -X POST http://localhost:8080/upstream/servers -d '{"server":"192.168.1.10:8080","weight":6}' - 可对接 Prometheus:用 PromQL 查出各实例 P95 响应时间,脚本每分钟拉取、重算权重、推送到 API
对接 Consul/etcd 实现服务发现联动
适合容器化或云环境,后端启停、指标变化自动触发权重更新,天然支持权重字段:
- 部署
nginx-upsync-module,配置upsync从 Consul KV 拉取 JSON 格式 upstream 列表(含server、weight、max_fails) - 由 sidecar 或独立 agent 监控 CPU、HTTP 延迟等指标,按规则写入 Consul(例如新节点上线默认
weight=2,防冷启动冲击) - Nginx 每 300ms 主动轮询 Consul KV 变更,毫秒级生效,全程无需 reload
- Consul 中可预设 fallback 权重和降级策略,比如某节点连续失败 5 次,agent 自动将其
weight设为 0 并写回 KV
别跳过诊断环节:权重不是万能解药
光调权重掩盖不了底层问题,必须结合日志交叉验证:
- 如果某节点
$upstream_response_time高,但$upstream_header_time很低,说明瓶颈在应用层(如慢 SQL),此时调权意义不大 - access_log 中固定记录
$upstream_addr $upstream_response_time $request_time,确保每条请求能准确归属到具体后端 - 用脚本按 5 分钟窗口聚合 P95 响应时间、错误率、超时次数,再设定升降权规则(例如连续两周期 P95 > 600ms 且超均值 1.8 倍 → 权重降为 60%)


















