nginx 不支持运行时直接修改 upstream weight,但可通过热重载配置实现毫秒级平滑切换:修改配置文件中 weight 值,执行 nginx -t 校验后 nginx -s reload,旧 worker 继续处理请求,新 worker 按新权重分发。

Nginx 本身不支持运行时直接修改 upstream 中 weight 的值,但可以通过“配置热重载 + 外部脚本控制”的方式,实现服务流量的平滑热切换——整个过程毫秒级完成,连接不断、请求不丢。
核心逻辑是:用 weight 控制分流比例,用 reload 加载新配置,靠健康检查兜底。
动态权重的本质是配置变更而非运行时API调用
Nginx 的 weight 是静态参数,写在配置文件里。所谓“动态”,指的是你能在不重启进程的前提下,修改配置文件内容并触发 nginx -s reload,让新权重立即生效。旧 worker 进程继续处理已有请求,新 worker 按新权重分发新请求——这就是平滑的关键。
- 修改
upstream块中各 server 的weight值(例如从weight=100改为weight=0) - 确保配置语法正确:
nginx -t - 执行热重载:
nginx -s reload - 不要使用
systemctl restart nginx或kill -TERM,那会中断连接
权重设置要配合健康检查和灰度节奏
光改 weight 不够,得让切换有缓冲、可观察、能回退:
- 用
max_fails=3 fail_timeout=30s自动剔除异常节点,避免把流量打到挂掉的服务上 - 新版本上线初期,可先设
weight=1或加backup标记,只在主节点全不可用时才启用 - 切流前用
curl -I http://192.168.1.11:8080/health验证新服务是否 ready - 切完后盯 access 日志 3–5 分钟,确认绿版有真实请求、状态码正常、无大量 5xx
实现时段自动切换的实用做法
如果需要按业务高峰自动调权(比如白天高配机器权重拉高、夜间降权),推荐三步走:
- 把
upstream单独抽成/etc/nginx/conf.d/upstream.conf,主配置里include它 - 写 shell 脚本,根据
date +%H判断当前小时,生成对应权重的 upstream 内容并覆盖该文件 - 用
cron每小时执行一次脚本 +nginx -s reload,无需人工干预
进阶:权重 + 请求特征双控更灵活
单纯按比例分流不够精细?可以叠加 map 指令做条件路由:
- 用
map $http_x_test_user $use_green { "true" 1; default 0; }提取请求头 - 在
location里判断$use_green,决定proxy_pass走统一 upstream 还是直连 green 版本 - 这样既能全局灰度放量(weight 控制),又能给内测用户开白名单(header 控制),互不干扰
不复杂但容易忽略的是:所有权重调整都必须基于同一 upstream 块。别把蓝绿拆成两个独立 upstream,否则只能全量切换,失去渐进能力。











