CDN 优化:这次怎么落地的
这次做 CDN 优化,从选择服务商到深度优化,。
CDN(Content Delivery Network)通过在全球部署边缘节点,将内容缓存到离用户最近的地方。
CDN 原理
基本原理
CDN(Content Delivery Network)通过在全球部署边缘节点,将内容缓存到离用户最近的地方。
graph TB
A[用户] --> B[DNS解析]
B --> C[CDN边缘节点]
C -->|缓存命中| D[返回内容]
C -->|缓存未命中| E[回源服务器]
E --> C
C --> D
style A fill:#FFD700
style C fill:#90EE90
style D fill:#FFB6C1
工作流程
- 用户访问 CDN 域名
- DNS 解析到最近的 CDN 节点
- CDN 节点检查缓存
- 缓存命中:直接返回
- 缓存未命中:回源获取并缓存
CDN 服务商选择
主流服务商
| 服务商 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|
| Cloudflare | 免费、全球节点多、安全功能强 | 定制化差 | 中小网站 |
| AWS CloudFront | 与 AWS 集成好 | 价格高 | AWS 用户 |
| 阿里云 CDN | 国内节点多、价格合理 | 海外节点少 | 国内为主 |
| 腾讯云 CDN | 节点多、价格优惠 | 文档一般 | 国内为主 |
选择标准
国内为主:阿里云 CDN、腾讯云 CDN
海外为主:Cloudflare、AWS CloudFront
全球部署:Cloudflare + 国内 CDN
Cloudflare 配置
基础配置
# 添加域名
1. 登录 Cloudflare
2. 添加域名 example.com
3. 修改域名 DNS 服务器到 Cloudflare
# 配置 DNS 记录
Type: CNAME
Name: www
Target: example.com
Proxy status: Proxied(橙色云)
缓存规则
# Page Rules
URL Pattern: *example.com/static/*
Settings:
- Cache Level: Cache Everything
- Edge Cache TTL: 1 month
- Browser Cache TTL: 4 hours
URL Pattern: *example.com/api/*
Settings:
- Cache Level: Bypass
- Disable Performance
压缩配置
# Auto Minify
- JavaScript: 启用
- CSS: 启用
- HTML: 启用
# Brotli
- Enable Brotli: 启用
阿里云 CDN 配置
基础配置
# 添加域名
1. 登录阿里云 CDN
2. 添加域名 example.com
3. 配置 CNAME 记录
# 验证配置
dig CNAME www.example.com
缓存配置
# 缓存配置
目录: /static/*
过期时间: 1 个月
目录: /images/*
过期时间: 6 个月
目录: /api/*
过期时间: 不缓存
回源配置
# 回源协议
协议跟随: HTTP
# 回源 HOST
回源 HOST: example.com
# 回源端口
端口: 80
应用层优化
静态资源版本控制
// webpack.config.js
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
output: {
filename: '[name].[contenthash].js',
chunkFilename: '[name].[contenthash].chunk.js',
},
plugins: [
new CleanWebpackPlugin(),
],
};
资源预加载
<!-- 预加载关键资源 -->
<link rel="preload" href="/static/css/main.css" as="style">
<link rel="preload" href="/static/js/main.js" as="script">
<link rel="preload" href="/fonts/main.woff2" as="font" crossorigin>
<!-- 预连接到 CDN -->
<link rel="preconnect" href="https://cdn.example.com">
图片优化
# 使用 WebP 格式
ffmpeg -i image.png -c:v libwebp -quality 80 image.webp
# 响应式图片
<picture>
<source srcset="image.webp" type="image/webp">
<source srcset="image.jpg" type="image/jpeg">
<img src="image.jpg" alt="Description">
</picture>
字体优化
/* 使用 font-display 优化字体加载 */
@font-face {
font-family: 'MyFont';
src: url('/fonts/myfont.woff2') format('woff2');
font-display: swap;
}
踩过的坑
坑一:缓存未命中
CDN 缓存命中率低,效果不明显。
解决:优化缓存规则,增加缓存时间。
# 配置缓存规则
目录: /*.js
过期时间: 1 个月
目录: /*.css
过期时间: 1 个月
目录: /*.woff2
过期时间: 1 年
坑二:跨域问题
CDN 资源跨域访问失败。
解决:配置 CORS 头。
// Nginx 配置
location ~* \.(jpg|jpeg|png|gif|webp|css|js|woff2)$ {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, OPTIONS";
add_header Access-Control-Max-Age 86400;
}
# 或者 Cloudflare Page Rules
URL Pattern: *example.com/static/*
Settings:
- Add Header: Access-Control-Allow-Origin: *
坑三:HTTPS 配置
CDN HTTPS 配置复杂。
解决:使用 Let’s Encrypt。
# Cloudflare SSL/TLS
SSL/TLS encryption mode: Full (strict)
# 阿里云 CDN
HTTPS 配置: 开启
证书: Let's Encrypt
坑四:回源问题
CDN 回源失败,导致服务不可用。
解决:配置多个源站,实现高可用。
# 多源站配置
源站 1: origin1.example.com
源站 2: origin2.example.com
源站 3: origin3.example.com
权重: 1:1:1
性能监控
监控指标
// 使用 Performance API
function getCDNPerformance() {
const resources = performance.getEntriesByType('resource');
return resources.map(resource => ({
name: resource.name,
duration: resource.duration,
transferSize: resource.transferSize,
decodedBodySize: resource.decodedBodySize
}));
}
// 分析 CDN 资源
function analyzeCDNResources() {
const resources = getCDNPerformance();
const cdnResources = resources.filter(r => r.name.includes('cdn.example.com'));
return {
count: cdnResources.length,
totalSize: cdnResources.reduce((sum, r) => sum + r.transferSize, 0),
avgDuration: cdnResources.reduce((sum, r) => sum + r.duration, 0) / cdnResources.length
};
}
使用 Lighthouse
# 运行 Lighthouse
npx lighthouse https://example.com --view
# 检查 CDN 配置
# 1. 查看静态资源是否使用 CDN
# 2. 查看缓存头是否正确
# 3. 查看压缩是否启用
最佳实践
缓存策略
# 静态资源:长期缓存
目录: /static/*
过期时间: 1 年
# 图片:长期缓存
目录: /images/*
过期时间: 1 年
# API:不缓存
目录: /api/*
过期时间: 不缓存
# HTML:短期缓存
目录: /*.html
过期时间: 1 小时
版本控制
// 使用内容哈希
import { version } from './version.json';
const imageUrl = `/images/logo.png?v=${version}`;
// 或者使用文件名哈希
import logo from './logo.png';
const img = new Image();
img.src = logo; // 自动带上内容哈希
预热 CDN
# 预热 CDN 缓存
for file in static/images/*; do
curl -X PURGE "https://cdn.example.com/$file"
done
# 或者使用 Cloudflare API
curl -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/purge_cache" \
-H "Authorization: Bearer ${API_TOKEN}" \
-H "Content-Type: application/json" \
--data '{"files":["https://example.com/static/css/main.css"]}'
写在最后
CDN 优化这东西,不只是技术问题,是用户体验问题。
优化了:
- 首屏加载时间
- 用户体验
- 流量成本
带来了:
- 运维成本
- 缓存管理
- 配置复杂度
优化之前先评估:
- 用户分布
- 内容类型
- 预算
- 技术能力
不是所有内容都需要 CDN,有时候本地缓存就够用。
这次 CDN 优化花了两周,从选择服务商到深度优化。优化完成后,首屏加载时间从 3 秒降到 1 秒,海外用户体验提升明显。
版权声明: 本文首发于 指尖魔法屋-CDN 优化:这次怎么落地的(https://blog.thinkmoon.cn/post/74-cdn-optimization-global-acceleration-practice/) 转载或引用必须申明原指尖魔法屋来源及源地址!
评论
使用 GitHub 账号登录后即可留言,支持 Markdown。