阶梯式平滑下线是按流量比例、用户特征或时间阶段逐步迁移请求,需结合Nginx的map、split_clients等模块实现分流与重定向,并通过日志和监控验证效果。

理解阶梯式平滑下线的核心逻辑
阶梯式平滑下线不是一次性关停,而是按流量比例、用户特征或时间阶段,逐步将请求从旧域名迁移到新域名(或返回特定响应),同时保障业务无感。Nginx 的 rewrite 模块本身不直接支持“灰度比例”或“用户分组”,需结合 map、split_clients 或 geo 等模块协同实现分流逻辑,再用 rewrite 或 return 执行跳转/拦截。
基于请求特征做分层路由(推荐方案)
利用 map 指令预定义匹配规则,将不同来源的请求映射到不同处理动作,再通过 rewrite 触发重定向或内部重写:
- 按 Host 匹配多个旧域名,统一映射到迁移状态变量
- 用 $http_cookie 或 $arg_version 识别灰度用户,决定是否放行或跳转
- 配合 if ($migrate_status = "redirect") { rewrite ^(.*)$ https://new.example.com$1 permanent; }
示例片段:
map $host $migrate_stage {
default 0; # 正常服务
old1.example.com 1;
old2.example.com 1;
legacy.example.com 2;
}
<p>map $migrate_stage $redirect_target {
0 "";
1 "<a href="https://www.php.cn/link/c68872e6cff6f7f445ce75299f546c3d">https://www.php.cn/link/c68872e6cff6f7f445ce75299f546c3d</a>";
2 "<a href="https://www.php.cn/link/245d66a9f52f4e5080f8175f53335539">https://www.php.cn/link/245d66a9f52f4e5080f8175f53335539</a>";
}</p><p>server {
listen 80;
server_name old1.example.com old2.example.com legacy.example.com;</p><pre class='brush:php;toolbar:false;'>if ($redirect_target) {
return 302 $redirect_target;
}}
按流量比例渐进式切流(需 split_clients)
split_clients 可基于 $remote_addr 做一致性哈希,实现稳定可控的流量划分,适合“先切 5% → 30% → 100%”的阶梯节奏:
- 定义一个百分比变量,如 $rollout_rate,值为 "on" 或 "off"
- 在 server 块中用 if ($rollout_rate = "on") { rewrite ... } 控制跳转
- 修改配置后 reload 即可调整比例,无需重启
注意:rewrite 在 if 中虽可用,但应避免嵌套复杂逻辑;优先用 return + 变量组合替代多层 rewrite。
配合日志与监控验证过渡效果
平滑下线成败取决于可观测性。建议:
- 在 log_format 中加入 $migrate_stage、$redirect_target 等变量,便于统计各阶段流量占比
- 用 access_log 按状态码分离记录:302 跳转量、404/410 下线页访问、200 正常响应
- 配合 Prometheus + nginx-vts-exporter 实时查看各域名 QPS、跳转率变化趋势
发现某阶段跳转异常率突增,可立即回退 map 映射或调整 split_clients 比例。


















