bigywater.tech
微服务 · 59

多机房:就近路由与跨机房容灾

多机房部署时怎么就近调用、又在机房出问题时跨机房容灾?Envoy 的优先级和 overprovisioning factor 什么时候开始溢出?主动检查和被动检测切换要多久?nginx 的 backup 有什么不同?这篇用 Envoy 1.39.3 和 nginx 1.31.6 逐项量出来。

100.0% → 69.8%
factor 140 时,dc1 剩 75% 与剩 50% 健康时留在 dc1 的请求比例(剩 50% 时 30.2% 溢出到 dc2)
59.0 s
主动检查 interval 0.5 s 但 no_traffic_interval 保持默认时,Envoy 发现一个停掉的后端的用时
23.4 ms → 4.0 ms
跨机房轮询与就近(dc1 优先)的 p50 延迟(dc2 后端模拟 40 ms)

优先级与 factor

实测 · 本机执行输出
  overprovisioning factor | dc1 停掉的后端数 | dc1 健康比例 | 落在 dc1 的请求 | 落在 dc2 的请求 | 错误数
  ------------------------+------------+----------+------------+------------+----
  140                     | 0          | 100%     | 100.0%     | 0.0%       | 0  
  140                     | 1          | 75%      | 100.0%     | 0.0%       | 0  
  140                     | 2          | 50%      | 69.8%      | 30.2%      | 0  
  140                     | 3          | 25%      | 33.6%      | 66.4%      | 0  
  140                     | 4          | 0%       | 0.0%       | 100.0%     | 0  
  100                     | 0          | 100%     | 100.0%     | 0.0%       | 0  
  100                     | 1          | 75%      | 74.6%      | 25.4%      | 0  
  100                     | 2          | 50%      | 50.9%      | 49.1%      | 0  
  100                     | 3          | 25%      | 24.1%      | 75.9%      | 0  
  100                     | 4          | 0%       | 0.0%       | 100.0%     | 0  
  dc1 的健康比例乘以 factor/100(封顶 100%)就是留在 dc1 的比例,剩下的溢出到 dc2:factor 140 时 dc1 还有 75% 健康仍然全部留在 dc1,降到 50% 才开始溢出;factor 100 时只要少了一个后端就开始溢出

留在优先机房的比例约为健康比例乘以 factor/100,封顶 100%,其余溢出到下一优先级。

整体切换

实测 · 本机执行输出
  配置           | 请求总数 | 失败的请求数 | 失败的请求相对停机时刻的范围(s) | 停机后第一个由 dc2 成功响应的请求(s)
  -------------+------+--------+-------------------+-----------------------
  (a)主动健康检查    | 800  | 172    | 0.02~1.85         | 1.86                  
  (b)只有被动异常点检测 | 800  | 95     | 0.02~1.11         | 1.12                  
  (c)两者都没有     | 800  | 535    | 0.02~5.48         | 没有切过去                 
  主动健康检查把 dc1 摘掉要等连续两次检查失败;被动检测靠真实请求失败来发现,摘除后同样切到 dc2;两者都没有时,Envoy 一直认为 dc1 健康,所有请求失败
  另一个观察:健康检查 interval 设 0.5 s,但 no_traffic_interval 保持默认值,先发了 20 个请求再停掉一个 dc1 的后端,Envoy 把它标成不健康用了 59.0 s(最多等 90 s;配置里写 no_traffic_interval: 0.5s 之后,前面的实验里是 1 s 左右)

主动检查要连续失败几次才摘除,被动检测靠真实失败;什么都不配则不会切换;no_traffic_interval 默认值会让检查非常慢。

就近的收益

实测 · 本机执行输出
  配置         | 延迟 p50(ms) | 延迟 p99(ms) | 落在 dc1 / dc2 的请求
  -----------+------------+------------+-----------------
  (a)dc1 优先  | 4.0        | 4.9        | 100.0% / 0.0%   
  (b)不区分机房轮询 | 23.4       | 52.3       | 50.0% / 50.0%   

优先级 0 的机房健康时,所有请求都留在本机房,延迟明显更低。

nginx backup 与 Envoy

实测 · 本机执行输出
  场景                        | 落在 dc1 | 落在 dc2 | 错误数 | 各后端的请求数                            
  --------------------------+--------+--------+-----+------------------------------------
  nginx(a)dc1 停掉两个          | 100.0% | 0.0%   | 0   | p0-2:750 p0-3:750                  
  Envoy(factor 140)dc1 停掉两个 | 69.8%  | 30.2%  | 0   | (见第一节)                             
  nginx(b)dc1 全停            | 0.0%   | 100.0% | 0   | p1-0:375 p1-1:375 p1-2:375 p1-3:375
  nginx 的 backup 只在所有普通 server 都不可用时才接流量:dc1 还剩一半时,剩下的两个后端承担全部流量;Envoy 的优先级按健康比例逐步溢出
ERRORS {}

nginx 的 backup 只在普通 server 全不可用时才接流量,Envoy 按健康比例逐步溢出。

分步演示

多机房就近路由与容灾
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Python 3.14.8 / Go / nginx / Envoy / etcd / Consul / Nacos / OpenTelemetry / Prometheus(按各篇注明用到哪些及版本);所有服务都是本机自己起的进程,端口 9150 以上,只监听 127.0.0.1,不连任何外部服务,不碰本机已有的实例;故障用 kill -9 进程、让连接断开或在代码里注入延迟与错误来制造;计时用 time.perf_counter,数字每次运行会有小幅抖动。Envoy 是 1.39.3,nginx 是 1.31.6,八个后端是本进程里的 Python 服务;“机房”只是后端分成两组,跨机房的代价用 dc2 后端额外的响应延迟模拟,不是真实的网络或距离;第二节每种配置只测了 1 次开环负载(100 个/秒,8 s);第一节每一格 1500 个顺序请求,比例有几个百分点的随机波动
    • 没有验证:真实的跨机房网络(带宽、丢包、费用);容量问题:溢出的流量超过 dc2 的容量会不会把 dc2 也压垮;Envoy 的 locality 加权负载均衡(locality_weighted_lb_config)与 zone 感知路由;注册中心层面的多数据中心(Consul WAN、Nacos 多集群同步);跨机房的数据一致性与读写路由;DNS 层面的 GSLB
    京ICP备2026067502号-1京公网安备11010502063487号