2. 流量切换基础:DNS切换、负载均衡器切换、反向代理切换的原理与差异
在蓝绿部署与灰度发布中,流量切换是决定 MTTR 的核心环节。不同的切换层(DNS、负载均衡器、反向代理)在生效速度、粒度、安全性和可观测性上存在本质差异。本章从原理出发,逐一拆解三种切换方式的机制与适用场景。
2.1 DNS 切换:全局生效,但受缓存制约
DNS 切换通过修改域名解析记录(A 记录 / CNAME)将流量指向新环境。其核心优势在于无需修改应用架构,但生效时间受 TTL(Time To Live)和客户端 DNS 缓存影响。
| 参数 | 说明 | 典型值 |
|---|---|---|
| TTL | DNS 记录在递归服务器上的缓存时长 | 60s ~ 300s(生产建议 ≤ 60s) |
| 传播延迟 | 全球 DNS 节点同步时间 | 数秒 ~ 数分钟(受权威服务器分布影响) |
| 客户端缓存 | 浏览器、操作系统、本地 resolver 的缓存 | 不可控,部分客户端忽略 TTL |
| 切换粒度 | 域名级别,无法按用户/请求细分 | 粗粒度 |
避坑提示:DNS 切换不适合需要秒级回滚的场景。若 TTL 设置为 300s,回滚后仍有 5 分钟窗口期流量进入异常环境。建议在蓝绿发布前将 TTL 临时调低至 30s-60s,待切换稳定后再恢复。
2.2 负载均衡器切换:四层流量调度
负载均衡器(如 AWS NLB、GCP TCP/UDP LB、F5、LVS)工作在 OSI 第四层(传输层),基于 IP + 端口转发流量。切换时只需修改后端服务器池的成员关系,无需等待 DNS 缓存,生效时间通常在秒级。
- 切换粒度:IP 级别,无法识别 HTTP 请求头或 Cookie。
- 会话保持:依赖源 IP Hash 或 sticky session,切换时可能导致会话中断。
- 健康检查:支持 TCP 端口探测,可自动摘除异常后端。
- 典型场景:数据库读写分离、TCP 长连接服务、游戏服务器。
关键指标:负载均衡器切换的 MTTR 通常由健康检查间隔(如 5s × 2 次失败)决定。若需加速,可手动强制摘除后端,将切换时间压缩至 1-2 秒。
2.3 反向代理切换:七层精细化控制
反向代理(Nginx / HAProxy / Envoy)工作在第七层(应用层),可解析 HTTP 请求头、Cookie、URI 等。切换时通过修改 upstream 配置或动态路由规则实现灰度、金丝雀、A/B 测试等复杂策略。
| 特性 | Nginx | HAProxy |
|---|---|---|
| 配置重载方式 | nginx -s reload(平滑重载,不丢连接) |
haproxy -sf(优雅重启,保留旧进程) |
| 动态 upstream | 需配合 ngx_http_upstream_dynamic_module 或 Lua |
原生支持 set server 命令(Runtime API) |
| 流量比例控制 | 通过 split_clients 或 weight 实现 |
通过 balance uri 或 stick-table 实现 |
| 灰度策略 | Cookie/Header 匹配 + 条件 proxy_pass | ACL + use_backend 条件路由 |
| 可观测性 | Stub Status / ngx_http_status_module | Stats Page / Prometheus Exporter |
# Nginx 蓝绿切换示例:通过 weight 控制流量比例
upstream backend {
server 10.0.1.10:8080 weight=90; # 蓝环境(旧)
server 10.0.2.10:8080 weight=10; # 绿环境(新)
}
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
}
}
# 切换命令:修改 weight 后 reload
# nginx -s reload
# HAProxy 蓝绿切换示例:通过 Runtime API 动态调整
backend blue-green
balance roundrobin
server blue 10.0.1.10:8080 weight 100 check
server green 10.0.2.10:8080 weight 0 check
# 动态切换命令(通过 socat 或 haproxy-runtime-api)
# echo "set server blue-green/green weight 100" | socat stdio /var/run/haproxy.sock
# echo "set server blue-green/blue weight 0" | socat stdio /var/run/haproxy.sock
2.4 三种切换方式的核心差异对比
| 维度 | DNS 切换 | 负载均衡器切换(四层) | 反向代理切换(七层) |
|---|---|---|---|
| OSI 层 | 应用层(DNS 协议) | 传输层(TCP/UDP) | 应用层(HTTP/HTTPS) |
| 生效速度 | 秒 ~ 分钟(受缓存影响) | 秒级(健康检查周期) | 毫秒 ~ 秒级(reload / API) |
| 切换粒度 | 域名级别 | IP + 端口 | 请求头、Cookie、URI、用户 |
| 灰度能力 | 无(需配合其他组件) | 有限(仅权重) | 强(条件路由 + 比例控制) |
| 回滚速度 | 慢(需等待 TTL) | 快(秒级修改后端池) | 极快(毫秒级 reload / API) |
| 会话保持 | 不适用 | 源 IP Hash / Sticky | Cookie / Header / JWT |
| 可观测性 | 日志 + DNS 监控 | 连接数、吞吐量 | 请求级指标、链路追踪 |
| 典型 MTTR | 5 ~ 15 分钟 | 10 ~ 60 秒 | 1 ~ 10 秒 |
选型建议:在蓝绿发布中,推荐将反向代理作为主要切换层,实现秒级切换与精细化灰度;负载均衡器作为基础设施层兜底;DNS 仅用于全局流量迁移或跨地域容灾,不适合作为主切换手段。