跳到主要内容

CDN 原理与实践

问题

CDN 是什么?它是如何加速网站访问的?

答案

CDN(Content Delivery Network,内容分发网络)是一组分布在全球各地的服务器,通过就近访问提高内容传输速度。

CDN 工作原理

核心优势

优势说明
降低延迟就近访问边缘节点
减轻源站压力边缘节点缓存内容
提高可用性多节点冗余
抵御攻击DDoS 防护
节省带宽减少跨网流量

CDN 访问流程

DNS 智能解析

# 查看 CDN DNS 解析过程
dig www.taobao.com

# 可能看到多级 CNAME
; www.taobao.com. CNAME www.taobao.com.danuoyi.tbcache.com.
; www.taobao.com.danuoyi.tbcache.com. CNAME ...
# 最终返回离用户最近的边缘节点 IP

CDN 缓存策略

缓存控制

// 源站设置缓存头
// Cache-Control: max-age=86400 (缓存 1 天)
// Cache-Control: no-cache (每次验证)
// Cache-Control: no-store (不缓存)

// CDN 常见策略
interface CDNConfig {
// 缓存时间
cacheTTL: {
html: 0, // 不缓存
css: 86400, // 1 天
js: 86400, // 1 天
image: 2592000, // 30 天
font: 31536000 // 1 年
};

// 缓存键
cacheKey: 'url + query + header';

// 忽略查询参数
ignoreQueryString: false;
}

缓存命中与回源

场景行为
缓存命中直接返回,响应快
缓存未命中回源获取,然后缓存
缓存过期协商缓存或重新获取
主动刷新CDN 控制台刷新缓存
// 判断是否命中 CDN 缓存
// 通常 CDN 会在响应头中标识

// 阿里云 CDN
// X-Cache: HIT TCP_MEM_HIT (命中内存缓存)
// X-Cache: HIT TCP_DISK_HIT (命中磁盘缓存)
// X-Cache: MISS (未命中)

// Cloudflare
// cf-cache-status: HIT
// cf-cache-status: MISS

CDN 配置实践

资源部署

// 1. 静态资源使用 CDN 域名
const assetURL = 'https://cdn.example.com/assets/app.js';

// 2. HTML 保留源站(动态内容)
// https://www.example.com/index.html

// 3. 版本化资源路径(利于缓存)
// ✅ /assets/app.abc123.js
// ❌ /assets/app.js?v=123

Webpack 配置

// webpack.config.js
module.exports = {
output: {
// 使用 contenthash 生成文件名
filename: '[name].[contenthash].js',
// 配置 CDN 域名
publicPath: 'https://cdn.example.com/'
}
};

Vite 配置

// vite.config.ts
export default defineConfig({
base: 'https://cdn.example.com/',
build: {
rollupOptions: {
output: {
// 资源文件名包含 hash
assetFileNames: 'assets/[name].[hash][extname]',
chunkFileNames: 'assets/[name].[hash].js',
entryFileNames: 'assets/[name].[hash].js'
}
}
}
});

CDN 高级特性

1. 边缘计算

// Cloudflare Workers 示例
// 在边缘节点执行代码

addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});

async function handleRequest(request: Request): Promise<Response> {
const url = new URL(request.url);

// A/B 测试
const variant = Math.random() < 0.5 ? 'a' : 'b';
url.pathname = `/variants/${variant}${url.pathname}`;

// 地理位置定向
const country = request.cf?.country || 'US';

// 请求改写
return fetch(url.toString(), {
headers: {
'X-Country': country
}
});
}

2. 图片优化

// CDN 图片处理
// 原始: https://cdn.example.com/image.jpg

// 缩放
// https://cdn.example.com/image.jpg?w=200&h=200

// 格式转换(自动 WebP)
// https://cdn.example.com/image.jpg?format=webp

// 质量压缩
// https://cdn.example.com/image.jpg?quality=80

// 裁剪
// https://cdn.example.com/image.jpg?crop=center

3. 安全防护

// 防盗链
// Referer 白名单
// 签名 URL(带时间戳和签名)

// 生成签名 URL
function generateSignedURL(
baseURL: string,
secretKey: string,
expireTime: number
): string {
const expire = Math.floor(Date.now() / 1000) + expireTime;
const stringToSign = `${baseURL}${expire}${secretKey}`;
const signature = md5(stringToSign);
return `${baseURL}?expire=${expire}&sign=${signature}`;
}

4. HTTPS 与 HTTP/2

// CDN 通常支持
// - 免费 HTTPS 证书
// - HTTP/2 自动启用
// - HTTP/3 (QUIC)
// - TLS 1.3

CDN 选型对比

服务商特点适用场景
阿里云 CDN国内节点多,DCDN国内业务
腾讯云 CDN与腾讯生态集成国内业务
Cloudflare免费套餐,边缘计算全球业务
AWS CloudFront与 AWS 集成AWS 用户
Fastly边缘计算强性能要求高

常见面试问题

Q1: CDN 的工作原理?

答案

  1. DNS 解析:域名 CNAME 到 CDN,智能 DNS 返回最近节点
  2. 就近访问:用户访问离自己最近的边缘节点
  3. 缓存命中:边缘节点有缓存直接返回
  4. 回源:无缓存时向源站获取,缓存后返回

Q2: CDN 如何选择最优节点?

答案

CDN 通过智能 DNS 实现节点选择:

因素说明
地理位置根据用户 IP 判断位置
网络拓扑考虑 ISP、网络跳数
节点负载避免热点节点
健康状态剔除故障节点
实时性能RTT、丢包率

Q3: CDN 缓存没有生效怎么排查?

答案

// 1. 检查响应头
// X-Cache: MISS 表示未命中
// 查看 Cache-Control、ETag 等

// 2. 检查缓存规则
// CDN 控制台配置是否正确
// 文件类型是否在缓存列表

// 3. 检查源站响应
// 源站是否设置了 no-cache、no-store
// 是否有 Set-Cookie(默认不缓存)

// 4. 缓存键冲突
// 查询参数不同导致缓存键不同
// 配置忽略查询参数或指定缓存键

// 5. 刷新缓存
// 手动刷新 CDN 缓存

Q4: CDN 和反向代理的区别?

答案

特性CDN反向代理
节点数量全球分布,大量节点少量服务器
主要目的加速访问、减轻源站压力负载均衡、安全
缓存策略边缘缓存,智能分发简单缓存
使用场景静态资源加速API 代理、入口网关

Q5: 如何设计一个静态资源缓存策略?

答案

// 1. HTML: 不缓存或短缓存
// Cache-Control: no-cache
// 每次请求验证,保证最新

// 2. 带 hash 的资源: 长期缓存
// app.abc123.js
// Cache-Control: max-age=31536000, immutable
// 文件名变化即更新

// 3. 图片/字体: 长期缓存
// Cache-Control: max-age=31536000
// 配合 ETag 协商

// 4. API 响应: 不缓存
// Cache-Control: no-store

相关链接