5月28日 09:24

CDN 的负载均衡策略有哪些?如何实现 CDN 的高可用?

面试核心结论

CDN 负载均衡的核心策略分为两层:全局调度层(GSLB/DNS)决定用户访问哪个边缘节点,本地均衡层(L4/L7 LB)决定节点内部请求分发到哪台服务器。主要策略包括地理位置路由、就近性路由、轮询、加权轮询、最少连接和一致性哈希。实现高可用的关键在于:健康检查 + 故障自动转移 + 熔断降级 + 多活冗余,缺一不可。

追问方向:GSLB 的 DNS 调度流程是怎样的?一致性哈希在 CDN 缓存中为什么重要?Anycast 和 DNS 调度有什么区别?

CDN 负载均衡的两层架构

理解 CDN 负载均衡,首先要分清两层调度:

  • 全局调度(GSLB):当用户发起请求时,DNS 解析通过 CNAME 指向 CDN 的 GSLB,GSLB 根据用户 IP、节点负载、网络质量等选择最优边缘节点,返回该节点的 IP。这一层决定"用户去哪个机房"。
  • 本地负载均衡(SLB):请求到达边缘节点后,节点内部的负载均衡器(Nginx、HAProxy 等)将请求分发到后端的缓存服务器集群。这一层决定"请求去哪台机器"。

面试时很多候选人只讲本地负载均衡,忽略了 GSLB 这一层,这是不够的。CDN 的核心优势——就近接入,正是由 GSLB 实现的。

六种核心负载均衡策略

地理位置路由(Geo-based Routing)

根据用户 IP 所属地域,将请求调度到最近的边缘节点。这是 CDN 最基础也最常用的全局调度策略。

实现机制:GSLB 维护一张 IP 地址段到地理位置的映射表(GeoIP 数据库),用户 DNS 请求到达后,查询映射表确定用户所在区域,返回该区域对应节点的 IP。

局限性:地理位置近不等于网络延迟低。比如跨运营商访问时,物理距离近但网络绕行严重。因此通常和就近性路由配合使用。

就近性路由(Proximity-based Routing)

不依赖地理数据,而是通过实际网络测量选择最优节点。

测量方式

  • 主动探测:GSLB 定期从各节点向探测点发送 ICMP/TCP 探测,收集 RTT 数据
  • 被动测量:分析实际用户请求的响应时间,统计各节点的真实服务质量
  • 混合模式:主动探测提供基线数据,被动测量做实时修正

实际生产中混合模式最常见。纯主动探测有探测盲区,纯被动测量冷启动阶段没数据。

一致性哈希(Consistent Hashing)

在 CDN 场景中,一致性哈希的核心价值是提高缓存命中率

为什么重要:如果用轮询策略,同一 URL 的请求可能落在不同缓存服务器上,导致重复回源。用 URL 做一致性哈希,相同 URL 始终路由到同一台服务器,缓存只需存一份。

关键参数:虚拟节点数。虚拟节点越多,数据分布越均匀,但管理开销也越大。通常设置 100-200 个虚拟节点。

节点变更影响:当节点增减时,一致性哈希只影响相邻虚拟节点上的数据,不会全盘重新分配。相比取模哈希(节点变化时全部重分布),这是巨大优势。

nginx
# Nginx 一致性哈希配置 upstream cdn_cache { hash $request_uri consistent; server 10.0.0.1:8080; server 10.0.0.2:8080; server 10.0.0.3:8080; }

加权轮询(Weighted Round Robin)

为不同性能的服务器分配不同权重,高性能服务器承载更多请求。

nginx
upstream cdn_nodes { server 10.0.0.1:8080 weight=5; # 32核 64G 高配 server 10.0.0.2:8080 weight=3; # 16核 32G 中配 server 10.0.0.3:8080 weight=1; # 8核 16G 低配 }

权重不是一成不变的。成熟的 CDN 系统会根据服务器实时负载(CPU、内存、连接数)动态调整权重,这叫动态权重调整

最少连接(Least Connections)

将新请求分发给当前活跃连接数最少的服务器。相比轮询,它适合请求处理时间差异大的场景——轮询只看"分了几个",最少连接看"还剩多少余力"。

nginx
upstream cdn_nodes { least_conn; server 10.0.0.1:8080; server 10.0.0.2:8080; server 10.0.0.3:8080; }

IP 哈希(IP Hash)

用客户端 IP 做哈希,保证同一用户的请求始终落到同一台服务器。主要用于会话保持场景,但在 CDN 中不如 URL 哈希常用,因为 CDN 主要是无状态的内容分发。

健康检查:高可用的基础

没有可靠的健康检查,负载均衡就是瞎指挥。健康检查分两种:

主动健康检查

LB 定期向后端发送探测请求,判断服务是否正常:

nginx
# Nginx Plus 主动健康检查 upstream cdn_nodes { zone health 64k; server 10.0.0.1:8080; server 10.0.0.2:8080; health_check interval=5s fails=3 passes=2 uri=/health; }

关键参数:

  • interval:探测间隔,正常节点 5-10s,异常节点缩短到 1-2s
  • fails:连续失败几次标记为不健康
  • passes:连续成功几次恢复为健康

被动健康检查

基于实际业务请求的响应判断,不额外发探测:

nginx
upstream cdn_nodes { server 10.0.0.1:8080 max_fails=3 fail_timeout=30s; server 10.0.0.2:8080 max_fails=3 fail_timeout=30s; }

max_fails=3 fail_timeout=30s 表示 30 秒内失败 3 次,该节点被标记不可用 30 秒。

生产实践:两种方式配合使用。主动检查发现硬故障(进程挂了、端口不通),被动检查发现软故障(响应变慢、错误率升高)。

高可用架构的关键机制

故障自动转移

当节点被标记不健康后,负载均衡器自动将流量切到健康节点。关键问题是切换速度

  • DNS 级别的 GSLB 切换依赖 TTL,即使设置很短的 TTL(如 30s),仍有本地 DNS 缓存问题,实际切换可能需要数分钟
  • Anycast 方式切换更快,因为 BGP 路由变化可在秒级生效
  • 本地 SLB 切换最快,通常在 1-2 个探测周期内完成

熔断与降级

当后端持续异常时,快速失败比慢慢等更好:

  • 熔断:错误率超过阈值(如 50%),直接断开,不再向该节点发请求,等一段时间后半开探测
  • 降级:返回缓存内容(stale-while-revalidate)、返回简化版本、或者直接拒绝(比超时等待体验更好)
nginx
# Nginx 熔断配置思路 proxy_connect_timeout 2s; proxy_read_timeout 5s; proxy_next_upstream error timeout http_502 http_503; proxy_next_upstream_timeout 10s; proxy_next_upstream_tries 2;

proxy_next_upstream 实现了请求级别的自动重试和故障转移。

多活与冗余

单点永远不可靠。CDN 的高可用需要多层次的冗余:

  • 节点级冗余:每个区域至少部署 2 个边缘节点,互为备份
  • 服务器级冗余:节点内部至少 2 台缓存服务器
  • 网络级冗余:多运营商接入(BGP 多线),避免单运营商故障
  • DNS 级冗余:多组权威 DNS,避免 DNS 服务本身成为单点

Anycast 与 DNS 调度的对比

这是面试中经常被追问的进阶问题:

维度DNS 调度(GSLB)Anycast
切换速度分钟级(受 TTL 和缓存影响)秒级(BGP 路由收敛)
精度基于 IP 库,有偏差基于网络拓扑,更精准
运维复杂度相对简单需要 ASN 和 BGP 配置
适用场景大多数 CDN对延迟敏感、需快速故障转移
缓存问题本地 DNS 缓存导致调度不准无此问题

大型 CDN(Cloudflare、Akamai)通常两种方式结合:Anycast 做全局入口,DNS 调度做精细化区域分配。

监控指标与告警

负载均衡不是配置完就完事了,需要持续监控:

核心指标

  • P50/P95/P99 响应时间:关注长尾延迟,P99 比 P50 更能反映用户体验下限
  • 错误率:5xx 比例超过 0.1% 就需要告警
  • 缓存命中率:低于 80% 说明负载均衡策略或缓存策略有问题
  • 节点可用性:目标 99.99%(年停机约 52 分钟)

告警分级

  • P1:节点完全不可用 → 立即处理,自动故障转移
  • P2:错误率 > 1% 或 P99 > 5s → 5 分钟内响应
  • P3:缓存命中率下降 > 10% → 工单跟进

面试回答要点

回答这个问题的正确姿势:

  1. 先说两层架构:全局调度(GSLB/Anycast)+ 本地均衡(L4/L7),展示你对 CDN 整体架构的理解
  2. 策略选讲 3-4 个:地理位置路由、一致性哈希、最少连接、加权轮询,每个说清楚适用场景和取舍
  3. 高可用讲机制链:健康检查 → 故障转移 → 熔断降级 → 多活冗余,形成完整链路
  4. 举实际例子:比如"我们线上遇到过 DNS 缓存导致 GSLB 切换慢的问题,后来加了 Anycast 做补充",比纯理论更有说服力
  5. 提 Anycast:很多人会忽略这个,提了就是加分项
标签:CDN