动态HTML不能直接套用静态资源策略,因其含用户身份、实时状态等变量,设public缓存会导致用户间内容错乱;需按user_id等关键维度构造缓存key,采用边缘片段缓存并设置短TTL,配合stale-while-revalidate与预热机制防雪崩。

动态HTML缓存为什么不能直接套用静态资源策略
因为动态HTML通常含用户身份、实时状态、个性化推荐等变量,直接设 Cache-Control: public, max-age=3600 会导致不同用户看到彼此的页面——比如A用户登录态被缓存后,B用户请求时直接返回A的首页。
常见错误现象包括:用户看到他人订单、未登录却显示“欢迎XXX”、购物车内容错乱。根源在于CDN边缘节点默认按URL路径缓存,不区分 Cookie、Authorization 或查询参数语义。
- 必须显式配置缓存键(cache key)包含关键上下文,例如把
user_id或session_id哈希后纳入key前缀 - 对含敏感字段的请求(如带
access_token的API),应禁用缓存或仅缓存无状态片段 - 避免使用
Vary: Cookie全量拆分缓存——它会极大膨胀缓存体积,命中率骤降
如何在CDN上安全缓存动态HTML片段
整页缓存风险高,但页面中大量区域其实是可复用的:用户头像栏、商品分类导航、热门榜单。这些适合做「边缘片段缓存」(Edge Fragment Caching),即只缓存HTML中某一块,其余部分由源站拼接或JS动态注入。
以Cloudflare Workers或Akamai EdgeWorkers为例,典型流程是:
立即学习“前端免费学习笔记(深入)”;
if (request.url.includes('/profile')) {
const userId = new URL(request.url).searchParams.get('id');
const cacheKey = `profile_${userId}`;
const cached = await CACHE.get(cacheKey);
if (cached) return new Response(cached, { headers: { 'Content-Type': 'text/html' } });
const html = await fetch(`https://origin.example.com/api/profile?uid=${userId}`);
const body = await html.text();
await CACHE.put(cacheKey, body, { expirationTtl: 60 });
return new Response(body, { headers: { 'Content-Type': 'text/html' } });
}- 缓存key必须唯一标识该片段的业务上下文,
user_id比session_id更稳定(后者可能频繁刷新) - TTL设为60秒而非数小时——动态内容新鲜度优先于命中率,尤其涉及库存、价格等字段
- 务必检查源站响应头是否含
Set-Cookie,若存在需剥离后再缓存,否则污染边缘节点
边缘计算中PHP逻辑迁移的现实约束
不是所有PHP代码都能直接扔到边缘节点跑。当前主流CDN边缘运行时(如Cloudflare Workers、Fastly Compute@Edge)不支持原生PHP执行环境,只能用JavaScript/Wasm重写轻量逻辑。
所以所谓“边缘PHP缓存”,本质是两层协作:
- 边缘节点处理缓存读写、简单条件判断(如
if (country === 'CN') {...})、HTTP头改写 - 源站保留完整PHP栈,只在缓存未命中时触发,且应剥离渲染逻辑,改用JSON API提供结构化数据
- 若坚持用PHP生成HTML,需通过Bref或AWS Lambda@Edge打包为容器镜像部署,但冷启动延迟和内存限制(通常≤300MB)会抵消边缘优势
真正高效的路径是:源站输出纯数据 → 边缘节点用JS模板(如LightningFS + Mustache)合成HTML → 缓存合成结果。
缓存失效时如何避免雪崩式回源
当某个热门动态HTML片段(如首页活动Banner)缓存集体过期,瞬间所有请求穿透到源站,极易打垮PHP-FPM进程或数据库连接池。
必须组合使用三种机制:
-
stale-while-revalidate:CDN响应过期内容的同时异步刷新,用户无感知 - 随机化TTL:对同一类请求设置
ttl = base_ttl + Math.random() * 10,打散过期时间点 - 预热机制:在业务低峰期(如凌晨2点)主动触发边缘缓存填充,而非全靠用户请求驱动
最容易被忽略的是预热的触发条件——不能只依赖定时任务,而应监听上游变更事件(如CMS发布新活动页时,立即调用CDN API刷新对应key前缀)。



















