Cloudflare 边缘缓存配置 Runbook(配合源站 Cache-Control 改造)
前置:scripts/cms-server.cjs 已按路径分类下发 Cache-Control(见下方「源站策略对照」)。
适用域名:eastaiai.com(nginx 直连,需先接入 CF 代理)、exploreai.fun(已 CF 代理)。
配置完成后用「验收」一节验证,全部通过才算完成。
0. 接入检查(eastaiai.com 专属,先做)
- Cloudflare 添加站点 → DNS 记录指向源站(82.156.40.94 或当前源站 IP),橙色云(Proxied)必须开。
- SSL/TLS 模式:
Full (strict)。 - 当前 exploreai.fun 根路径返回 404:先确认其源站/回源规则是否正确指向本应用,否则后面全部无效。
1. Speed → Optimization
| 项 | 值 |
|---|---|
| Brotli | Auto(已验证 br 生效,保持) |
| HTTP/3 | On |
| Early Hints (103) | On |
| Auto Minify | JS / CSS 开;HTML 建议关(本应用 HTML 由服务端渲染,minify 可能破坏内联脚本) |
| Tiered Cache | On(免费,减少 L1 回源) |
2. Caching → Configuration
| 项 | 值 | 说明 |
|---|---|---|
| Browser Cache TTL | Override origin,4 小时 | 减少浏览器重复请求 |
| Respect origin headers | 保持默认 | 源站 no-store 的 API/后台不会因此被缓存 |
| Eligible status codes | 200, 301, 302, 308, 404(不要勾 5xx) | 避免缓存 5xx |
| Serve stale | On(1 小时) | 回源故障时吐旧内容,配合 stale-while-revalidate |
3. Caching → Cache Rules(核心)
规则 1 — 公开页强制可缓存(创建顺序第一,Priority 1)
- Expression:
``
(http.host in {"eastaiai.com", "www.eastaiai.com", "exploreai.fun", "www.exploreai.fun"})
and (
http.request.uri.path eq "/"
or starts_with(http.request.uri.path, "/article/")
or starts_with(http.request.uri.path, "/list/")
or starts_with(http.request.uri.path, "/docs-static/")
or starts_with(http.request.uri.path, "/tech-docs")
or starts_with(http.request.uri.path, "/digital-employee")
or starts_with(http.request.uri.path, "/bossagents-demo")
or http.request.uri.path in {"/plan", "/products", "/cases", "/training", "/open-platform", "/download", "/buy", "/huzeng", "/assets", "/partner", "/feedback", "/articles", "/logo.png", "/favicon.ico"}
)
and not (http.request.uri.query contains "profile=")
and not (http.request.uri.query contains "preview=")
and not (http.request.uri.query contains "token=")
`
注意:query contains "profile=" 这类子串判断是保守兜底;白标档案切换是个性化内容,必须不缓存(源站已同步处理,双保险)。
- Actions:
- Cache eligibility → Eligible for cache(可覆盖源站禁止缓存的头)
- Edge TTL → 10 分钟(与源站 s-maxage 对齐;文章 s-maxage=3600,边缘取 10 分钟更稳)
- Serve stale → On
规则 2 — 静态资源长缓存(Priority 2)
- Expression:
`
(http.request.uri.path matches "(?i)\\.(png|jpg|jpeg|webp|gif|svg|ico|woff2?|ttf|mp4)$")
and not (http.request.uri.path contains "/admin")
`
- Actions:Cache eligibility → Eligible;Edge TTL → 30 天;Cache deprecation rules:对含 6+ 位哈希文件名的可加 1 年。
不要Create「全站 Eligible」的规则 —— API、/admin/、/api/ 必须继续 no-store(源站已下发,CF 默认遵循)。
4. Rules → Transform Rules → Modify Response Header(双保险)
规则 1 — 公开页 Cache-Control 纠正(Priority 1,Apply to:Incoming requests,同规则 3 的 path 表达式)
- Operation:Set;Field:Cache-Control
;Value:
public, max-age=60, s-maxage=600, stale-while-revalidate=86400
(文章/列表/文档路径若想用 1 小时边缘 TTL,可再拆一条规则设 public, max-age=300, s-maxage=3600, stale-while-revalidate=86400)
规则 2 — 保护性头(Priority 2,path 匹配 /api/ 或 /admin)
- Operation:Set;Field:Cache-Control
;Value:no-store, private - Operation:Set;Field:X-Robots-Tag
;Value:noindex, nofollow(/admin 与 /api 管理端不索引)
5. Security → WAF → Custom Rules(Bot 放行,GEO 收益)
一条 Allow 规则(Priority 建议靠前,Action = Skip,跳过所有后续 WAF 规则):
- Expression:
`
(http.user_agent contains "ChatGPT-User")
or (http.user_agent contains "GPTBot")
or (http.user_agent contains "Claude-User")
or (http.user_agent contains "ClaudeBot")
or (http.user_agent contains "PerplexityBot")
or (http.user_agent contains "Google-Extended")
or (http.user_agent contains "Applebot")
or (http.user_agent contains "Googlebot")
or (http.user_agent contains "Bingbot")
`
- 说明:源站 robots.txt 已显式 Allow 上述爬虫(handleRobotsTxt
),CF 侧放行后两边一致。 - 验收:上线后用 https://eastaiai.com/robots.txt
+ 搜索引擎"site:"与 AI 对话引用验证;CF 面板 Analytics → Bots 可见对应爬虫流量计数 > 0。
6. 部署后缓存失效(必须写进发布流程)
发布新文章/改模板后调用 Purge 按 URL,禁止 Purge Everything:
- POST https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache
- Body:{"files": ["https://eastaiai.com/article/123", "https://eastaiai.com/articles"]}
(单批 ≤ 30 个 URL) - Token 放服务器 .env
(CF_ZONE_ID/CF_API_TOKEN,权限:Zone → Cache → Purge),不要提交进仓库。
7. 源站策略对照(cms-server.cjs 已实现)
| 路径 | 源站 Cache-Control | 边缘 |
|---|---|---|
| /、/logo.png、/favicon.ico | public, max-age=60, s-maxage=600, stale-while-revalidate=86400 | HIT |
| 营销页(/plan /products /cases …)与文章/列表/文档 | public, max-age=300, s-maxage=3600, stale-while-revalidate=86400 | HIT |
| /robots.txt、/llms.txt | public, max-age=3600 | HIT |
| /sitemap.xml | public, max-age=60 | HIT |
| /docs-static/*、public/ 下图片 | public, max-age=604800(图片 30 天+7 天 stale) | HIT |
| 带指纹静态文件(*.a1b2c3.js) | public, max-age=31536000, immutable | HIT |
| 只读公开 API(/api/columns /api/company /api/site /api/export/ …) | public, max-age=30 | HIT |
| 其余 /api/、/admin/、/cms、/customer-site | no-store(, private) | 不缓存 |
| ?profile= / ?preview= / ?token= 任意页 | no-store | 不缓存(白标防串号) |
| 4xx/5xx | no-store | 不缓存 |
| SSE 流(/api/bossagents-sse) | no-cache | 不缓存 |
8. 验收(全部通过才算完成)
`bash
A. 边缘缓存:第 1 次 MISS/DYNAMIC,第 2 次必须 HIT
curl -sI https://eastaiai.com/ | grep -iE "cache-control|cf-cache-status|age"
curl -sI https://eastaiai.com/ | grep -iE "cache-control|cf-cache-status|age"
期望: Cache-Control: public, max-age=60, s-maxage=600... / cf-cache-status: HIT / age 递增
B. 安全门禁:公开页无 Set-Cookie(改造前后都要确认)
curl -sI https://eastaiai.com/ | grep -i set-cookie && echo "❌ 有 Cookie" || echo "✅ 无 Cookie"
C. 白标不泄漏:两个档案请求头必须 no-store
curl -sI "https://eastaiai.com/?profile=customer-demo" | grep -i cache-control # 期望 no-store
D. 管理端不缓存不索引
curl -sI https://eastaiai.com/admin/columns | grep -iE "cache-control|x-robots-tag"
E. 4xx 不缓存
curl -sI https://eastaiai.com/nonexistent-xyz | grep -iE "HTTP|cache-control" # 期望 no-store
F. 指标(1~3 天后看 CF 面板)
缓存命中率 > 70%;海外边缘 TTFB < 400ms;WebPageTest(US-East/Frankfurt/Singapore/Mumbai) LCP < 2.5s
`
9. 回滚
- 源站:把 edgeCacheControl()
默认值改回'no-store'(或 revert 该 commit)→ 立即恢复原状。 - CF:禁用第 3、4 节的 Cache Rule / Transform Rule → 立即恢复原状。
- 两步独立,可分别回滚,不需要联动。
10. 单机部署加固(本周最低要求,另开任务)
- systemd 守护(Restart=always
)+/health` 健康检查接入监控 - MySQL 每日自动备份 + 一次可恢复演练
- CPU/内存/磁盘/5xx 率告警
- 中期:数据库迁托管实例,与应用分离(与「偶发 404」相关)
BossAgents