CDN 场景下的排障,比单机服务更容易让人迷失。因为用户请求并不是直接到源站,而是先到边缘节点,再根据缓存、调度和策略决定是否回源。链路一旦变长,问题也更容易被中间层掩盖。
CDN 排障真正的难点,不是概念多,而是参与者变多了。客户端、DNS、边缘节点、回源链路、源站本身,任何一层异常都可能在用户视角里表现成同一种“访问异常”。
先把整条链路画出来
排查 CDN 相关问题时,脑子里最好先有一张最小路径图。
用户发起请求,先完成域名解析,再被调度到某个边缘节点。边缘节点会先判断本地是否命中缓存,如果命中,直接返回;如果未命中,或者缓存过期,就继续向源站回源获取内容,然后再把结果返回给用户。
所以同一个“访问慢”现象,可能分别来自下面几类原因。
- 调度到了不合适的边缘节点。
- 边缘节点没有命中缓存。
- 回源链路慢。
- 源站本身处理慢。
- 中间代理或安全策略影响了请求。
一组足够实用的排查手段
1 | curl -I -v https://example.com/resource |
在 CDN 场景里,curl -I -v 特别有价值,因为很多平台会在响应头里带出缓存状态、边缘节点信息、回源痕迹或链路标识。
虽然不同 CDN 厂商的头部名字不一样,但观察思路是一样的:先看有没有命中缓存,再看响应路径有没有表现出回源特征。
一个比较稳的排查顺序
第一步,先确认调度结果。
1 | dig example.com |
这里先看域名最终解析到哪里。如果不同地区、不同 DNS 返回的边缘地址差异很大,就要考虑调度策略本身是否合理。
第二步,看请求阶段耗时。
1 | curl -o /dev/null -s -w 'dns:%{time_namelookup} connect:%{time_connect} tls:%{time_appconnect} starttransfer:%{time_starttransfer} total:%{time_total}\n' https://example.com/resource |
如果前面的 DNS、建连和 TLS 都不高,但首字节时间明显偏大,就很值得怀疑边缘未命中缓存或回源慢。
第三步,看响应头。
1 | curl -I -v https://example.com/resource |
此时重点不是只看状态码,而是看有没有缓存命中标识、边缘节点标识、源站相关头部或者明显的代理痕迹。
第四步,如果你能在边缘或源站侧抓到包,就继续确认回源过程有没有异常,比如源站连接慢、TLS 握手慢、回包慢、上游重传等。
怎么区分是边缘慢还是源站慢
一个很常用的思路,是先比较缓存命中和未命中的表现差异。
如果同一个资源第一次慢、第二次明显快,通常就说明第一次可能经历了回源,第二次命中了边缘缓存。
如果每次都慢,而且首字节一直很高,那更要继续区分是边缘节点处理压力、回源链路问题,还是源站响应慢。
如果命中缓存时依然很慢,就不能再只盯着源站,而要看边缘节点、调度节点或客户端到边缘之间的路径质量。
这也是 CDN 排障里非常重要的一点:不要因为“用了 CDN”就默认所有问题都在源站,也不要因为“回源了”就忽略客户端到边缘这一段链路。
常见误判
第一个常见误判,是把用户看到的 5xx 全部当成源站问题。实际上,边缘节点、回源超时、上游握手失败、代理规则异常,都可能最终表现成 5xx。
第二个常见误判,是只看状态码不看链路。状态码只告诉你结果,不告诉你请求是在哪一层、哪个节点上变坏的。
第三个常见误判,是忽略缓存状态。很多时候用户抱怨“偶尔慢”,根本原因就是命中和未命中混在一起,导致体验不稳定。
一个值得自己做的小实验
选一个带静态资源的站点,连续请求同一个文件几次。
1 | curl -I -v https://example.com/static/app.js |
重点观察。
- 两次请求的首字节时间是否明显不同。
- 响应头里是否出现缓存状态变化。
- 如果换网络环境或换 DNS,调度结果是否变化。
这个实验能非常直观地帮助你理解什么叫“边缘命中”和“回源开销”。
小结
CDN 排障之所以难,不是因为它神秘,而是因为它把一条本来就不短的网络链路又拉长了一层。只要你养成从调度、边缘、缓存、回源、源站这几个环节逐层拆开的习惯,再配合 dig、curl 和必要的抓包去验证,很多看似复杂的 CDN 问题其实都会有清晰的落点。排障最怕一团糊,而 CDN 场景最需要的,恰恰就是把这团糊重新拆成一段一段可验证的链路。