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,待切换稳定后再恢复。
DNS 切换流程与缓存影响 用户客户端 本地 DNS 缓存 递归 DNS 服务器 权威 DNS 服务器 缓存影响: • 本地缓存命中 → 直接返回旧 IP,切换不生效 • 递归缓存未过期 → 不查询权威,切换延迟 蓝环境(旧) 绿环境(新) 切换方式: • 修改 A 记录指向绿环境 IP • 等待 TTL 过期 + 缓存刷新

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
反向代理七层切换:Nginx / HAProxy 流量调度 用户 HTTP 请求 反向代理 Nginx / HAProxy 路由规则(七层): Header: X-Canary=yes → 绿环境 | Cookie: version=new → 绿环境 | 默认权重 → 蓝环境 90% / 绿环境 10% 蓝环境(旧) weight=90 绿环境(新) weight=10 可观测性 Metrics / Logs / Traces

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 仅用于全局流量迁移或跨地域容灾,不适合作为主切换手段。