nginx原生不支持运行时修改upstream weight,需通过openresty+lua、nginx-upstream-dynamic-servers模块或nginx-upsync-module+consul/etcd实现动态权重调控,全程不reload、不断连。

Nginx 原生不支持运行时修改 upstream 中的 weight 参数——该值在配置加载时固化,必须通过外部机制才能实现真正意义上的“动态”权重调控。核心思路是:绕过静态 weight,用实时指标驱动选节点逻辑,或借助扩展模块热更新 upstream 状态,全程不 reload、不断连。
用 OpenResty + Lua 实现毫秒级闭环调权
适合对延迟敏感、已有 OpenResty 基础的场景。它不改配置,而是在每次请求时动态计算并选择后端。
- 用
ngx.timer.at每 2–5 秒探测各后端的/health和业务接口响应时间(如/api/status) - 把指标(P95 延迟、错误率、CPU)写入
lua_shared_dict,避免多 worker 重复采集 - 在
balancer_by_lua_block中读共享字典,按公式算权重:例如weight = math.max(1, math.floor(10 * (200 / actual_rt)^1.5)),结果限制在 1–10 - 用加权随机算法选 peer:
balancer.set_current_peer(ip, port),直接生效 - 内置熔断:单节点连续 3 次超时,临时设权为 0,并标记状态
用 nginx-upstream-dynamic-servers 模块 + HTTP API 控制
轻量、无中间件依赖,适合中小规模集群,运维可脚本化操作。
- 编译 Nginx 时加入模块:
--add-module=/path/to/nginx-upstream-dynamic-servers - upstream 块中只写
dynamic_server on;,不写任何server指令 - 通过标准 REST 接口增删改节点及权重:
curl -X POST http://nginx-host/upstream/servers -d '{"server":"192.168.1.11:8080","weight":8}' - 可对接 Prometheus:用 PromQL 查询各实例
http_request_duration_seconds_bucket的 P95,每分钟重算权重并推送 - 变更立即生效,无需 reload,也不依赖 Consul 或 etcd
用 nginx-upsync-module + Consul/etcd 实现服务自愈式联动
云原生首选,天然适配容器扩缩容与服务发现,毫秒级同步。
- Consul KV 中维护 JSON 数组,每个节点含
server、weight、max_fails字段 - Nginx 配置启用
upsync,默认每 300ms 拉取一次,变更在内存中完成 - 权重更新只需写 Consul:
curl -X PUT http://consul:8500/v1/kv/upstreams/backend -d '[{"server":"10.0.2.5:8080","weight":10}]' - 支持 fallback 权重(如新节点上线默认
weight=2),防冷启动冲击 - 自动处理节点上下线,天然支持健康检查与权重衰减
关键配套:可观测性不能少
再好的调权逻辑,没有准确指标就是盲调。务必在 access_log 中固定记录:
-
$upstream_addr—— 实际转发到的后端地址 -
$upstream_response_time—— 后端真实处理耗时(单位秒,精度毫秒) -
$request_time—— 客户端总等待时间 -
$status和$upstream_http_x_trace_id(如有)用于链路追踪
日志聚合建议按 5 分钟窗口统计 P95、错误率、超时率,作为权重调整的校验依据,避免误调。











