89、CDN基础:CDN架构、内容分发、边缘节点
说到CDN,很多人第一反应就是「加速」。没错,但加速只是结果。真正要理解CDN,你得先搞清楚它到底解决了什么问题。
我刚开始做网络编程那会儿,给一个视频平台做后端。用户分布在五湖四海,服务器却只放在北京。结果呢?新疆的用户打开一个视频要等十几秒,广东的用户看标清都卡。老板拍桌子问:「能不能让所有人都像在北京一样快?」
嗯,这就是CDN要干的事。
CDN的核心思想:离用户近一点
说白了,CDN就是「把内容搬到离用户最近的地方」。你想想看,数据在光纤里跑,物理距离越远,延迟就越高。从北京到新疆,光速也得跑十几毫秒,再加上路由跳转、丢包重传,几十毫秒甚至上百毫秒就出去了。
那怎么办?多放几台服务器。在全国各地甚至全球部署节点,用户访问时自动路由到最近的节点。这就是CDN最朴素的思想。
核心概念:
- 源站:你的原始服务器,存放真正的数据
- 边缘节点:部署在各地的缓存服务器,离用户最近
- 内容分发:把源站的内容同步到所有边缘节点
- 调度系统:决定用户该访问哪个边缘节点
CDN架构长什么样?
我习惯把CDN架构分成三层来看:
- 用户层:浏览器、APP、各种客户端
- 边缘层:遍布各地的边缘节点,负责直接响应请求
- 源站层:你的后端服务器,真正的数据源头
用户请求先到边缘节点。如果边缘节点有缓存,直接返回。如果没有,边缘节点会去源站拉取,然后缓存下来,再返回给用户。下次再有用户请求同样的资源,就直接从缓存走了。
这里有个关键点:缓存策略。不是所有内容都适合长期缓存。静态资源(图片、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选型
做项目时,CDN选型主要看这几个维度:
- 覆盖范围:国内还是海外?节点够不够多?
- 协议支持:HTTP/2、QUIC、WebSocket 支不支持?
- 缓存策略:能不能自定义缓存规则?支持不支持动态加速?
- 安全能力:有没有WAF、DDoS防护?
- 成本:按流量计费还是按带宽计费?有没有最低消费?
我建议小项目先用云厂商的CDN(阿里云、腾讯云、AWS CloudFront),配置简单,按量付费。大项目或者对延迟要求极高的场景,可以考虑自建CDN,用Nginx + Varnish或者Squid搭建边缘节点,配合DNS调度。
一个小技巧: 调试CDN时,可以在请求头里加 X-Cache: HIT 或 X-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