CDN 与 WAF 精讲教程 / 第05章 CDN 性能优化
第05章 CDN 性能优化
本章聚焦 CDN 层面的性能优化技术,涵盖图片优化、压缩算法、协议升级和连接优化,帮助你榨干每一毫秒的性能。
5.1 图片优化
5.1.1 图片格式对比
| 格式 | 压缩方式 | 透明度 | 动画 | 浏览器支持 | 适用场景 |
|---|
| JPEG | 有损 | ❌ | ❌ | 全部 | 照片、复杂图像 |
| PNG | 无损 | ✅ | ❌ | 全部 | Logo、图标、截图 |
| GIF | 无损 | ✅ | ✅ | 全部 | 简单动画 |
| WebP | 有损+无损 | ✅ | ✅ | 96%+ | 现代浏览器首选 |
| AVIF | 有损+无损 | ✅ | ✅ | 90%+ | 最高压缩率 |
| SVG | 矢量 | ✅ | ✅ | 全部 | 图标、图表 |
5.1.2 现代图片策略
响应式图片加载策略:
用户请求 image.jpg
│
▼
┌─────────────────────────────────────┐
│ CDN 边缘图片优化引擎 │
│ │
│ 1. 检测 Accept 头 │
│ ├── 支持 AVIF → 返回 image.avif │
│ ├── 支持 WebP → 返回 image.webp │
│ └── 仅 JPEG → 返回 image.jpg │
│ │
│ 2. 检测设备尺寸 │
│ ├── 移动端 → 宽度 640px │
│ ├── 平板 → 宽度 1024px │
│ └── 桌面 → 宽度 1920px │
│ │
│ 3. 质量参数 │
│ ├── 高带宽 → quality=85 │
│ └── 低带宽 → quality=60 │
└─────────────────────────────────────┘
5.1.3 HTML 响应式图片
<picture>
<!-- AVIF 优先 -->
<source
type="image/avif"
srcset="/image/photo-640w.avif 640w,
/image/photo-1280w.avif 1280w,
/image/photo-1920w.avif 1920w"
sizes="(max-width: 640px) 640px,
(max-width: 1280px) 1280px,
1920px">
<!-- WebP 其次 -->
<source
type="image/webp"
srcset="/image/photo-640w.webp 640w,
/image/photo-1280w.webp 1280w,
/image/photo-1920w.webp 1920w"
sizes="(max-width: 640px) 640px,
(max-width: 1280px) 1280px,
1920px">
<!-- JPEG 兜底 -->
<img src="/image/photo-1280w.jpg"
alt="Photo"
loading="lazy"
decoding="async"
width="1280" height="720">
</picture>
5.1.4 图片优化效果参考
| 原始格式 | 原始大小 | WebP (q=80) | AVIF (q=50) | 节省比例 |
|---|
| JPEG 2MB | 2,000 KB | 800 KB | 400 KB | 60-80% |
| PNG 500KB | 500 KB | 200 KB | 150 KB | 60-70% |
| PNG 50KB (图标) | 50 KB | 30 KB | 25 KB | 40-50% |
5.2 压缩算法
5.2.1 压缩算法对比
| 算法 | 压缩率 | 压缩速度 | 解压速度 | 浏览器支持 | 说明 |
|---|
| Brotli | 最高 | 慢 | 快 | 96%+ | Google 开发,现代首选 |
| Gzip | 中等 | 快 | 快 | 全部 | 经典方案,兼容性最好 |
| Zstandard | 高 | 快 | 快 | 实验中 | Facebook 开发 |
5.2.2 Brotli 压缩级别
| 级别 | 压缩率 | CPU 消耗 | 适用场景 |
|---|
| 1 | ~70% | 极低 | 实时压缩(边缘) |
| 4 | ~75% | 低 | 一般网站 |
| 6 | ~78% | 中等 | 推荐级别 |
| 9 | ~82% | 高 | 静态资源预压缩 |
| 11 | ~83% | 极高 | 离线压缩(构建时) |
5.2.3 Nginx Brotli 配置
# 动态 Brotli 压缩
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css application/json
application/javascript text/xml
application/xml application/xml+rss
text/javascript image/svg+xml;
# 预压缩静态文件(构建时生成 .br 文件)
brotli_static on;
# Gzip 作为降级方案
gzip on;
gzip_comp_level 6;
gzip_types text/plain text/css application/json
application/javascript text/xml
application/xml text/javascript;
gzip_vary on;
gzip_min_length 256;
5.2.4 压缩效果实测
测试资源: 典型 React SPA 首页
原始大小: 2.4 MB (未压缩)
┌─────────────┬──────────┬──────────┬───────────┐
│ 算法 │ 压缩后 │ 压缩率 │ 压缩耗时 │
├─────────────┼──────────┼──────────┼───────────┤
│ 不压缩 │ 2,400 KB │ 0% │ 0ms │
│ Gzip (6) │ 620 KB │ 74% │ 8ms │
│ Brotli (6) │ 510 KB │ 79% │ 15ms │
│ Brotli (11) │ 460 KB │ 81% │ 120ms │
└─────────────┴──────────┴──────────┴───────────┘
5.3 HTTP/2 与 HTTP/3
5.3.1 HTTP 协议演进
HTTP/1.1 (1997) HTTP/2 (2015) HTTP/3 (2022)
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ 文本协议 │ │ 二进制帧 │ │ 基于 QUIC │
│ 串行请求 │ │ 多路复用 │ │ 多路复用 │
│ 无头部压缩 │ │ HPACK 头部压缩 │ │ QPACK 头部压缩 │
│ 无服务器推送 │ │ 服务器推送 │ │ 服务器推送 │
│ TCP 连接 │ │ TCP 连接 │ │ UDP (QUIC) │
│ 队头阻塞 │ │ TCP 层队头阻塞 │ │ 无队头阻塞 │
└────────────────┘ └────────────────┘ └────────────────┘
5.3.2 HTTP/2 核心优势
| 特性 | HTTP/1.1 | HTTP/2 | 收益 |
|---|
| 多路复用 | 6-8 个 TCP 连接 | 1 连接多流 | 消除队头阻塞 |
| 头部压缩 | 无(每次全量) | HPACK 静/动态表 | 减少 30-50% 头部 |
| 二进制帧 | 文本解析 | 二进制解析 | 更高效 |
| 服务器推送 | 不支持 | Push 资源到客户端 | 减少往返 |
| 流优先级 | 无 | 权重 + 依赖树 | 关键资源优先 |
5.3.3 Nginx HTTP/2/3 配置
# HTTP/2
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# HTTP/3 (QUIC)
listen 443 quic reuseport;
add_header Alt-Svc 'h3=":443"; ma=86400';
# 启用 HTTP/2 Server Push(谨慎使用)
location /index.html {
http2_push /style/main.css;
http2_push /script/app.js;
}
}
5.3.4 HTTP/3 (QUIC) 注意事项
| 优势 | 限制 |
|---|
| 0-RTT 连接建立 | UDP 可能被部分网络封锁 |
| 连接迁移(Wi-Fi → 4G) | CPU 消耗略高于 TCP |
| 无 TCP 队头阻塞 | 生态仍在完善 |
| 内置 TLS 1.3 | 需要客户端/CDN 同时支持 |
5.4 预连接与资源提示
5.4.1 Resource Hints
<head>
<!-- DNS 预解析:提前解析域名 -->
<link rel="dns-prefetch" href="//cdn.example.com">
<link rel="dns-prefetch" href="//analytics.example.com">
<!-- 预连接:DNS + TCP + TLS(比 dns-prefetch 更进一步) -->
<link rel="preconnect" href="https://cdn.example.com">
<link rel="preconnect" href="https://api.example.com" crossorigin>
<!-- 预获取:提前获取可能需要的页面 -->
<link rel="prefetch" href="/next-page.html">
<!-- 预加载:当前页面关键资源,必须加载 -->
<link rel="preload" href="/font/main.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/style/critical.css" as="style">
<link rel="preload" href="/image/hero.avif" as="image" type="image/avif">
</head>
5.4.2 Resource Hints 对比
| 指令 | 作用 | 优先级 | 时机 |
|---|
dns-prefetch | 仅 DNS 解析 | 低 | 浏览器空闲时 |
preconnect | DNS + TCP + TLS | 中 | 尽快 |
preload | 当前页面必须资源 | 高 | 立即 |
prefetch | 下一页可能需要的资源 | 最低 | 浏览器空闲时 |
prerender | 预渲染整个页面 | — | 浏览器决定 |
5.4.3 性能影响估算
典型优化效果(以首次访问为例):
无优化:
DNS 解析 → TCP 握手 → TLS 握手 → HTTP 请求 → 响应
50ms 50ms 50ms 10ms 100ms
总计: ~260ms
启用 preconnect:
[DNS+TCP+TLS 已提前完成] → HTTP 请求 → 响应
0ms (预连接完成) 10ms 100ms
总计: ~110ms(节省 ~150ms)
启用 preload (关键 CSS):
[关键 CSS 已提前下载] → 首屏渲染 → 非关键资源异步加载
0ms 首屏快 200-500ms
5.5 TLS 优化
5.5.1 TLS 握手优化
| 技术 | 说明 | 收益 |
|---|
| TLS 1.3 | 1-RTT 握手(TLS 1.2 为 2-RTT) | 减少 1 次往返 |
| 0-RTT | 恢复连接时零往返(配合 TLS 1.3) | 首字节更快 |
| OCSP Stapling | 服务器预取 OCSP 响应 | 减少客户端验证延迟 |
| Session Resumption | 复用 TLS 会话 | 跳过密钥交换 |
| Certificate Compression | 压缩证书链 | 减少握手数据量 |
5.5.2 Nginx TLS 优化配置
server {
# TLS 1.3 + 0-RTT
ssl_protocols TLSv1.2 TLSv1.3;
ssl_early_data on; # 0-RTT
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/ssl/certs/ca-chain.crt;
resolver 8.8.8.8 8.8.4.4 valid=300s;
# Session 复用
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets on;
# 现代密码套件
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
# ECDH 曲线
ssl_ecdh_curve X25519:secp384r1:secp256r1;
}
5.6 边缘计算优化
5.6.1 边缘计算场景
| 场景 | 技术 | 说明 |
|---|
| A/B 测试 | Cookie 注入 + 重写 | 边缘分流,无需回源 |
| URL 重写 | 边缘路由规则 | 减少回源 |
| 认证鉴权 | JWT 验证 | 边缘校验 Token |
| 个性化 | 边缘渲染 | ESI / Edge SSR |
| API 聚合 | 边缘组合多 API | 减少客户端请求数 |
| 地理限制 | GeoIP + 重定向 | 边缘判断地理位置 |
5.6.2 Cloudflare Workers 示例
// 边缘 JWT 验证示例
export default {
async fetch(request) {
const url = new URL(request.url);
// 不需要认证的路径
const publicPaths = ['/login', '/register', '/health'];
if (publicPaths.includes(url.pathname)) {
return fetch(request);
}
// 验证 JWT
const token = request.headers.get('Authorization')?.replace('Bearer ', '');
if (!token) {
return new Response(JSON.stringify({ error: 'Unauthorized' }), {
status: 401,
headers: { 'Content-Type': 'application/json' }
});
}
try {
const payload = await verifyJWT(token);
// 将用户信息添加到请求头,传递给源站
const modifiedRequest = new Request(request, {
headers: {
...Object.fromEntries(request.headers),
'X-User-Id': payload.sub,
'X-User-Role': payload.role,
}
});
return fetch(modifiedRequest);
} catch (e) {
return new Response(JSON.stringify({ error: 'Invalid token' }), {
status: 403,
headers: { 'Content-Type': 'application/json' }
});
}
}
}
5.7 性能监控指标
5.7.1 核心 Web 指标 (Core Web Vitals)
| 指标 | 英文全称 | 良好阈值 | 衡量维度 |
|---|
| LCP | Largest Contentful Paint | < 2.5s | 加载速度 |
| INP | Interaction to Next Paint | < 200ms | 交互响应 |
| CLS | Cumulative Layout Shift | < 0.1 | 视觉稳定性 |
| TTFB | Time to First Byte | < 800ms | 服务器响应 |
| FCP | First Contentful Paint | < 1.8s | 首次渲染 |
5.7.2 CDN 层面监控
| 指标 | 说明 | 目标值 |
|---|
| Cache Hit Ratio | 缓存命中率 | > 85% |
| Edge Latency | 边缘处理延迟 | < 10ms |
| Origin Latency | 回源延迟 | < 200ms |
| Bandwidth Saved | 带宽节省比例 | > 70% |
| Error Rate | 5xx 错误率 | < 0.1% |
5.8 注意事项
⚠️ 0-RTT 重放攻击:TLS 1.3 的 0-RTT 数据可被重放,不应用于非幂等请求(如 POST、支付)。
⚠️ HTTP/2 Server Push:已被 Chrome 移除支持,建议改用 103 Early Hints。
⚠️ Brotli 动态压缩:级别 10-11 的 CPU 消耗极高,仅用于构建时预压缩,不适合实时压缩。
⚠️ 图片格式兼容:AVIF 虽压缩率最高,但旧浏览器不支持,务必提供 WebP/JPEG 兜底。
5.9 扩展阅读
本章小结
| 主题 | 核心要点 |
|---|
| 图片优化 | WebP/AVIF 格式优先 + 响应式尺寸 |
| 压缩 | Brotli 6 级动态压缩,11 级静态预压缩 |
| HTTP/2+ | 多路复用 + 头部压缩 + TLS 1.3 |
| 预连接 | preconnect/preload 减少关键路径延迟 |
| 边缘计算 | 在边缘处理认证、路由、个性化 |
下一章:第06章 WAF 基础原理 →