nginx 不支持运行时修改 upstream weight,需依赖外部系统采集指标并热更新:openresty+lua 实现内存级毫秒调控;nginx-upstream-dynamic-servers 模块提供 rest api 控制;nginx-upsync-module 联动 consul/etcd 实现服务自愈;所有方案均需以可观测性为基础。

Nginx 本身不支持运行时修改 upstream 中的 weight 值——该参数在启动时固化,静态生效。所谓“根据负载情况动态调整权重”,本质是靠外部系统持续采集 CPU、内存、响应时间、错误率等真实指标,计算出新权重,并通过热更新机制同步进 Nginx 工作进程,全程不 reload、不断连。
用 OpenResty + Lua 实现毫秒级内存调控
适合已有 OpenResty 环境、对延迟敏感、不能接受配置重载的场景。它把权重逻辑完全搬到内存中执行:
- 启用
lua_shared_dict缓存各节点的实时负载指标(如process_cpu_seconds_total、http_request_duration_seconds_bucket) - 用
ngx.timer.at每 2–5 秒调用后端/health或业务接口,获取真实响应时间和状态 - 在
balancer_by_lua_block中读取共享字典里的最新权重,调用balancer.set_current_peer()手动选节点 - 权重公式建议:
weight = math.max(1, math.min(10, base * (ref_rt / actual_rt)^1.5)),既防过载又保灵敏度 - 加入熔断:单节点连续 3 次超时,立即将其内存权重设为 0,并标记状态
用 nginx-upstream-dynamic-servers 模块 + HTTP API 控制
轻量、无中间件依赖,适合中小集群,靠标准 REST 接口驱动变更:
- 编译 Nginx 时加入模块:
--add-module=/path/to/nginx-upstream-dynamic-servers - upstream 块中只写
dynamic_server on;,不写任何server指令 - 外部脚本(如 Python + Prometheus)每分钟拉取 P95 延迟、CPU 使用率,按规则重算权重
- 推送新权重:
curl -X POST http://nginx-host/upstream/servers -d '{"server":"192.168.1.12:8080","weight":7}' - 可直接对接 Grafana 告警:PromQL 触发阈值后自动调低异常节点权重
用 nginx-upsync-module + Consul/etcd 实现服务自愈式联动
云原生环境首选,后端启停、指标劣化自动触发权重更新,毫秒级生效:
- Consul KV 中存 JSON 数组,每个节点含
server、weight、max_fails字段 - Sidecar(如 Telegraf 或自研 agent)监控后端指标,按策略写入 Consul(例:CPU > 85% → weight × 0.6)
- Nginx 配置
upsync每 300ms 拉取一次,变更立即生效,无需 reload - 支持 fallback 权重:新节点上线默认
weight=2,避免冷启动流量冲击 - Consul 可预设降级规则,如某节点连续失败 5 次,agent 自动将其
weight设为 0 并写回 KV
必须配套的可观测性基础
光调权重掩盖不了底层问题,所有方案都要以可观测性为前提:
- access_log 固定记录:
$upstream_addr $upstream_response_time $upstream_header_time $request_time - 若
$upstream_response_time高但$upstream_header_time低,说明瓶颈在应用层(如慢 SQL),此时调权效果有限 - 聚合分析建议窗口:5 分钟统计各节点 P95 响应时间、5xx 错误率、超时次数
- 权重调整后,至少观察 5 分钟 access_log,确认流量分布与预期一致,且错误率未跳升











