優化 CDN 伺服器快取

因動態內容分類導致的快取未套用現象

最近在分析遊戲伺服器的 API 回應速度時,發現與靜態檔案不同,JSON 資料並未被快取。原因是根據 Cloudflare 的預設政策,HTML 或 JSON 等文字型資料會被歸類為動態內容。 回應標頭中的 CF-Cache-Status: DYNAMIC 狀態,意味著使用者的請求繞過了 CDN 直接連線至來源伺服器 (Origin Server),這最終會加重來源伺服器的負載。

https://developers.cloudflare.com/cache/concepts/default-cache-behavior Default cached file extensions "Cloudflare only caches based on file extension and not by MIME type. The Cloudflare CDN does not cache HTML or JSON by default. Additionally, by default Cloudflare caches a website's robots.txt."

sequenceDiagram participant U as 客戶端 participant CF as Cloudflare Edge participant O as 來源伺服器 Note over CF: 預設政策:不支援 JSON 快取 (DYNAMIC) U->>CF: GET /char.json 請求 CF->>O: 請求繞過 (Bypass) O-->>CF: 回傳 JSON 資料 CF-->>U: 回應 JSON 資料 (Cache-Status: DYNAMIC)

第一階段方案:利用 Cache Rules 導入強制快取

靜態資源 (CSS, JS) 容易透過檔名雜湊 (Hash) 進行版本管理 (Cache Busting),但 API 端點作為資源的唯一識別碼,其 URL 必須固定,因此難以採用變更檔名的方式。

Cache Busting 強制使用者瀏覽器下載最新版本檔案的方法

為了解決上述問題,第一步是利用 Cloudflare 的 Cache Rules 設定。這能針對具有特定副檔名 (*.json) 的請求強制套用 Edge 快取 TTL,從而減少對來源伺服器的請求頻率。

  • s-maxage (Edge TTL):中繼伺服器的快取有效時間
  • max-age (Browser TTL):使用者瀏覽器的快取有效時間

權衡 (Trade-off) - 資料一致性問題

然而,設定較長的 TTL 必然會伴隨著資料新鮮度下降的副作用。即使因為遊戲平衡調整等原因修改了原始資料,只要基於唯一 ID 的 URL 結構維持不變,CDN 和瀏覽器就無法察覺檔案的變更。這會導致在預設的長 s-maxage 期間內,持續向使用者傳送過期 (Stale) 資料,進而引發服務營運上致命的資訊不一致問題。

第二階段方案:自動化的 Cache Purge 策略

為了從根本上解決上述問題,將快取刪除邏輯整合至部署管線 (Deployment Pipeline) 中。

sequenceDiagram autonumber actor User as 客戶端 participant CF_Edge as CDN participant O as 儲存空間 participant GA as 來源伺服器 actor Dev as 開發者 rect rgba(235, 197, 145, 0.1) CF_Edge-->>User: GET /char.json Dev->>GA: 版本更新 activate GA GA->>O: 部署最新版本 GA->>CF_Edge: 呼叫 purge_cache API GA->>User: 傳送訊號 deactivate GA end rect rgba(82, 129, 172, 0.1) User->>CF_Edge: GET /char.json CF_Edge->>O: Revalidate O-->>CF_Edge: 回傳最新資料 CF_Edge-->>User: 回應最新資料 end