CloudFront cache 錯頁面 Debug 流程(Rails 篇)
以前在 bootcamp 學習套用 CDN 的時候,因為懂的少也不懂得懷疑,覺得反正部署之後,圖片有經過 CDN 、顯示得出來就好,其他不管。
但現在有了經驗、也踩了各種雷坑之後,疑心病加重!每個設定都覺得疑點重重,在想幹嘛要有這個,設定這是想做什麼!每個都覺得這一定有問題!!決定用這篇紀錄我的實作心得。

事件緣起:Reddit 真實案例
在 Reddit 上看到這篇討論,作者遇到了一個恐怖的狀況:CloudFront 把 A 使用者的頁面快取起來,卻回傳給 B 使用者看!
想像一下這個場景:
- 付費用戶登入後看到的專屬內容,竟然被免費用戶看到了
- 或者相反,免費用戶看到了付費才能看的頁面
- 更糟的是,用戶 A 的個人資訊被用戶 B 看到了
Production 環境要是真的發生這種事情還得了啊!天啊!!!!緊張如我開始有了一連串的質疑!
問題:我的 CDN 設置可能 cache 錯頁面嗎?
CDN 基礎:Cache Hit / Cache Miss
首先,讓我們複習一下 CDN 是如何工作的:
下面根據剛剛 Reddit 討論畫出流程圖
情況 1:快取命中(Cache Hit)

情況 2:快取未命中(Cache Miss)

當使用者打開一個頁面時,請求會先送到 CDN。如果 CDN 上有快取的資料,就直接回傳(Cache Hit);如果沒有,就會再去找原始伺服器(Cache Miss)。
咦?如果這樣看,那我的 CDN 設置不是會有一樣的問題嗎?!?!我以為只有 assets 有快取誒?
首先看看參考 Rails 的說明:
CDN Request Caching While a CDN is described as being good for caching assets, it actually caches the entire request.
這個說法容易讓人誤解,讓人懷疑不只是 assets,而是任何 request 都會被快取...
參考 AWS Cloudfront 說明
A cache hit occurs when a viewer request generates the same cache key as a prior request, and the object for that cache key is in the edge location’s cache and valid.
By default, the cache key for a CloudFront distribution includes the following information:
- The domain name of the CloudFront distribution (for example,d111111abcdef8.cloudfront.net
)
- The URL path of the requested object (for example,/content/stories/example-story.html
)
💡 AWS Cloudfront 提到的概念,叫做「Cache Key」,用來決定:「這次請求要不要用快取的結果?」
最簡單的情況下,Cache Key 只會包含網址的路徑。例如:
/member/dashboard
只要兩個使用者都請求這個網址,CloudFront 就會認為他們是「要同一個頁面」,直接回傳快取!
問題就在這 ⚠️——
即使路徑一樣,不同使用者的頁面內容可能不同(例如登入身份不同、顯示資料不同),這樣就有可能把 A 的資料給了 B!
CloudFront 當然可以進一步設置 Cache Key,加入更多條件(像是 cookie、查詢參數、HTTP header 等),但如果你沒有特別設定,CloudFront 可能只會看路徑!(這邊先講一些小概念。更多 cache key 細節會之後再補充)
以 rails CDN 設置、CloudFront 設置,我真的需要擔心被 cache 的問題嗎?
參考下面 Rails 官方文件說明:
以這邊來看,非 assets 的 request 是不會進到 CDN 拿取資料的

但這是 Rails 的設置,但為什麼剛剛的上面會遇到使用者頁面被 cache 的問題,照理來說如果除了 assets 之外不會經過 CDN,我根本不用擔心會有問題啊!
兩種常見的 CDN DNS 佈署模式:
(1) 整個網域交給 CDN (2) 僅把靜態子網域交給 CDN。
模式 | 描述 | 是否經過 CDN | 風險 |
---|---|---|---|
模式一 | 整個網站都透過 CDN | 是 | 若設定錯誤,動態頁面也可能被快取 |
模式二 | 只有 static.example.com 用 CDN | 否(動態頁面直達 origin) | 比較安全 |
模式 1:整個網域交給 CDN,DNS 寫法
記錄類型 | 主機名 | 內容 (指向) |
---|---|---|
CNAME | www.example.com | cdn-provider.net |

- 設定簡單,所有流量都經過 CDN
- 有風險:如果 Cache Policy 設定錯誤,動態頁面也會被快取
- Cloudflare 就是用這種模式去做設置
模式 2:僅靜態子網域交給 CDN
記錄類型 | 主機名 | 內容 | 備註 |
---|---|---|---|
CNAME | static.example.com | cdn-provider.net | 靜態檔案子網域指向 CDN |
A / AAAA | example.com | 原伺服器 IP | 動態頁面直達 Origin server。 |

- 安全:非 assets 內容不經過 CDN,不會有快取混淆問題
- 靜態資源(圖片、CSS、JS)享有 CDN 加速
- 如果沒有把主網域(如
example.com
)透過 DNS 設成指向 CloudFront,那整個主網站就不會經過 CDN,只會讓特定子網域(如static.example.com
)走 CDN。(如果是使用 Rails, 記得還要設置 asset_host 要給 CDN 才會生效)
為了確認即使 CDN 設錯,也不會把動態頁面快取錯給其他人,我想確認 Rails 有沒有幫我預設加上正確的 HTTP Header。
Rails 如何保護動態頁面?
如果我沒特別設,Rails 有幫我加防快取 header 嗎?
Rails 預設 Header 設定

可以看到預設 header 送 cache 是 private,而且一定要重新驗證,也就是快取內容只能保存在使用者自己的瀏覽器中,CDN、代理伺服器**不得快取。**這個機制也會保護動態內容不會被 cache
如何驗證這些 Header 是否生效?
curl -I <https://example.com/member/dashboard>
# 期待看到類似:
# Cache-Control: private, must-revalidate
三步驟自我健檢
第一步:DNS 指向誰?
# 檢查網域指向哪裡
dig www.udn.com
# 如果回傳的是 CDN 網址,代表使用模式 1
# 如果回傳的是你的伺服器 IP,代表使用模式 2
第二步:頁面是否被快取?
# 檢查 HTTP 回應標頭
curl -I <https://www.example.com/page>
# 注意看這些標頭:
# X-Cache: Hit from cloudfront (代表被快取了)
# 如果你是測試 動態頁面,這行不應該出現 Hit。出現了就表示 CDN 有快取,應該調查 Cache Policy 是否設錯
換用戶測試內容是否正確?
- 用無痕模式訪問頁面
- 登入後再訪問同一頁面
- 登出後再次訪問
- 檢查內容是否正確顯示
結語:我怎麼確定自己不會中招?
我目前是採用模式二(僅靜態子網域經過 CDN),所以可以避免 Reddit 上那種動態頁面被錯快取的災情。
Reddit 上那個案例,多半是用了整站走 CDN(模式一),又沒設好 Cache Policy,才導致資料快取錯誤。但說實話,我也不知道對方用什麼框架,所以也不能百分之百說「Rails 就不會有事」。
在我對 CDN 跟 cache 不熟的情境下,看到網路上有人遇到這個問題,我就會完全無法確定自己會不會發生,所以看到那種文章真的會很慌。
經過一連串排查下來才有確定的理由知道不會有問題,所以才想記錄下來也提醒自己:當不確定自己的設定到底在幹嘛的時候,其實就代表,任何一個錯誤都可能發生。(以上紀錄如果有錯,也歡迎來信跟我討論)