CDN 最難理解的地方,不是名詞,而是整條請求路徑到底怎麼跑。當你知道使用者、邊緣節點和來源站之間的互動,之後看快取命中率、排錯或調規則都會順很多。
你如果希望這篇不只是看完「大概知道」,而是真的能拿來安排自己的部署或排錯順序,那就把每一步都對照你現在的環境去看,效果會差很多。
你會學到什麼
- 把 CDN 工作流程用一條線串起來,從 DNS 查詢到內容回傳。
- 理解 Cache Hit 與 Miss 的差別,以及不同快取狀態代表什麼。
- 搞懂回源機制的細節,包括條件式回源和回源 Header。
- 知道智慧路由和負載均衡怎麼讓 CDN 更穩定。
- 之後遇到資源更新不即時時,更知道從哪裡排查。
什麼情況最適合先看這篇
- 想讓網站更快、更穩,並把 DNS、SSL、快取一起整理好的站長
- 你開了 CDN 但遇到「改了東西卻沒看到更新」的問題
- 你想了解 CDN 快取狀態(HIT、MISS、EXPIRED)各代表什麼
- 你希望做完後不只是功能可用,連驗證與風險也一起想進去
開始前先確認
- 先有基本 DNS 和網站請求概念,如果不熟可以先看 DNS 基礎教學。
- 手邊最好有一個實際網站案例可以對照。
- 如果你對 CDN 基本概念還不清楚,建議先看 CDN 基礎教學。
- 如果你常碰 Cloudflare 快取問題,這篇特別值得先看。
先提醒你一件事
CDN、DNS、Proxy 與 SSL 是互相連動的,不要一次開很多開關卻沒有逐步驗證。
詳細教學與操作步驟
完整請求流程:從訪客到內容回傳
當一個訪客在瀏覽器輸入你的網址,到頁面顯示出來,中間經過了這些步驟:
讓我們一步一步拆解。
第一步:DNS 解析與 Anycast 路由
訪客輸入 yoursite.com,瀏覽器先問 DNS:「這個網域的 IP 是什麼?」
如果你用 Cloudflare,DNS 回傳的 IP 不是你原站的 IP,而是 Cloudflare 的 Anycast IP。Anycast 是一種特殊的路由技術:同一個 IP 位址,在全球很多地方都有伺服器在「回應」。
# 你可以用 dig 查看 DNS 解析結果
dig yoursite.com
# 回傳的 IP 是 Cloudflare 的,不是你原站的
;; ANSWER SECTION:
yoursite.com. 300 IN A 104.21.xx.xx
Anycast 的好處:
- 訪客的請求會自動被路由到「網路距離最近」的資料中心
- 不需要你設定任何 GeoDNS,Anycast 在網路層就搞定了
- 如果某個資料中心故障,流量自動轉到下一個最近的,你什麼都不用做
注意:Anycast 的「最近」是指網路跳數最少,不一定是地理距離最近。台灣的訪客可能被路由到台北、東京或香港的節點,取決於當時的網路狀態。
第二步:到達邊緣節點
請求到達邊緣節點後,CDN 要做一個關鍵判斷:「這個請求的資源,我手上有沒有?」
這個判斷的依據是:
- 請求的 URL 路徑
- 請求的 Host Header
- 快取的 TTL 有沒有過期
- 是否有被 Page Rule 或快取規則排除
第三步:快取命中(Cache Hit)
如果邊緣節點有這個資源的快取,而且還沒過期,就直接回傳給訪客。這是最快的情況,延遲通常在 5-15ms。
你可以在 Chrome DevTools 的 Network 面板看到回應的 Header:
cf-cache-status: HIT
age: 3600
age: 3600 表示這份快取已經存在邊緣節點上 3600 秒(1 小時)了。
影響快取命中率的因素:
- TTL 設定:TTL 越長,快取命中率越高。但你要平衡內容即時性。
- 流量分布:如果你的訪客分散在很多國家,每個邊緣節點的快取都要獨立建立,命中率會比流量集中的情況低。
- 資源 URL 的一致性:
/image.jpg、/image.jpg?v=1、/Image.jpg對 CDN 來說是三個不同的資源。URL 不一致會嚴重降低命中率。
第四步:快取未命中(Cache Miss)與回源
如果邊緣節點沒有快取,或者快取已過期,就要「回源」——向你的原始伺服器要資源。
完整回源 vs 條件式回源
不是每次回源都需要傳完整內容。如果原站支援 ETag 或 Last-Modified Header,邊緣節點可以用「條件式請求」:
# 邊緣節點發出的條件式請求
GET /style.css HTTP/1.1
If-None-Match: "abc123def456"
如果原站的檔案沒變,就回 304 Not Modified,不傳內容,只傳 Header。這省下了大量的回源頻寬。
如果原站的檔案變了,就回 200 OK 加上新的內容和新的 ETag。
回源失敗怎麼辦?
如果回源時原站掛了(5xx 錯誤或連不上),不同的 CDN 有不同的處理方式:
- Cloudflare 預設:回傳 Cloudflare 的錯誤頁面(502/504)
- Always Online(Cloudflare 功能):提供 Internet Archive 的快取版本
- 自訂設定:你可以設定「回源失敗時,提供過期的快取內容」,這在 Cloudflare 的 Cache Rules 裡可以設定
對於重要的網站,建議開啟「Serve Stale」功能:
Cache-Control: public, max-age=3600, stale-if-error=86400
這行的意思是:「快取 1 小時。如果回源失敗,可以繼續用過期的快取,最多 24 小時。」這能讓你的網站在原站短暫故障時仍然可用。
第五步:快取存儲與回傳
邊緣節點從原站拿到內容後,會做兩件事:
- 存一份在自己的快取裡
- 回傳給訪客
之後同一個邊緣節點收到相同資源的請求,就直接從快取回傳,不需要再回源。
智慧路由(Smart Routing)
基礎的 CDN 只是「就近取件」,但現代 CDN 還有智慧路由的能力。
什麼是智慧路由?
網際網路不是一條直線,從 A 到 B 可能有很多條路徑。有些路徑塞車(壅塞)、有些路徑繞路(跳數多)、有些路徑斷了(故障)。
智慧路由就是 CDN 根據即時的網路狀態,選一條最快的路徑來傳送你的請求和內容。
Cloudflare Argo Smart Routing
Cloudflare 的 Argo Smart Routing 是付費功能,原理是:
- Cloudflare 持續監測自己全球網路中,每條路徑的延遲和封包遺失率
- 當你的請求需要回源時,Argo 不走公開的網際網路,而是走 Cloudflare 自己的私有骨幹網路
- 這條私有路徑通常比公開網路更快、更穩定
Cloudflare 的數據顯示,Argo 平均能減少 30% 的回源延遲。對於原站在海外但主要訪客在亞洲的網站來說,效果特別明顯。
不過免費方案沒有 Argo。如果你的預算有限,把原站放在離主要訪客近的地方(例如用侃瑞科技的 VPS 方案),效果可能更直接。
負載均衡(Load Balancing)
當你的網站流量大到一台伺服器撐不住,或者你需要高可用(High Availability),就需要負載均衡。
CDN 層級的負載均衡
CDN 的邊緣節點本身就是一種負載均衡:流量被分散到全球各地的節點,不會全部壓在你的原站上。
原站層級的負載均衡
如果你有多台原站(例如一台在台灣、一台在美國),CDN 可以根據以下條件選擇回源到哪一台:
- 地理位置:亞洲的邊緣節點回源到台灣的原站,美洲的回源到美國的原站
- 健康檢查:定期 ping 每台原站,如果某台掛了就不再回源到它
- 權重:例如 70% 的流量回源到主機 A,30% 回源到主機 B
Cloudflare 的 Load Balancing 是付費功能,但對於多數中小型網站來說,一台好的 VPS 加上 CDN 快取就夠用了。
邊緣運算(Edge Computing)
這是 CDN 技術的新方向。傳統 CDN 只能快取靜態內容,邊緣運算讓你可以在邊緣節點「跑程式」。
Cloudflare Workers
Cloudflare Workers 讓你在邊緣節點執行 JavaScript,常見用途:
- A/B 測試:在邊緣節點決定顯示版本 A 還是版本 B,不需要回源
- URL 重寫:在邊緣節點就把
/old-page轉到/new-page - 請求過濾:根據自訂邏輯(國家、裝置、Cookie)決定要不要允許請求
- API Gateway:在邊緣做速率限制、驗證、回應快取
// Cloudflare Worker 範例:根據國家重導向
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
const country = request.cf.country
if (country === 'TW') {
// 台灣訪客,導向中文版
return Response.redirect('https://tw.example.com' + new URL(request.url).pathname, 302)
}
// 其他國家,正常回源
return fetch(request)
}
HTTP Header 與快取控制的完整對照
理解這些 Header,你就能讀懂 CDN 的行為:
請求端(瀏覽器 → CDN)的重要 Header:
| Header | 用途 | 範例 |
|---|---|---|
Cache-Control: no-cache | 有快取也要回源驗證 | 瀏覽器按 F5 重新整理 |
Cache-Control: no-store | 完全不要快取 | 敏感頁面 |
If-None-Match | 條件式請求,帶 ETag | 節省頻寬 |
If-Modified-Since | 條件式請求,帶時間 | 節省頻寬 |
回應端(CDN → 瀏覽器)的重要 Header:
| Header | 用途 | 範例 |
|---|---|---|
Cache-Control: public, max-age=86400 | 可以被任何快取存 1 天 | 靜態資源 |
Cache-Control: private, no-cache | 只能瀏覽器存,每次要驗證 | 含登入狀態的頁面 |
ETag: "abc123" | 資源的指紋 | 條件式回源用 |
Vary: Accept-Encoding | 不同編碼各存一份快取 | gzip 和 br 各存一份 |
cf-cache-status: HIT | Cloudflare 快取狀態 | 判斷有沒有命中 |
用 curl 檢查回應 Header:
# 檢查某個資源的快取狀態
curl -I https://yoursite.com/style.css
# 重點看這幾行
# cf-cache-status: HIT ← 有快取
# cache-control: public, max-age=31536000 ← 快取策略
# age: 7200 ← 這份快取已經存在 2 小時
# cf-ray: xxxx-TPE ← TPE 表示從台北的節點回應
實際排查案例:為什麼改了檔案卻沒更新?
這是最常見的問題。你改了 CSS 或圖片,但訪客看到的還是舊版。排查流程:
Step 1:確認原站有更新
先繞過 CDN,直接存取原站確認檔案是否已經更新:
# 如果你知道原站 IP,可以直接存取
curl -H "Host: yoursite.com" http://原站IP/style.css | head
Step 2:檢查 CDN 快取狀態
curl -I https://yoursite.com/style.css
# 看 cf-cache-status 和 age
如果 cf-cache-status: HIT 而且 age 很大,表示 CDN 還在提供舊的快取。
Step 3:清除快取
到 Cloudflare Dashboard → Caching → Configuration → Purge Cache。
你可以選擇:
- Purge Everything:清除所有快取。簡單但粗暴,會導致短暫的全站回源。
- Custom Purge:只清特定 URL。精確但要手動輸入。
- Purge by Tag/Host:Enterprise 方案才有。
Step 4:如果清了快取還是舊的
那問題不在 CDN,而在瀏覽器快取。叫訪客按 Ctrl+Shift+R(強制重新整理),或者用無痕模式開。
長期解法:用版本化的檔名(style.a1b2c3.css),這樣內容一改,URL 就不同,瀏覽器不可能拿到舊的。
快取命中率的優化策略
快取命中率是衡量 CDN 效能的關鍵指標。Cloudflare 後台可以看到你的 Cache Hit Rate。
理想的快取命中率:
- 靜態網站(部落格、公司官網):90% 以上
- 混合型網站(電商、有會員系統):60-80%
- 高度動態網站(社群平台、即時資料):30-50%
提升命中率的方法:
-
統一 URL:不要用
?v=1、?v=2來做版本控制,改用檔名 hash。每個不同的 URL 在 CDN 看來就是不同的資源。 -
設定合理的 TTL:靜態資源至少 1 天,有 hash 的資源可以 1 年。
-
注意 Query String 排序:
?a=1&b=2和?b=2&a=1對某些 CDN 來說是不同的 URL。Cloudflare 有 Query String Sort 功能可以解決。 -
善用 Page Rules(或 Cache Rules):
/wp-admin/*→ Bypass Cache/wp-content/uploads/*→ Cache Everything, Edge TTL 30 days/*.css→ Cache Everything, Edge TTL 1 year
-
減少 Vary Header 的變化:
Vary: Accept-Encoding是正常的,但如果你的原站回傳Vary: *或太多 Vary 值,CDN 可能完全不快取。
CDN 與 SSL/TLS 的關係
CDN 和 SSL 的關係經常讓人搞混。當你啟用 CDN Proxy(Cloudflare 的橘色雲朵),SSL 的運作變成兩段:
- 訪客 ↔ CDN 邊緣節點:用 Cloudflare 提供的 SSL 憑證
- CDN 邊緣節點 ↔ 你的原站:看你的 SSL 模式設定
這就是為什麼 Cloudflare 的 SSL 模式選擇很重要。詳細的 SSL 模式說明,請看 Cloudflare 設定教學 裡的 SSL 段落。
如果你的原站需要 SSL 憑證,可以參考 SSL 憑證設定教學。
做完後怎麼確認自己真的有設對
- 用
curl -I檢查關鍵頁面的cf-cache-status、cache-control、ageHeader。 - 在 Cloudflare Dashboard 的 Analytics 裡看 Cache Hit Rate,確認命中率符合預期。
- 至少從不同網路或無痕模式測一次,確認快取與代理後的實際結果。
- 從使用者視角再跑一次實際流程,不要只看後台畫面。
- 如果你有改 DNS、Proxy、背景服務或權限,請逐層確認,不要一次判斷全部成功。
- 測試「更新內容 → 清快取 → 確認更新」的完整流程,確保你的部署流程跟快取策略是配合的。
這一題最常踩的坑
- 只知道「有經過 CDN」,卻不知道到底是命中還是回源。用
curl -I看 Header 就能判斷。 - 資源已更新卻忘了快取層還沒刷新。養成習慣:部署後清快取。
- 快取規則與部署流程沒有一起設計,導致每次更新都很混亂。
VaryHeader 設太多,導致同一個資源存了好幾份,命中率暴跌。- 忘了 CDN 的快取是「每個邊緣節點獨立的」。你清了台北節點的快取,東京節點可能還有舊的。Purge Everything 會清所有節點。
- 原站回傳
Cache-Control: private或no-store,CDN 根本不會快取,但你不知道為什麼命中率一直是 0。 - 忽略
cf-rayHeader 裡的機場代碼。cf-ray: xxx-TPE表示台北,cf-ray: xxx-NRT表示東京。這能幫你確認請求是從哪個節點回應的。
Troubleshooting:更多常見問題
Q:CDN 會造成資料同步問題嗎? 有可能。如果你更新了圖片但檔名沒變,CDN 可能還在提供舊的圖。這時你需要執行 Purge Cache 操作。詳細設定可參考 Cloudflare 設定教學。
Q:小網站也需要 CDN 嗎? 建議開。即使流量不大,CDN 提供的免費 SSL、DDoS 防護與基礎加速,都能讓你的網站更安全、更快。Cloudflare 免費方案零成本,沒有理由不用。
Q:為什麼 cf-cache-status 顯示 DYNAMIC? Cloudflare 預設只快取特定副檔名(.js、.css、.jpg 等)。HTML 頁面預設不快取(顯示 DYNAMIC)。如果你要讓 HTML 也被快取,需要設定 Page Rule 或 Cache Rule,加上 Cache Everything。
Q:多個子網域(subdomain)的快取是獨立的嗎?
是的。www.example.com 和 blog.example.com 的快取完全獨立。每個子網域在每個邊緣節點都有自己的快取空間。
如果你要往下一步走
如果你要真的動手導入,下一篇就看 Cloudflare 免費帳號註冊與 DNS 設定教學。如果你想回頭複習基本概念,看 CDN 基礎教學。DNS 相關問題可以看 DNS 問題排除教學 和 DNS 基礎教學。如果你要讓網站直接套用這些做法,可以搭配侃瑞的 主機方案。