用户输入的一个站点服务,如果只是服务器带宽不足或源站本身响应慢,问题往往不在CDN调度,而在源站架构或缓存命中策略上。如果它是某个城市访问慢、某个运营商普遍卡,这大概率是调度选择有问题,而如果我们把所有城市的访问都导同一个节点,又可能是调度策略太保守。
排查的路径我是这样走的:先取故障发生前后各30分钟、按省份和运营商拆分的访问日志,看访问量的地理分布和时间走势,确认明显增长的区域。然后再看这期间调度系统有没有产生告警,比如节点负载过高、健康检查fail、权重自动收敛这类记录。因为大多数调度系统都有自动降级的保护机制,节点压力大了会主动把流量分走,但这个过程有时候会产生震荡,把流量从一个热点节点导到另一个。
那次我把告警记录和流量曲线对齐,发现苏州电信这个区域的调度在故障开始的前几分钟确实自动调低过华东主节点的权重,把部分流量分到了华南。但华南节点本身并没有针对这个区域的回源优化,浏览器从华南节点拿到内容需要跨地域回源,首包时间直接翻倍,用户体感就是“更慢了”。
也就是说,调度系统本身没有故障,故障在于“决策维度太单一”,它只知道华东节点负载高了要分流,却不知道这段流量是从长三角地区的电信用户来的,分流之后的跨区回源成本会高到让体验变差。这其实暴露了动态调度一个普遍问题:要综合评估的指标太多,而生产系统里我们往往因为怕误判,只敢用最保守的负载维度。
后面我调整了规则,把“用户出口地域+运营商”作为分流判定的第一维度,先保证同类网络特征的请求尽量分到同区域或低延迟路径,再叠加负载做二次判断。把流量分出去之前,调度系统先算一个“候选节点回源成本”的预估值,宁可让它多排一会儿队,也不要轻易扔给一个跨了两个省的节点。这才把那个区域的体感稳下来。
这个案例让我深刻体会到一件事:调度的本质不是选一个节点,而是保证全链路质量,从用户到边缘节点、再回到源站这一段,每一环都需要进入调度决策的视野。
2. 智能指挥的三个核心枢纽:DNS调度、GSLB与HTTP调度各自在解决哪一环
现在我们把“调度系统”这顶大帽子摘掉,看它内部到底拆成几个部分。绝大多数生产级CDN调度系统,核心枢纽有三个:DNS调度、全局负载均衡(GSLB)、边缘HTTP调度。它们分工不同,适合解决的问题也完全不同。
2.1 DNS调度解决的是“用户先找到谁”
DNS调度是用户触达CDN的第一道门。用户输入域名后,本地DNS(LocalDNS)会发起解析请求,CDN的权威DNS通过CNAME被拉进解析链,然后根据请求来源IP返回一个最优的边缘节点IP。
这个环节的决策速度极快,但决策维度相对粗——它能看到的只是LocalDNS的出口IP,而这个IP的地理信息、运营商真不一定能代表真实用户。我们实际接入中发现,同一个LocalDNS出口下可能有电信、联通、移动三种用户混着,如果你按IP地市库一拍脑袋返回某个节点,难免有一部分用户会绕路,这就涉及到后面要讲的动态调度模型。
DNS调度的关键性能指标是TTL(Time to Live)。TTL设小了,LocalDNS频繁回源到权威DNS,查询压力呈指数增长;TTL设大了,节点变动了用户还在访问旧IP,故障倒换的生效时间就会拉长。我在生产里的经验是:
- 常态:TTL跑60秒到300秒之间
- 大促前的节点预扩容:TTL降到30秒,方便快速腾挪
- 故障收敛期:TTL不能太小,防止大量LocalDNS同时来问造成DNS压力,常用配置是60秒
除了TTL,DNS调度还容易踩一个坑:没有考虑LocalDNS出口的归属。有些运营商的DNS出口集中在一个地区,比如你在西北某省访问,但LocalDNS解析出口在省城,你要是按省城去做就近判断,边缘节点覆盖并不会好到哪去。现在有经验的调度系统会把“LocalDNS出口地域矩阵”做成一张表,每一条DNS请求进来,先查用户出口IP和LocalDNS的匹配关系,再做地理定位。
2.2 GSLB在DNS之上叠加负载与质量判断
如果说DNS调度解决的是“用户找到谁”,那么GSLB解决的就是“在多个候选节点里,选一个最合适的”。
GSLB拿到的信息更多,它可以实时收集每个节点的负载情况(CPU、带宽、连接数)、健康状态、回源链路质量。在此基础上叠加用户来源、运营商、内容类型等因素,输出一个综合评分,再根据评分分配权重。常见的GSLB策略和适用场景,我做了个表对比:
| 策略 | 核心逻辑 | 适用场景 | 坑点 |
|---|---|---|---|
| 轮询 | 所有节点轮流 | 各节点能力完全相同 | 生产环境几乎不单独用 |
| 加权轮询 | 按容量权重分配 | 异构节点混合部署 | 权重需要动态调整,固定权重无法应对尖峰 |
| 最少连接 | 连接数最小的优先 | 长连接、视频直播 | 需要考虑节点处理速率差异 |
| 哈希 | 按用户标识映射固定节点 | 需要会话保持的业务 | 节点故障时需要摘除和重新映射 |
| 延迟探测 | 按实时RTT/丢包率选优 | 跨运营商优化 | 探测覆盖面不足时反而是负优化 |
实际生产里基本是用混合策略:先按地域和运营商做粗筛,再用延迟探测和负载评分做细选。像上面那个苏州电信的案例,就是在粗筛环节出了问题,把华东的用户分去了华南。
2.3 边缘HTTP调度补足最后一公里
用户找到了节点、也建立了连接,但CDN节点内部还要做第二次决策:这台边缘机器要不要响应?要不要把这个请求重定向到同节点的另一台机器?要不要改走备用回源链路?
这就是边缘HTTP调度干的活。它一般基于一致性哈希把用户请求映射到边缘集群内的不同实例,同时根据实例的负载情况做局部重定向。常见实现包括302跳转、内部重定向、或者DNS层面的内网调度。
边缘调度的时效要求比GSLB更高,因为它直接面对秒级的流量尖峰。如果边缘集群里某台实例的CPU先被打满,哈希环就需要快速把该实例对应的Key迁移到其他机器,这个迁移过程必须在请求级别平滑完成。我在压测时发现,一致性哈希配合虚拟节点数量设置在100到200之间时,热点实例的摘除时间可以降到百毫秒级;虚拟节点太少会导致流量倾斜,太多则增加内存消耗,这个参数需要实际压测调优。
这三个枢纽的配合关系,简单来说就是:**DNS调度负责把人领进门,GSLB负责分到正确的小区,边缘调度负责走到正确的单元房。**任何一环判断失误,用户的请求质量都会直接受损。
3. 所谓“智能”的含金量:从“就近接入”到“综合博弈”的决策模型
很多刚开始了解CDN调度的朋友会下意识认为,CDN做的就是“就近接入”——用户在哪,就把内容放到离他最近的机房。这个概念没错,但只对了一半。“就近”如果只看地理距离,不看链路质量、缓存命中率和回源成本,结果往往就是上面苏州电信那样:地理上最近的节点,网络上并不是最优的。
3.1 为什么“地理就近”不等于“网络最优”
跨境和跨运营商场景最能说明问题。国内三大运营商之间的互联带宽有限,某个地区电信用户的流量要访问部署在联通机房的节点,可能要绕到异地骨干网节点交换,RTT比访问一个物理距离更远的电信机房还高。也就是说,一个节点物理距离用户300公里,但跨了运营商链路,反而不如一个物理距离800公里但同运营商直连的节点快。
所以生产级别的CDN调度系统,普遍会建立一张“网络质量矩阵”。这张矩阵记录的是:从每个运营商、每个地域的探测点出发,到每个边缘节点的时延、丢包率、抖动等指标,定时探测并更新。调度决策的第一步就是查这张矩阵,把“地理位置近,但链路质量差”的节点从候选列表里过滤掉。
3.2 多目标打分决策模型
在质量矩阵基础之上,真正的调度决策通常是一个多目标打分模型,我会把它简化为这样一个公式:
综合得分 = w1 × 网络质量分 + w2 × 缓存命中分 + w3 × 回源成本分 + w4 × 稳定性分
每一项都有明确的量化方式:
- 网络质量分:来自探测数据,换算成首包预计时间或RTT评分的倒数;
- 缓存命中分:根据内容热度预测该节点是否已经缓存了目标资源;热点资源在节点已有缓存,得分高,冷门资源则重点看回源距离;
- 回源成本分:把源站到边缘节点的链路带宽费用、跨地域回源流量费用折算成分数。这个指标在没有成本压力的小团队里容易被忽略,但流量规模上来后它就是真金白银;
- 稳定性分:节点最近的错误率、慢请求率、健康状态的历史统计。
四个权重w1到w4没有一个通用值。我的经验是,Web页面类场景w1要显著高,因为用户对首屏时间极其敏感;视频点播类场景w2要高,因为命中率直接决定卡顿率;而政企客户的大文件下载,对稳定性分w4会更敏感。权重的取值,最好用自己的真实业务日志去拟合,在没有历史数据之前建议从w1=0.5、w2=0.3、w3=0.1、w4=0.1这个组合起步,再看效果迭代。
3.3 数据闭环驱动决策进化
智能调度和静态规则调度的最大区别,在于它有一个完整的数据闭环:
- 调度系统下发决策
- 边缘节点执行并把访问日志、质量数据上报
- 中心系统汇总数据,重新计算质量矩阵和节点评分
- 形成新决策,再次下发
这个闭环跑得越勤,调度准确度就越高。但注意,闭环频率不能无限加快——我见过一些团队把调度决策频率调到秒级,结果节点权重被实时指标搞得剧烈震荡,用户前一个请求被导到A节点、后一个请求又被导到B节点,TCP连接池和缓存全部被打乱,体验反而更差。我的建议是:核心决策周期保持在一分钟级到五分钟级,只在故障场景下临时开启秒级收敛。
3.4 机器学习在调度里到底干了点啥
聊到“智能调度”,很多人会直接联想到机器学习。我个人的体感是,ML在调度系统里不是万能药,但确实有三个比较成熟的应用方向:
- 容量预测:根据历史流量周期、大促活动日历、实时曲线,预测未来几分钟到几小时各区域的流量,提前扩容节点或预热内容;
- 热点预取:预测哪些内容即将变成热点,提前分发到边缘节点缓存,减少回源压力;
- 故障预警:从海量监控指标里学习正常模式,发现异常走势提前报警,而不是等用户投诉。
我团队做过一个热点预取模型,输入是发布系统的时间表和历史点击数据,输出是未来热度TOP100的URL列表。把它接到调度系统的预取模块后,大促期间的回源率下降了约30%,效果相当直观。但也要清醒一点:ML模型在流量模式剧变时(比如突发新闻、割接演练)容易失效,所以生产系统一定要保留一条“人工覆盖通道”——关键时段的调度策略,人工可以直接指定。
4. 调度的稳定之道:故障倒换、限流保护与灰度发布的实战经验
调度系统设计得再“智能”,如果稳定性不行,一切都是零。我在一线踩过的坑里,有很大一部分和“变更”“故障”相关。这部分我想重点讲讲如何在调度系统上做好风险控制。
4.1 调度策略变更,必须走灰度发布
调度策略变更的影响范围比改代码还大——代码上线前还有测试环境,调度规则一变,全球流量几分钟内就会受影响。所以我现在对所有调度策略的变更,强制走灰度发布流程,步骤大致这样:
- 先在测试域名或1%的线上流量上应用新策略;
- 对比新策略与旧策略的首包时间、错误率、命中率,观察至少10到30分钟;
- 指标稳定后逐步放大流量比例,从1%到5%再到20%、50%,每一步保留回滚能力;
- 全量发布后持续观察一个完整业务周期,并设置自动回滚阈值。
灰度期间有一个关键细节:对照组和实验组尽量采用同一批用户属性(地域、运营商、设备类型)。否则流量比例的差异容易埋没新策略的真实效果,之前我就吃过亏,灰度组切到了北方用户,恰逢当天晚高峰网络波动,还以为策略有性能问题差点误杀了方案。
4.2 故障自动倒换要带“冷却时间”
当调度系统检测到某个边缘节点故障或质量恶化时,会自动降低该节点的调度权重,甚至直接摘除节点。这个过程如果设计得太激进,很容易引发“抖动风暴”:
- 节点A出现网络抖动,健康检查失败;
- 调度系统立刻把A的流量全部切到B;
- B突然扛不住流量,健康检查也开始失败;
- 调度系统又把B的流量切到A;
- 于是A、B两个节点反复横跳,用户请求来回切换,大量连接被重置。
我在生产系统里加的机制是:每次故障倒换后设置一段“冷却时间”,比如60秒内不再对该节点做同方向的二次切换。同时给同一个故障节点设置“最小摘除时长”,例如连续三次健康检查失败才触发摘除,并且摘除后至少要等2分钟才能重新接收流量。这样即使节点状态波动,也不会引起调度震荡。
4.3 调度层限流:防止雪崩的最后防线
现在流量尖峰越来越猛,边缘节点的容量规划哪怕做得再好,也难免被瞬间突发流量击穿。这种情况下,调度系统应该具备“限流保护”能力,但不能简单粗暴地拒绝请求,而是要有优先级地管理流量。
我常用的思路是分级保护:
- 第一级:保证核心页面请求(HTML、API)永远有处理名额;
- 第二级:保证登录态用户或付费用户的请求有高优先级;
- 第三级:静态资源、图片、下载类请求可以被降级或延迟处理;
- 兜底:当节点容量利用率超过95%,调度系统开始把新流量导向备用节点,并同步开启边缘层的排队机制。
这套分级机制配合调度系统的权重调整,能有效缓解“打爆一个节点,整个集群跟着挂”的连锁反应。实测下来,和我们合作的一个电商客户在大促峰值比平时高15倍的情况下,核心页面错误率依然控制在0.1%以内。
4.4 健康检查别只测TCP端口
最后讲一个非常细节但很常见的坑:很多团队的调度系统,健康检查只做了“TCP端口通不通”或者“HTTP返回码是不是200”。这个粒度远远不够,因为边缘节点进程虽然活着,不代表服务是健康的。
我目前推荐的做法是做三层健康检查:
- TCP层:端口是否可达
- HTTP层:请求头是否正确返回,返回码是否正常
- 内容层:实际请求一个指定的探针URL,校验内容签名或关键字段
探针URL要选一个轻量级的,比如一个简单的JSON接口或者一个固定文件,不要用耗时高的业务接口,否则健康检查回包本身就慢,容易误判。三层检查全部通过才算健康,任何一层失败就触发降权或摘除。这套机制曾经帮我提前发现过一个节点“进程在、线程池满、页面全503”的事故——如果只查端口,那台节点还会继续接流量,事故面会大得多。
5. 已在路上的新变量:IPv6、HTTP/3与边缘计算正在重塑调度策略
调度系统不是一个静态系统,它必须跟着网络基础设施和业务形态的变化持续演进。最近这两三年,有三个新变量正在明显影响调度策略的设计和落地方式。
5.1 IPv6规模化部署下的寻址挑战
IPv6地址空间和IPv4完全不同,地址数量大到靠IP段去识别地域和运营商变得不可靠。以前一条IPv4地址段记录就能覆盖某省某运营商,现在IPv6的地址分配规则更复杂,单纯依赖GeoIP数据库的误差明显偏大。
我的处理思路是双栈分离:对IPv6用户,调度决策更多依赖实时探测和网络质量矩阵,而不是静态地理库;在探测样本不足的区域,宁可把流量调度到相邻省份的同运营商节点,也不要因为地址识别不准而随意跨链路段回源。这条策略在双栈渗透率高的区域验证下来,首包时延能稳定在可接受的范围内。
5.2 HTTP/3和QUIC对连接调度的冲击
QUIC协议的连接迁移特性,让用户在网络切换时也能保持会话不断。这对调度系统其实是个利好——因为调度的切换成本变低了。以前用户访问的节点IP换掉,TCP连接需要重建,握手开销明显;现在QUIC连接可以携带原连接的身份标识迁移到新IP,切换几乎无感。
但代价是:调度系统的可观测性需要跟上。QUIC流量不再像TCP那样具备显著的四元组特征,需要额外解析QUIC CID和连接标识来关联用户和调度决策。我们最近在做的调度优化里,就有专门的模块去识别“哪些连接可以通过QUIC的Connection ID平滑迁移”,这样节点扩容和缩容时就能更放心地进行流量腾挪,不再担心连接重建拖垮用户体验。
5.3 边缘计算让“调度”这个词的外延变宽了
经典CDN调度的核心是内容分发——把已经生成好的资源搬到离用户更近的地方。但边缘计算普及后,一个边缘节点上跑的不再只是静态缓存,还有函数计算、实时转码、AI推理等服务。这就带来一个新的调度维度:任务调度。
这比内容调度复杂得多,因为函数或推理任务有“计算亲和性”,可能依赖特定的模型资源、GPU实例、数据集缓存。调度系统需要同时考虑计算资源剩余量、依赖数据的本地命中情况、输出结果的传输成本。我们内部把这种调度叫“算力感知调度”,目前还在比较初级的阶段,但大的方向已经比较明确:未来的调度系统一定是一套同时管理内容、算力和网络路径的复合决策系统。
5.4 我对调度系统下一阶段的一点想法
结合最近的工程实践,我认为调度系统会走向“策略即代码”的模式。调度规则不再是一堆手工配置的静态表,而是可以用代码表达、可以版本化管理、可以自动化测试的策略单元。每个策略单元都像软件工程里的模块一样,有输入、输出、异常分支和测试用例。调度系统的变更管理水平,会越来越接近一个大型软件系统的发布管理。
说到底,CDN调度这套东西,表面看是网络技术,骨子里其实是系统工程。选节点、看指标、调权重、做灰度、控风险,每个环节都有大量值得打磨的细节。每秒数亿次请求能平稳被送达到正确的节点,靠的不是某个单项技术有多黑,而是整个决策链条上每一环都经得起考验。
最后分享一个最近在验证的小技巧:如果你运维的CDN系统支持自定义探测任务,可以尝试把“首屏关键资源”单独做成一个探针URL,调度系统定期拨测每个候选节点的该资源首包时间,而不是只测一个通用URL。用贴近真实业务的URL做探针,调度结果往往比通用指标更贴近用户体验。这个改动不大,但实测对我们优化动态首屏的调度效果很明显,你可以试试看。