CloudFront 怎麼決定快取?搞懂 Cache Key、TTL 與 Path Pattern(上)

CloudFront 怎麼決定快取?搞懂 Cache Key、TTL 與 Path Pattern(上)
圖文不符之 - 薄荷島海很藍。CloudFront 設定知識跟海一樣深

第一次打開 CloudFront 的設定頁時,我其實有點混亂。

畫面上會看到 Cache Key、TTL、Path Pattern 這些名詞,但如果你還沒實際踩過 CDN 快取的坑,很難立刻知道它們各自在管什麼。

後來我爬了很多文跟資料才理解,這三個設定其實分別在回答三件事:

  • 這份快取可以保留多久?
  • 哪些請求可以共用同一份快取?
  • 這個請求要套用哪一套規則?

換句話說,CloudFront 的快取行為,很多時候就是由 Path Pattern、Cache Key、TTL 一起決定的。

這篇文章我會用比較直白的方式,整理這三個概念各自的角色,以及它們實際上怎麼影響 CDN 的快取判斷。


實際進到 CloudFront 的 Behaviors 頁面時,會看到一組預設行為,以及對應的快取相關設定。
一開始如果不熟這些欄位,很容易只看到一堆名詞,卻不知道它們分別會影響什麼。也因為這樣,我後來是反過來先搞懂每個設定在決定什麼,再回頭看介面,才比較看得懂。

當我從 Behaviors 頁面點選「建立行為」後,畫面裡又會跑出更多設定。
像是路徑模式、快取政策、原始來源請求政策等等,第一次看到時其實很容易更混亂:欄位變多了,但還是不知道它們彼此的差別是什麼。

例如,當路徑模式填入 /*.js 這類靜態資源路徑時,在快取政策欄位裡,CloudFront 會推薦使用 CachingOptimized

這時候很容易出現另一個疑問:為什麼是這個?它到底適合什麼情境?又是根據什麼判斷的?

也因為這樣,我後來才回頭拆開來看,CloudFront 的快取行為其實主要和 Path Pattern、Cache Key、TTL 這幾個概念有關。

Cache Key 是什麼?

Cache Key 像圖書館的索書號系統:

  • 圖書館找書:
    • 讀者說:「我要《網頁設計入門》這本書」
    • 圖書館員查系統:找到索書號 312.9 4567
    • 用索書號找書:拿著索書號去書架找,312.9 區域的 4567 號位置
  • CloudFront 找檔案:
    • Client 端 (瀏覽器、curl 等) 說:「我要 logo.png 這個檔案」
    • CloudFront 查看 cache key:mywebsite.com/images/logo.png
    • 用 cache key 找檔案:拿著這個 key 去快取裡找對應的檔案

👉 所以 Cache Key 就是「找檔案的依據」,若是 key 不同就會被視為不同的檔案。

預設情況下,Cache Key 包含:

  • 請求的主機名稱 (Host header)(例如:d111111abcdef8.cloudfront.net
  • 請求的 URI 路徑 (不包含 query string)

這代表什麼?

  • CloudFront 是依賴這兩個最基本的資訊來判斷「這是同一個檔案嗎?」「這個檔案有在快取裡嗎?」這樣可以簡單高效就能拿到檔案。
    這就像圖書館的「書名」和「作者」是預設的找書資訊,但如果你想找「某某出版社出版的精裝版」,你就需要更多的資訊了。

為什麼 CloudFront 預設 Cache Key 是兩個?

因為只用 Host + Path 能讓靜態檔案達到最高快取命中率。

設計邏輯:針對靜態檔案優化

  • 最早前 CDN 設計就主要是為了快取靜態檔案(圖片 .jpg, .png、CSS 檔案 .css、JavaScript 檔案 .js),同樣的靜態檔案,對所有使用者來說內容都是一樣的,所以不需要因應 query、header、cookie 去快取多份版本。
    • 例子: yourdomain.com/images/logo.png 不管誰來拿,它永遠是那個 logo.png

為什麼不包含 Query、Header、Cookie?

  • 考量快取「命中率」CloudFront 的目標是盡可能地快取檔案,讓使用者能從最近的節點取得內容,減少延遲。
    • 如果 Cache Key 太複雜: 如果預設把所有的「查詢參數 Query Parameters」、「HTTP 標頭 Headers」都納入 Cache Key,那麼即使是同一個檔案,只要網址上多一個 ?id=1 或是加個 header,CloudFront 就會把它視為完全不同的檔案,並單獨快取一份。
    • 導致的結果:
      • 快取命中率下降: 許多 cache Key 不同的檔案,每次請求可能都得回 Origin 拿一次,因為 CloudFront 覺得它是「新檔案」。

結果: 簡化的 Cache Key(只有 Host + Path)讓靜態檔案快取效率最大化。

💡
關於 CDN 原生用途,可以參考這裡說明 Akamai 研究論文(2010)- Originally, CDNs improved website performance by caching static site content at the edge of the Internet, close to end users, in order to avoid middle mile bottlenecks as much as possible.

Path Pattern 是什麼?——幫不同路徑分類設定規則

Path Pattern 可以針對不同類型的 URL 設定不同的快取策略。

💡
區別:
Path Pattern 決定 哪些 路徑用哪一組快取設定;
Cache Key 決定 同一路徑 有沒有命中快取
Path Pattern 代表意義
/images/*.jpg 對所有圖片設定,可以決定其為同樣的快取政策
*.html 對所有 HTML 設定,可以決定其為同樣的快取政策

這也是為什麼當我們進到行為頁面的時候,是可以用「建立行為」去做更細緻設定的。這樣就能控制不同類型內容的快取行為。
🔗 參考 AWS 文件 Path pattern 說明

TTL 是什麼?

TTL(Time-To-Live)決定 CDN 多久向 Origin 確認檔案是否有更新。 在 TTL 時間內直接回傳快取,不向 Origin 確認。

TTL 就像保存期限的概念

CloudFront 會把檔案存放在最近的「超商」(Edge Location)。TTL(Time-To-Live)就是這份檔案的保存期限:期限內客人(Client 端:瀏覽器、curl 等)來買,店員(Edge Location)直接從貨架拿;期限一到,快取項目會被標記為過期,店員才回總倉(Origin)補貨。

什麼檔案適合設長 TTL?

  • 靜態檔就像罐頭:圖檔、CSS、JavaScript 通常不會變
  • 寫好沒錯就不變動:既然不常變質,適合設很長的保存期限
  • 減少重複請求:長 TTL 讓使用者載入更快、原伺服器更省力

CloudFront 的 CachingOptimized 政策

提供了最適合靜態檔案的 TTL 策略:

  • 長保存期限:TTL 預設 24 小時,最多可到 1 年
  • 只保留單一快取檔案:不將 Query、Cookie、Header 列入 Cache Key
  • 最高命中率:確保同一個 URL 只有一個版本

要更新快取可以怎麼辦?

  • 改檔名(加 fingerprint / hash):例如把 app.js 換成 app-a1b2c3.js。URL 變了,Edge 快取與所有 Client 端(瀏覽器、curl、App)都會把它當成全新檔案。

實際效果 TTL 搭配 CachingOptimized 政策,讓靜態檔案就像放在各地超商的罐頭一樣,客人隨時都能就近快速取得,總倉庫也不用一直出貨。
簡單來說,先理解 TTL 保存期限的概念,再用 CloudFront 的 CachingOptimized 政策來實現快取最佳化!

為什麼 AWS 會在 Path Pattern 推薦 CachingOptimized?

因為大部分網站的靜態資源(圖檔、CSS、JS)都放在特定路徑下(如 /static/*/assets/*),而 CachingOptimized 正是為這類檔案設計的最佳策略。

什麼時候不該用 CachingOptimized?

  • API 回應、動態內容、需要即時更新的檔案

設定 CloudFront 快取時容易混淆的幾個地方

如何驗證 CloudFront 快取設定是否正確?

  • 我們可以實際去網站上看,看有沒有 hit cloudfront。驗證是為了確保快取如預期工作,避免因為設定錯誤而導致的「快取失效」之類的問題
  • 舉例:
# 第一次通常 MISS
curl -I <https://blog.majid.info/js/photoswipe-lightbox.esm.min.js>

# 再跑一次就會 HIT
curl -I <https://blog.majid.info/js/photoswipe-lightbox.esm.min.js>
# 重點關注這些 header:
# - x-cache: Hit from cloudfront / Miss from cloudfront
# - age: 顯示快取了多久
# - cache-control: 顯示快取策略

為什麼 CSS 明明更新了,使用者看到的還是舊版本?

這是使用長 TTL 時最常遇到的問題!解決方案是讓每次更新都產生「新的檔名」:優先使用框架內建的 fingerprint 功能是最好的,以 Rails 來說,Rails 好棒已經自動處理了這個問題,其他框架必須確認各自的 fingerprint 處理方式
🔗 參考 Rails 官方網站文章

# 部署前:app.css  
# 部署後:app-a1b2c3d4e5f6.css ← 自動加上 fingerprint
  • 在 cloudfront 頁面也可以手動建立無效判定,讓特定路徑的快取無效(invalidation)

動態內容(如 API)該怎麼設定快取?

  • 先記住動態內容不要設定 CachingOptimized 當作快取政策,在整個網域交給 CDN 的情境下會出事啊,詳細 CDN 架構可以參考上一篇文章。
CloudFront cache 錯頁面 Debug 流程(Rails 篇)
這篇文章從真實案例出發,帶你逐步排查 CloudFront 快取錯頁面的問題。解析 Rails 的預設 Header、CDN 設定與 DNS 模式,避免使用者畫面被快取錯誤、看到別人的資料。

結論:回到最初的問題

還記得開頭看到 CloudFront 設定頁面的困惑嗎?現在你應該能理解以下:

💡
重點提醒:
Cache Key:像圖書館索書號,CloudFront 用 Host + Path 找檔案TTL:像罐頭保存期限,決定快取檔案多久重新驗證或獲取新版本Path Pattern:幫不同路徑分類,設定專屬的快取策略

為什麼 AWS 推薦 CachingOptimized?
因為它符合靜態檔案的特性:簡化的 Cache Key + 長 TTL = 最高快取命中率。
💡
實務建議:
靜態檔案(圖片、CSS、JS)→ 用 CachingOptimized
更新靜態檔案時記得加 fingerprint,讓新版本立即生效避免使用舊檔案