名称: cdn-architecture 描述: 用于设计内容交付网络、缓存策略或全球内容分布时使用。涵盖CDN架构、缓存层次结构、源站屏蔽、缓存失效和边缘优化。 允许工具: Read, Glob, Grep
CDN架构
内容交付网络架构的综合指南 - 缓存、分布和边缘优化模式。
何时使用此技能
- 为Web应用程序设计CDN策略
- 实施缓存层次结构
- 优化源站负载和性能
- 理解缓存失效模式
- 选择CDN提供商和功能
- 配置边缘缓存规则
CDN基础
CDN如何工作
无CDN:
用户(东京) ───────────────────► 源站(纽约)
2000公里,~200毫秒RTT
有CDN:
用户(东京) ──► 边缘(东京) ──► 源站(纽约)
<10公里,~10毫秒RTT (仅在缓存未命中时)
CDN好处:
├── 减少延迟(内容从附近提供)
├── 源站卸载(较少请求击中源站)
├── DDoS防护(分布式,吸收攻击)
├── 可扩展性(处理流量峰值)
└── 可靠性(多个POP提供冗余)
CDN架构
CDN组件:
┌─────────────────────────────────────────────────────────┐
│ 互联网 │
└────────────────────────┬────────────────────────────────┘
│
┌───────────────┼───────────────┐
│ │ │
┌────▼────┐ ┌────▼────┐ ┌────▼────┐
│ 边缘 │ │ 边缘 │ │ 边缘 │
│ POP 1 │ │ POP 2 │ │ POP 3 │
│(东京) │ │(伦敦) │ │(纽约) │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
└───────────────┼───────────────┘
│
┌──────────▼──────────┐
│ 源站屏蔽 │
│ (中间层) │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ 源站 │
│ (您的服务器) │
└─────────────────────┘
术语:
- POP:存在点(边缘位置)
- 边缘:最接近用户的服务器
- 源站屏蔽:可选中间缓存
- 源站:您的实际服务器
缓存命中/未命中流程
请求流程:
1. 用户请求asset.js
2. 边缘缓存检查
┌─────────────────────────────┐
│ asset.js在边缘缓存中吗? │
└─────────────┬───────────────┘
│
┌────────┴────────┐
│ │
命中:立即返回 未命中:转发
(~10毫秒) 到源站屏蔽
3. 源站屏蔽检查(如配置)
┌─────────────────────────────┐
│ asset.js在屏蔽中吗? │
└─────────────┬───────────────┘
│
┌────────┴────────┐
│ │
命中:返回到边缘 未命中:转发
(~50毫秒) 到源站
4. 源站获取
┌─────────────────────────────┐
│ 从源站服务器获取 │
│ 在屏蔽和边缘中缓存 │
└─────────────────────────────┘
(~200毫秒)
关键指标:
- 缓存命中率(CHR):从缓存服务的请求百分比
- 首字节时间(TTFB):接收首字节的延迟
- 源站请求:到达源站的请求数量
缓存策略
Cache-Control头部
Cache-Control指令:
浏览器 + CDN:
Cache-Control: public, max-age=31536000
└── 任何人可缓存1年
仅CDN:
Cache-Control: private, no-store
└── 不缓存(敏感数据)
短期缓存:
Cache-Control: public, max-age=300, s-maxage=3600
└── 浏览器:5分钟,CDN:1小时
陈旧-while-重新验证:
Cache-Control: public, max-age=3600, stale-while-revalidate=86400
└── 在后台重新验证时提供陈旧内容24小时
CDN特定头部:
CDN-Cache-Control: max-age=3600
Surrogate-Control: max-age=3600
Cloudflare-CDN-Cache-Control: max-age=3600
缓存决策矩阵
内容类型 → 缓存策略:
静态资源(JS, CSS, 图像):
├── 长TTL(1年)
├── 基于内容的文件名(哈希)
├── 不可变标志
└── Cache-Control: public, max-age=31536000, immutable
HTML页面:
├── 短TTL或无缓存
├── 基于重新验证
├── ETag/最后修改
└── Cache-Control: no-cache(每次重新验证)
API响应(公共数据):
├── 短到中TTL
├── 根据适当头部变化
├── 考虑stale-while-revalidate
└── Cache-Control: public, max-age=60, stale-while-revalidate=300
API响应(个性化):
├── 不在CDN缓存
├── 可在浏览器缓存带认证
└── Cache-Control: private, no-store
用户生成内容:
├── 中TTL
├── 更新时考虑清除
└── Cache-Control: public, max-age=3600
Vary头部
Vary头部用法:
目的:基于请求头部缓存不同版本
Vary: Accept-Encoding
└── 缓存单独的gzip、brotli和普通版本
Vary: Accept-Language
└── 按语言缓存单独版本
└── 警告:可能导致缓存变体爆炸
Vary: Cookie
└── 通常意味着“不在CDN缓存”
└── 每个唯一cookie = 不同缓存条目
最佳实践:
✓ Vary: Accept-Encoding(始终用于可压缩内容)
✓ Vary: Origin(用于CORS)
✗ 避免Vary: Cookie(缓存片段化严重)
✗ 避免Vary: User-Agent(数千变体)
Vary替代方案:
- 在边缘规范化头部
- 使用查询参数替代
- 为不同变体使用单独URL
源站屏蔽
屏蔽架构
无源站屏蔽:
边缘POPs:200+位置
│ │ │ │ │ │ │ │ │ │
└─┴─┴─┴─┴─┴─┴─┴─┴─┘
│
所有200个POPs可从源站请求
▼
┌────────┐
│ 源站 │ (200个潜在请求者,在缓存未命中时)
└────────┘
有源站屏蔽:
边缘POPs:200+位置
│ │ │ │ │ │ │ │ │ │
└─┴─┴─┴─┴─┴─┴─┴─┴─┘
│
所有边缘未命中转到屏蔽
▼
┌─────────────────┐
│ 源站屏蔽 │ (每个区域1个屏蔽)
│ (合并) │
└────────┬────────┘
│
仅屏蔽从源站请求
▼
┌────────┐
│ 源站 │ (1-3个潜在请求者)
└────────┘
好处:
- 合并缓存未命中
- 减少源站负载
- 更好的缓存效率
- 改进源站可用性
请求合并
请求合并(汇聚):
场景:100个用户同时请求相同未缓存资源
无合并:
100个请求 ──► 边缘 ──► 100个请求 ──► 源站
(雷群效应)
有合并:
100个请求 ──► 边缘 ──► 1个请求 ──► 源站
│
99个请求等待
│
响应缓存,所有100个被服务
实施:
- 第一个请求触发源站获取
- 后续相同URL请求等待
- 所有请求从单个源站响应服务
- 在缓存未命中峰值时保护源站的关键
缓存失效
失效策略
策略1:基于TTL的过期
└── 让内容自然过期
└── 简单,可预测
└── 更改传播延迟
策略2:清除(立即失效)
└── 从缓存中移除特定URL
└── 快速更新传播
└── 在大规模时可能昂贵
策略3:软清除(陈旧-while-重新验证)
└── 标记内容为陈旧
└── 在获取新鲜内容时提供陈旧内容
└── 最佳用户体验
策略4:版本化URL
└── 内容更改时更改URL
└── 无需清除
└── 最佳缓存效率
└── asset.js?v=abc123 或 asset.abc123.js
策略5:缓存标签(代理键)
└── 用标识符标记内容
└── 按标签而非URL清除
└── 适用于相关内容
└── 清除所有“product-123”标记的内容
版本化模式
URL版本化:
模式1:查询参数
/styles.css?v=1.2.3
/styles.css?v=a1b2c3d4(哈希)
+ 易于实施
- 一些CDN默认不缓存查询字符串
模式2:文件名哈希
/styles.a1b2c3d4.css
+ 最佳缓存效率
+ CDN默认缓存
- 需要构建过程
模式3:路径版本化
/v1.2.3/styles.css
+ 清晰版本组织
- 可能有多个版本需清除
推荐:
- 静态资源:文件名哈希(最佳缓存效率)
- API:路径版本化(/v1/api/...)
- HTML:短TTL + 重新验证
缓存标签 / 代理键
缓存标签示例:
源站响应:
HTTP/1.1 200 OK
Surrogate-Key: product-123 category-electronics homepage
Cache-Control: public, max-age=86400
内容标记为:
- product-123(特定产品)
- category-electronics(产品类别)
- homepage(出现在首页)
清除场景:
- 产品更新:清除“product-123”
- 类别重组:清除“category-electronics”
- 首页更改:清除“homepage”
单个清除影响所有带该标签的URL。
边缘计算
边缘函数
边缘函数用例:
1. 请求操作
- URL重写
- 头部修改
- 认证
- 基于地理位置的路由
2. 响应操作
- HTML注入(A/B测试)
- 内容转换
- 边缘个性化
- 响应压缩
3. 安全
- 机器人检测
- 速率限制
- WAF规则
- 令牌验证
4. 缓存逻辑
- 自定义缓存键
- Vary规范化
- 缓存绕过规则
- 选择性清除
平台:
- Cloudflare Workers
- AWS Lambda@Edge / CloudFront Functions
- Fastly Compute@Edge
- Akamai EdgeWorkers
边缘A/B测试
边缘A/B测试:
传统(源站基础):
用户 ──► CDN ──► 源站 ──► 确定变体 ──► 响应
│ (由于个性化,不可缓存)
每次缓存未命中
边缘基础:
用户 ──► 边缘Worker ──► 分配变体(cookie/header)
│
├── 变体A:服务 /page-a(可缓存)
└── 变体B:服务 /page-b(可缓存)
好处:
- 每个变体单独可缓存
- 无需每请求源站计算
- 一致变体分配
- 边缘分析
CDN选择
提供商比较
CDN提供商考虑因素:
性能:
├── 全球POP覆盖
├── 网络质量(对等)
├── 缓存命中率
└── TTFB基准
功能:
├── 边缘计算支持
├── 实时分析
├── 自定义缓存规则
├── 图像优化
├── 视频流
└── 安全功能(WAF, DDoS)
定价模型:
├── 基于带宽
├── 基于请求
├── 固定费率
└── 承诺折扣
集成:
├── API质量
├── Terraform/IaC支持
├── CI/CD集成
└── 监控集成
主要提供商:
- Cloudflare:出色的开发者体验,慷慨免费层
- Fastly:适合动态/个性化内容
- AWS CloudFront:与AWS生态系统最佳
- Akamai:企业级,全球最多POPs
- Azure CDN:与Azure生态系统最佳
最佳实践
CDN最佳实践:
1. 缓存效率
□ 对静态资源使用内容哈希
□ 为内容类型设置适当TTLs
□ 实施源站屏蔽
□ 监控缓存命中率
2. 性能
□ 启用压缩(Brotli/Gzip)
□ 使用HTTP/2或HTTP/3
□ 实施预连接提示
□ 为核心Web指标优化
3. 缓存失效
□ 优先使用版本化URL而非清除
□ 为相关内容使用缓存标签
□ 尽可能实施软清除
□ 准备好清除自动化
4. 安全
□ 随处启用HTTPS
□ 配置正确CORS
□ 实施安全头部
□ 对敏感内容使用签名URL
5. 监控
□ 跟踪缓存命中率
□ 监控源站负载
□ 设置延迟警报
□ 分析错误率
故障排除
常见问题:
1. 低缓存命中率
- 检查Vary头部扩散
- 验证cache-control头部
- 查看查询字符串变化
- 检查基于cookie的变化
2. 陈旧内容
- 验证cache-control max-age
- 检查清除传播延迟
- 确认版本化策略
- 审查源站响应头部
3. 高源站负载
- 实施源站屏蔽
- 启用请求合并
- 在适当处延长TTLs
- 为API响应添加缓存
4. 慢性能
- 检查POP分布
- 验证压缩已启用
- 审查TLS配置
- 分析源站响应时间
调试头部:
X-Cache: HIT/MISS
X-Cache-Hits: 123
Age: 3600
CF-Cache-Status: DYNAMIC/HIT/MISS
相关技能
edge-computing- 在CDN边缘计算latency-optimization- 端到端延迟减少multi-region-deployment- 全球基础设施模式caching-strategies- 应用级缓存