CDN 接入与 HTTP/2、HTTP/3
CDN 干的事很朴素:把你的静态资源复制到离用户最近的节点,用户就近取,源站只承受回源流量。它对「用户分布广、静态资源多、经不起流量峰值」的站点收益极大,对「用户就在一个城市、全是动态接口」的站点可能只是多了一层排查难度。本章讲接入流程、缓存规则、真实 IP 还原与 HTTP/2、HTTP/3 的现状。
要解决的问题
- 我这个站到底需不需要 CDN?
- 接 CDN 要做哪几步,源站要不要改?
- CDN 的缓存规则怎么设计,忽略查询串有什么风险?
- 接上 CDN 后日志里全是 CDN 节点 IP,风控和统计全乱了?
- CDN 侧证书和源站证书是什么关系?
- HTTP/2、HTTP/3 该不该开,条件是什么?
- 回源费用怎么控?
是否需要 CDN
| 场景 | 是否需要 | 原因 |
|---|---|---|
| 用户跨省甚至跨国,静态资源多(图片/JS/CSS/下载) | 需要 | 就近分发,首屏与下载速度提升最明显 |
| 营销活动、短视频、直播等流量峰值明显 | 需要 | 边缘吸收峰值,源站不至于被打挂 |
| 有 DDoS/CC 风险,需要清洗与隐藏源站 IP | 需要 | CDN 同时承担防护与 IP 隐藏 |
| 纯动态接口站(后台系统、API 服务) | 基本不需要 | 动态请求无法缓存,回源比例接近 100% |
| 个人工具站、用户主要在一个区域、日 PV 几千 | 通常不需要 | 一台 1~2 核机器 + 合理缓存就够,CDN 反而增加排查成本 |
| 源站带宽与费用已是瓶颈 | 需要,但要算账 | 回源流量、请求数、刷新次数都可能计费 |
「CDN 不是万能」:它不会让你的慢 SQL 变快,也不会让计算密集的接口变快;它只解决「静态内容离用户远」和「流量峰值」两个问题。接入前先问一句:我的瓶颈真的是分发距离吗?
接入流程与源站配置
① 在 CDN 控制台添加加速域名(需要该域名已 ICP 备案,国内节点必须)
② DNS 处把加速域名 CNAME 到 CDN 分配的地址(不要用 A 记录指源站 IP)
③ 配置回源:回源地址(IP 或域名)、回源端口、回源协议(HTTPS 优先)、回源 Host
④ 配置缓存规则、HTTPS 证书、强制 HTTPS 跳转、HTTP/2 与 HTTP/3 开关
⑤ 源站侧:只允许 CDN 回源网段访问,并还原真实客户端 IP
⑥ 验证:curl 看响应头是否出现 CDN 节点标识,再对比源站直连的差异
# 源站:还原真实 IP(限流、日志、风控的前提),网段以 CDN 厂商文档为准
set_real_ip_from 100.64.0.0/10;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
server {
listen 443 ssl;
server_name static.example.com;
# 回源鉴权:CDN 配置固定请求头,源站不认就 403
# 更稳的做法是安全组/防火墙只放行 CDN 回源网段,双保险更好
if ($http_x_cdn_token != "replace-with-your-token") { return 403; }
location / { root /srv/www/site; expires 30d; }
location /api/ {
proxy_pass http://app_backend;
add_header Cache-Control "no-store" always; # 动态接口明确告诉 CDN 不要缓存
}
}
缓存规则设计
| 资源 | 路径/后缀 | 边缘缓存时间 | 忽略查询串 | 说明 |
|---|---|---|---|---|
| 带哈希的静态资源 | *.js *.css *.woff2 | 30 天 ~ 1 年 | 可以忽略 | 文件名变即新资源 |
| 图片 | /img/* | 7 ~ 30 天 | 不可忽略 | 同一路径常靠参数区分尺寸/裁剪 |
| HTML | /、*.html | 不缓存,或 1~5 分钟 | 不忽略 | 长缓存会导致发布不生效 |
| 接口 | /api/* | 不缓存 | 不忽略 | 除显式声明的公开只读接口 |
| robots / sitemap | /robots.txt、/sitemap.xml | 1 小时 | 不忽略 | 一天一次抓取足够 |
| 下载/安装包 | /download/* | 7 天 | 不忽略 | 大文件最值得上 CDN |
「忽略查询串」是 CDN 配置里最容易出事的一项:一旦忽略,/img/a.jpg?w=200 与 /img/a.jpg?w=800 会被当成同一个资源,先到哪个就把哪个缓存住,用户看到错尺寸甚至错内容的图片。默认一律不忽略,只有明确由文件名区分内容的资源才忽略。
刷新与预热:刷新(清除边缘缓存)有配额限制且生效需几分钟,发版时只刷 HTML,静态资源靠文件名哈希自然更新。预热是在活动或发布前把热门 URL 主动拉到边缘,避免流量瞬间全部回源造成雪崩——大促前值得做,日常小站意义不大。
HTTPS 与真实 IP
CDN 上其实有两段 TLS:用户 ↔ CDN 节点(用 CDN 侧配置的证书)和 CDN 节点 ↔ 源站(用源站证书或厂商托管证书)。两者互相独立,所以:
| 情况 | 结果 |
|---|---|
| CDN 侧有证书、源站没有 | 用户看到安全锁,但 CDN 到源站是明文 http,仍有被抓包风险 |
| CDN 侧有证书、源站证书过期 | 回源失败,用户看到 502/521 一类错误,且容易误判成 CDN 问题 |
| 两边都开「强制 HTTPS 跳转」 | 可能形成跳转循环,只在一侧跳转即可 |
真实 IP 的取法:CDN 回源时把用户 IP 放在 X-Forwarded-For,源站用 set_real_ip_from + real_ip_header 还原(见上面配置)。不还原的后果是日志统计、Nginx 限流、应用风控全部按 CDN 节点 IP 计算——要么所有用户互相误伤,要么一个都限不住。
HTTP/2 与 HTTP/3 现状
| 特性 | 生效位置 | 开启条件 | 说明 |
|---|---|---|---|
| HTTP/2 | 用户 ↔ CDN(默认开);也可在源站开 | 必须基于 HTTPS;源站 Nginx 需 1.9.5+ | 多路复用、头部压缩,解决应用层队头阻塞(TCP 层仍在) |
| HTTP/3 (QUIC) | 一般只在 CDN 侧开 | CDN 开关 + 客户端支持 + UDP 443 放行 | 基于 UDP,弱网与移动网络提升明显;源站自行开启意义有限 |
| Alt-Svc 头 | CDN 自动下发 | 自动 | 告诉浏览器「这个站也支持 h3」,浏览器后续才会尝试 |
源站自己在 Nginx 上开 HTTP/2 的写法(1.25.1+):
server {
listen 443 ssl;
http2 on; # 旧版写 listen 443 ssl http2;
ssl_certificate /etc/nginx/certs/example.com.fullchain.pem;
ssl_certificate_key /etc/nginx/certs/example.com.key;
}
验证:curl -sI --http2 https://example.com/ 的响应行应显示 HTTP/2。HTTP/3 在命令行验证不方便,用浏览器 DevTools 的 Protocol 列看 h3 更直接。
回源费用控制要点:回源流量按 GB 计费、请求数也可能计费,所以命中率就是钱——把能缓存的都配上缓存、避免忽略查询串造成缓存碎片、发版不要刷全站静态资源、大文件(视频/安装包)改用对象存储 + CDN 而不是从应用服务器回源。
验证方法
# 1) 是否真的走了 CDN:看响应头里的节点标识(不同厂商头名不同)
curl -sI https://static.example.com/ | grep -i -E 'via|x-cache|server|age'
# 2) 连续请求两次,看 Age 是否增长(增长说明命中边缘缓存)
curl -sI https://static.example.com/img/logo.png | grep -i age
# 3) 绕过 CDN 直连源站对比(--resolve 强制解析到源站 IP)
curl -sI --resolve static.example.com:443:47.98.x.x https://static.example.com/ | head -3
# 4) 源站日志里是否是真实用户 IP(配了 real_ip 之后)
tail -5 /var/log/nginx/access.log
# 5) 缓存头是否符合预期
curl -sI https://static.example.com/assets/app.a1b2c3.js | grep -i cache-control
常见坑
| 坑 | 现象 | 做法 |
|---|---|---|
| 忽略查询串 | 图片尺寸/内容错乱 | 默认不忽略 |
| HTML 被边缘长缓存 | 发布后用户仍是旧页面 | HTML 不缓存,只刷 HTML |
| 源站没还原真实 IP | 限流误伤、日志全是 CDN 节点 | set_real_ip_from + real_ip_header |
| 源站仍然对全网开放 | 有人直接打源站 IP 绕过 CDN 与防护 | 安全组只放行 CDN 回源网段 + 回源鉴权 |
| 两侧都开强制跳转 | 跳转循环、请求异常 | 只在一侧配置 |
| 以为开了 CDN 接口就快了 | 动态接口没有任何改善 | 优化 SQL/缓存,CDN 帮不上 |
| 没算回源费用 | 账单远超预期 | 提升命中率、大文件走对象存储 |
| 源站证书过期 | CDN 回源失败,误判为 CDN 故障 | 把源站证书纳入到期监控 |
小结:CDN 只解决「静态内容离用户远」和「流量峰值」两件事,接入前先确认瓶颈真在这;接入的关键动作是「CNAME 接入 → 源站只放行回源网段并还原真实 IP → 按资源类型设计缓存规则 → 只刷 HTML 不刷静态资源」;查询串默认不要忽略,HTTPS 要弄清楚用户侧与回源侧是两套证书;HTTP/2 源站可开、HTTP/3 交给 CDN;最后再强调一次——动态接口密集、用户集中的小站,把缓存头和压缩配好,比接 CDN 更有效。