89、CDN基础:CDN架构、内容分发、边缘节点

说到CDN,很多人第一反应就是「加速」。没错,但加速只是结果。真正要理解CDN,你得先搞清楚它到底解决了什么问题。

我刚开始做网络编程那会儿,给一个视频平台做后端。用户分布在五湖四海,服务器却只放在北京。结果呢?新疆的用户打开一个视频要等十几秒,广东的用户看标清都卡。老板拍桌子问:「能不能让所有人都像在北京一样快?」

嗯,这就是CDN要干的事。

CDN的核心思想:离用户近一点

说白了,CDN就是「把内容搬到离用户最近的地方」。你想想看,数据在光纤里跑,物理距离越远,延迟就越高。从北京到新疆,光速也得跑十几毫秒,再加上路由跳转、丢包重传,几十毫秒甚至上百毫秒就出去了。

那怎么办?多放几台服务器。在全国各地甚至全球部署节点,用户访问时自动路由到最近的节点。这就是CDN最朴素的思想。

核心概念:

  • 源站:你的原始服务器,存放真正的数据
  • 边缘节点:部署在各地的缓存服务器,离用户最近
  • 内容分发:把源站的内容同步到所有边缘节点
  • 调度系统:决定用户该访问哪个边缘节点

CDN架构长什么样?

我习惯把CDN架构分成三层来看:

  1. 用户层:浏览器、APP、各种客户端
  2. 边缘层:遍布各地的边缘节点,负责直接响应请求
  3. 源站层:你的后端服务器,真正的数据源头

用户请求先到边缘节点。如果边缘节点有缓存,直接返回。如果没有,边缘节点会去源站拉取,然后缓存下来,再返回给用户。下次再有用户请求同样的资源,就直接从缓存走了。

这里有个关键点:缓存策略。不是所有内容都适合长期缓存。静态资源(图片、CSS、JS)可以缓存很久。动态内容(用户信息、实时数据)就得小心了,缓存时间太短没意义,太长又会导致数据不一致。

我的经验: 静态资源我一般设置缓存7天,动态API设置30秒到5分钟。具体看业务场景。曾经有个项目,我把用户头像缓存了24小时,结果用户换了头像,别人看到的还是旧头像……嗯,后来改成了1小时。

内容分发是怎么做的?

内容分发,就是把源站的数据「推」到所有边缘节点。常见的方式有两种:

  • 主动分发(Push):源站主动把内容推送到边缘节点。适合大文件、热门资源。
  • 被动分发(Pull):用户请求时,边缘节点发现没有缓存,再去源站拉取。适合冷门资源、动态内容。

实际项目中,两种方式会混合使用。热门视频提前推送到所有节点,冷门视频等用户访问时再拉取。这样既保证了热门内容的响应速度,又节省了冷门内容的存储成本。

我曾经遇到过一个坑:某个活动页面,图片资源特别大,用了被动分发。结果活动上线瞬间,大量用户涌入,所有边缘节点同时去源站拉取图片,源站带宽被打满,直接挂了。后来改成主动分发,提前把图片推到所有节点,问题解决。

注意: 被动分发存在「回源风暴」的风险。大量请求同时回源,源站扛不住。解决方案:预热(提前推送)、限流(控制回源速率)、多级缓存(边缘节点之间互相缓存)。

边缘节点到底做了什么?

边缘节点不只是「存一份缓存」那么简单。它承担了这些工作:

功能 说明
缓存存储 把源站内容缓存到本地磁盘或内存
请求处理 接收用户请求,判断是否命中缓存
回源拉取 缓存未命中时,去源站或上级节点拉取
负载均衡 节点内部多台机器分担请求
协议优化 支持HTTP/2、HTTPS、压缩等
安全防护 拦截DDoS攻击、CC攻击等

边缘节点通常部署在IDC机房或者运营商的网络边缘。离用户越近,效果越好。我见过一些极端案例,边缘节点直接放在小区机房里,延迟能降到1毫秒以内。

CDN的调度机制

用户访问一个域名,怎么知道该去哪个边缘节点?这就要靠调度系统了。

常见的调度方式:

  • DNS调度:根据用户IP的地理位置,返回不同的IP地址。最简单,但精度不高。
  • HTTP调度:用户先访问一个调度中心,返回302重定向到最近的节点。精度高,但多了一次请求。
  • Anycast:多个节点共享同一个IP,路由协议自动把用户导向最近的节点。延迟最低,但部署成本高。

我个人习惯用DNS调度 + HTTP调度混合。DNS做粗粒度调度,HTTP做细粒度调整。比如用户在北京,DNS返回华北节点的IP。如果华北节点负载太高,HTTP调度可以临时把用户导向华东节点。

一张图看懂CDN核心逻辑

下面这张图展示了CDN的基本工作流程。从用户请求到边缘节点,再到源站,最后返回数据。每一步都清晰可见。

CDN核心工作流程 用户请求 浏览器 / APP DNS调度 边缘节点 缓存命中? 判断 命中 返回缓存内容 未命中 源站服务器 真正的数据源头 拉取数据 缓存到边缘节点 返回给用户 用户请求 边缘节点 源站 回源路径

实际项目中的CDN选型

做项目时,CDN选型主要看这几个维度:

  • 覆盖范围:国内还是海外?节点够不够多?
  • 协议支持:HTTP/2、QUIC、WebSocket 支不支持?
  • 缓存策略:能不能自定义缓存规则?支持不支持动态加速?
  • 安全能力:有没有WAF、DDoS防护?
  • 成本:按流量计费还是按带宽计费?有没有最低消费?

我建议小项目先用云厂商的CDN(阿里云、腾讯云、AWS CloudFront),配置简单,按量付费。大项目或者对延迟要求极高的场景,可以考虑自建CDN,用Nginx + Varnish或者Squid搭建边缘节点,配合DNS调度。

一个小技巧: 调试CDN时,可以在请求头里加 X-Cache: HITX-Cache: MISS 来判断是否命中缓存。很多CDN厂商都支持这个自定义头,方便排查问题。

避坑指南

做CDN接入时,有几个坑我踩过,分享给你:

  • 缓存刷新不及时:更新了源站文件,但CDN还在用旧缓存。解决方案:用版本号或者时间戳,比如 style.css?v=20240101
  • HTTPS证书问题:源站和CDN之间也要走HTTPS,否则中间环节可能被劫持。我见过有人只配了用户到CDN的HTTPS,CDN到源站用的HTTP,结果被运营商插广告。
  • 跨域问题:CDN域名和主站域名不同,浏览器会拦截跨域请求。记得配好CORS头。
  • 日志丢失:CDN节点分散,日志收集是个麻烦事。建议用统一的日志服务,比如阿里云SLS或者自建ELK。

嗯,CDN这东西,说复杂也复杂,说简单也简单。核心就是「缓存 + 调度」。你只要把这两个点吃透了,剩下的都是细节。

最后说一句:别把CDN当成万能药。如果你的源站本身性能就很差,CDN也救不了。先把源站优化好,再上CDN,效果才明显。


公众号:蓝海资料掘金营,微信deep3321