FurCDN 文檔

快取深度指南

從原理到實踐,把 FurCDN 快取調到極致;附 JSON 模式與批量匯入匯出。

從原理到實踐,把 FurCDN 快取調到極致。

TL;DR 三條黃金原則:

  1. 靜態資源設長 TTL + 配合版本號,讓使用者永遠拿快取
  2. HTML 設短 TTL,兼顧更新即時性
  3. API 不快取(TTL=0),動態內容必須回源

〇、JSON 模式 & 批量 JSON

跟 WAF 對齊,每條緩存規則的「新增 / 編輯」對話框增加 JSON 模式 Tab; 頁面頂部「自訂緩存規則」區段右上角新增 批量 JSON 按鈕。

JSON 模式(單規則)

儀表板 > 域名 > 編輯 > 緩存,點「自訂緩存規則」區段右上角 新增 / 任一條規則的 編輯 鉛筆。對話框頂端的 Tab:

  • 表單:可視化點按填欄位。
  • JSON 模式:直接編輯整條規則 JSON。

切到 JSON 後修改、儲存:存的是 JSON 內容。 切回表單時若 JSON 解析失敗會停在 JSON tab 顯示錯誤,表單內容不會被覆蓋

批量 JSON 匯入 / 匯出

按頁面上的 批量 JSON:

  • 匯出:所有「自訂」緩存規則(預設規則不匯出)序列化成 JSON 陣列,可一鍵複製。
  • 匯入:貼入 JSON 陣列,逐條 POST 新增,不覆蓋既有規則。
    • 與既有 (matchType, matchValue) 完全相同 → 後端回 409 拒絕,計入失敗數
    • 部分失敗會顯示失敗清單,成功的會留下

沒有「條數上限」(WAF 才有 10 條限制),你可以一次匯一打規則進去。


一、規則結構(完整 Schema)

每條緩存規則:

{
  "name": "規則顯示名(必填,≤100 字)",
  "matchType": "extension",
  "matchValue": "jpg,png,webp,css,js",
  "ttl": 604800,
  "cacheControl": "public, max-age=604800, immutable",
  "priority": 10,
  "enabled": true
}

欄位逐項

欄位型別必填預設說明
namestring規則名(≤100 字)
matchTypeenum"extension"extension / path / contentType / all
matchValuestringmatchType≠all 必填匹配值,語意依 matchType 而定(≤500 字)
ttlint 0–315360000秒。0 = 不快取;最大 10 年
cacheControlstringnull自訂回應的 Cache-Control,覆寫源站;留空 = 透傳源站(≤200 字)
priorityint ≥010數字小的優先匹配
enabledbooltruefalse 視為規則不存在

matchType × matchValue

matchTypematchValue 格式範例
extension副檔名清單,逗號分隔(可帶 . 也可不帶)jpg,png,webp / .jpg,.png
path路徑前綴或含 * 萬用/static/ / /api/v2/*
contentType回應 Content-Type 字首萬用image/* / application/json
all(不需 matchValue)命中該域名所有請求

extension 取 URL 路徑最後一個 . 之後的部分(不含 query)。如 /img/cat.jpg?v=2 → 副檔名 jpg

後端去重

同一域名下 (matchType, matchValue) 完全相同會被拒(回 409)。 要對同一目標有不同行為,改 priority 是錯的做法 — 應該用 path + 更精準的萬用值。


二、兩級快取原理

L1:記憶體(In-Memory)

  • 小檔(<8 MiB)優先存記憶體
  • LRU 淘汰
  • 命中速度 <1ms
  • 節點重啟即清空

L2:磁碟(Disk)

  • 大檔或 L1 miss 時落盤
  • 單域名 / 單節點都有上限
  • 命中速度 ~5ms
  • 重啟保留

命中流程

請求進來

WAF 評估 (allow/block/challenge)

查 L1 → 命中?→ 是,X-Cache: HIT-L1 直接返回
              ↓ 否
查 L2 → 命中?→ 是,X-Cache: HIT-L2 + 寫入 L1 → 返回
              ↓ 否
回源 → X-Cache: MISS,寫 L1+L2 → 返回

Response Headers

Header含義
X-Cache: HIT-L1命中記憶體
X-Cache: HIT-L2命中磁碟
X-Cache: MISS未命中,剛從源站回
X-Cache: BYPASS命中但配置不快取(TTL=0)
X-Cache-Node: <name>哪個節點服務了這個請求
X-Cache-Age: <秒>已快取多久
X-Cache-Key: <hash>本次的快取鍵 hash(debug 用)

三、預設規則

新建域名時自動產生若干條 isDefault: true 規則,典型為:

規則matchTypematchValueTTL用途
靜態資源extensionjpg,jpeg,png,gif,webp,svg,ico,css,js,woff,woff2,ttf,eot,mp4,webm,mp37 天長 TTL
HTML 頁面extensionhtml,htm5 分鐘兼顧更新即時性
API 不快取path/api/0 秒動態 API 必須回源
  • 預設規則可開關但不會被批量匯出
  • 至少保留「API 不快取」,否則動態內容會被誤快取。

四、快取鍵設定(域名級)

每條規則決定 是否快取與快取多久,快取鍵組成則是域名級設定。

預設快取鍵

SHA256(method + host + uri + query + cacheKeyHeaders 們的值)

ignoreQueryString

開啟後 query 不入鍵,例如版本號 ?v=20240101 對 CDN 等同同一份。

URL預設ignoreQueryString=true
/pagekey Akey A
/page?v=1key Bkey A
/page?v=2key Ckey A

反例:搜尋頁 /search?q=apple/search?q=banana 結果不同,不能忽略 query。

cacheKeyHeaders

陣列,加入快取鍵的 HTTP header 名稱:

["Accept-Language", "X-Device-Type"]

效果:不同 header 值快取為獨立副本

最佳場景:多語言網站根據 Accept-Language 返回不同語言。

請求快取鍵
/page + Accept-Language: zh-TWkey_zhTW
/page + Accept-Language: en-USkey_enUS

快取爆炸警告

場景後果
cacheKeyHeadersUser-AgentUA 變化萬千 → 每個 UA 一份 → 快取空間爆炸
cacheKeyHeadersCookie每個 session 一份 → 同樣爆炸
不設 ignoreQueryString 而源站亂帶時間戳 query每次請求 key 都不同 → 永遠 MISS

Header 名稱大小寫不敏感,但值大小寫敏感


五、源站 Cache-Control 互動

源站回的 header 影響 FurCDN 怎麼快取:

源站 Cache-ControlFurCDN 行為
public, max-age=3600快取 1 小時
private不快取(個人資料,不應在 CDN)
no-store不快取
no-cache允許快取但每次回源 revalidate(目前簡化:仍按 TTL 快取)
s-maxage=600, max-age=60CDN 快 10 分鐘(s-maxage 給共享快取)

規則 vs 源站 優先級

1. 規則 ttl > 0   → 強制用規則的 TTL,完全覆寫源站
2. 規則 ttl = 0   → 強制不快取(BYPASS)
3. 沒規則匹配     → 看域名 cacheTime(預設快取時間)
4. cacheTime = 0  → 看源站 Cache-Control;源站沒設則不快取

實踐:寫規則時要意識到完全覆寫源站


六、立即刷新

域名編輯 > 「立即刷新快取」按鈕

  • master 透過 SSE 即時廣播給所有服務該域名的節點
  • 每個節點同時清 L1 + L2 該域名所有 entry
  • 通常 <1 秒 生效
  • 全域名 purge,不能精確到單一 URL
  • API 等價:POST /api/v1/domains/{id}/purge

不要過度刷新。每次刷新後該域名所有節點全部 MISS,源站瞬時負載 ↑。 真要頻繁更新建議改 TTL 短一點,而不是手動刷新。


七、可直接貼進批量匯入的成套配方

7.1 靜態網站

[
  { "name": "HTML 短 TTL", "matchType": "extension", "matchValue": "html,htm", "ttl": 300, "priority": 10, "enabled": true },
  { "name": "JS/CSS 30 天", "matchType": "extension", "matchValue": "js,css", "ttl": 2592000, "cacheControl": "public, max-age=2592000, immutable", "priority": 10, "enabled": true },
  { "name": "圖片 30 天", "matchType": "extension", "matchValue": "jpg,jpeg,png,webp,svg,ico,gif", "ttl": 2592000, "priority": 10, "enabled": true },
  { "name": "字體 1 年", "matchType": "extension", "matchValue": "woff,woff2,ttf,eot,otf", "ttl": 31536000, "cacheControl": "public, max-age=31536000, immutable", "priority": 10, "enabled": true }
]

配合「域名設定 > 忽略 Query String」即可用 ?v=hash 隨時破快取。

7.2 SPA(Single Page App)

[
  { "name": "index.html 短 TTL", "matchType": "path", "matchValue": "/", "ttl": 300, "priority": 10, "enabled": true },
  { "name": "構建產物長 TTL", "matchType": "path", "matchValue": "/static/", "ttl": 2592000, "priority": 10, "enabled": true },
  { "name": "API 不快取", "matchType": "path", "matchValue": "/api/", "ttl": 0, "priority": 5, "enabled": true }
]

SPA 的 index.html 必須短 TTL,構建產物用 hash filename 可放長 TTL。

7.3 WordPress / 動態 CMS

[
  { "name": "wp-admin 不快取", "matchType": "path", "matchValue": "/wp-admin/", "ttl": 0, "priority": 1, "enabled": true },
  { "name": "wp-login 不快取", "matchType": "path", "matchValue": "/wp-login.php", "ttl": 0, "priority": 1, "enabled": true },
  { "name": "PHP 不快取", "matchType": "extension", "matchValue": "php", "ttl": 0, "priority": 5, "enabled": true },
  { "name": "圖片 7 天", "matchType": "extension", "matchValue": "jpg,jpeg,png,webp,svg,ico,gif", "ttl": 604800, "priority": 10, "enabled": true },
  { "name": "CSS/JS 1 天", "matchType": "extension", "matchValue": "css,js", "ttl": 86400, "priority": 10, "enabled": true }
]

7.4 OSS / 對象儲存圖床

[
  { "name": "全部資源長 TTL", "matchType": "all", "ttl": 2592000, "cacheControl": "public, max-age=2592000, immutable", "priority": 10, "enabled": true }
]

OSS 內容不變,極長 TTL。配合 ignoreQueryString=true + presigned URL,流量可以做到 99% 命中率。

7.5 即時新聞

[
  { "name": "首頁 1 分鐘", "matchType": "path", "matchValue": "/", "ttl": 60, "priority": 10, "enabled": true },
  { "name": "文章 10 分鐘", "matchType": "path", "matchValue": "/news/", "ttl": 600, "priority": 10, "enabled": true },
  { "name": "圖片 1 天", "matchType": "extension", "matchValue": "jpg,png,webp", "ttl": 86400, "priority": 10, "enabled": true },
  { "name": "API 不快取", "matchType": "path", "matchValue": "/api/", "ttl": 0, "priority": 5, "enabled": true }
]

兼顧即時性 + 性能,配合「立即刷新」應對重大新聞。

7.6 多語言網站

[
  { "name": "HTML 5 分鐘", "matchType": "extension", "matchValue": "html,htm", "ttl": 300, "priority": 10, "enabled": true }
]

外加域名級設定:cacheKeyHeaders=["Accept-Language"],每種語言獨立快取。

7.7 圖片 / 影片下載類

[
  { "name": "影片不上記憶體", "matchType": "extension", "matchValue": "mp4,webm,mov,mkv", "ttl": 86400, "cacheControl": "public, max-age=86400", "priority": 10, "enabled": true },
  { "name": "音訊 1 週", "matchType": "extension", "matchValue": "mp3,m4a,ogg,flac", "ttl": 604800, "priority": 10, "enabled": true }
]

大檔(>8 MiB)會自動只進 L2 不進 L1,規則不用特別寫。

7.8 規則精修:特定文件覆蓋通用規則

/static/v1/critical.js 走 1 小時 TTL 而其他 /static/*.js 走 30 天? 用更小的 priority 覆蓋:

[
  { "name": "Critical JS 短 TTL", "matchType": "path", "matchValue": "/static/v1/critical.js", "ttl": 3600, "priority": 5, "enabled": true },
  { "name": "其他 JS 長 TTL", "matchType": "extension", "matchValue": "js", "ttl": 2592000, "priority": 10, "enabled": true }
]

八、JSON 模式常見錯誤

錯誤訊息原因
JSON 格式錯誤: Unexpected token多了/少了逗號、用了 trailing comma、雙引號漏掉
頂層必須是規則物件單規則編輯時頂層必須是 {...};陣列請走批量匯入
匹配類型無效matchType 不在 extension / path / contentType / all 之中
匹配值必填matchType 不是 allmatchValue 必須有值
TTL 不合法必須是 0–315360000 的整數(10 年上限)
已存在相同匹配規則後端去重:同 (matchType, matchValue) 已有規則;改 matchValue 或刪舊的

九、故障排查

永遠 MISS,沒命中

  1. 域名 cacheEnabled 開了嗎?域名編輯 > 緩存 > 緩存總開關
  2. 規則 enabled=true 嗎?且 priority 沒被前面的 ttl=0 規則蓋掉?
  3. 源站 Cache-Control: no-store / private 而你沒寫規則覆寫?寫規則 ttl > 0 強制
  4. query 變化:沒設 ignoreQueryString 而每次 query 都不同
  5. Vary: *:源站回了 Vary: * 等同不可快取

快取了不該快取的內容

  1. 該路徑有規則 ttl > 0 嗎?改成 0
  2. 登入態頁面應該有 Cache-Control: private,源站沒設就加規則 ttl=0
  3. 緊急刷快取:點「立即刷新」

多語言頁面只看到一種語言

  • 沒設 cacheKeyHeaders=["Accept-Language"]
  • 第一個訪問的人是哪種語言,後面所有人都看到那種

改了源站但 CDN 還是舊內容

  • TTL 還沒到 → 等 / 點「立即刷新」
  • 規則 cacheControl 設了長 max-age 也覆寫到 response,用戶端瀏覽器也快取了
  • 改規則的 cacheControl,新請求才會拿短 max-age;舊請求等舊 max-age 過期

開了 ignoreQueryString 後 SEO 受影響?

  • 不會。SEO 看的是源站 + URL 結構,跟 CDN 快取鍵無關
  • 只要源站對相同 query 永遠返回同樣內容,ignoreQueryString 安全

十、進階:Cache-Control 透傳

如果你的源站本身就有完整的快取策略(例如 Cache-Control: public, max-age=86400, s-maxage=604800),不需要寫 FurCDN 規則:

  1. 域名 cacheEnabled=true
  2. 域名 cacheTime 設一個合理 fallback(如 60 秒)
  3. 不寫任何 cacheRule(或只寫 path=/api/ ttl=0 排除 API)

FurCDN 會直接讀源站的 s-maxage(優先) / max-age,完整尊重源站策略。

優點:單一事實來源,改源站 header 即可即時生效,不需動 CDN 設定。


還是搞不定?訪問日誌裡每筆請求都有 cache_status 欄位,點開看細節:命中哪條規則、用了什麼快取鍵、源站 header 是什麼。

© 2023-2026 SLOWSPEED NETWORK LLC. 版權所有

langya.io 驅動

On this page