同一個 URL 可以有多個正確回應,這件事本身不難理解。難的是快取要怎麼知道「這兩個請求的差異,到底會不會改變回應」。Cloudflare 在 2026 年 9 月 22 日發佈的 Vary 支援 就是在處理這個問題:Vary 這個 response header 長期被形容為 HTTP 裡最醜、互通性最差的一塊,但醜不等於沒用。
問題不在正確性,在命中率
Vary 告訴中介快取哪些 request 欄位可能影響回應,但它沒有告訴快取哪些差異真的有意義。來源端可能只提供英文、法文、德文三種內容,但客戶端送來的 Accept-Language 可以有上千種組合:順序不同、大小寫不同、帶 q 值、帶地區標籤。快取比對原始字串時無法假設它們等價,只好各自存成一個 variant,即使回應內容完全相同。
單一欄位十個值就是十個 variant;三個欄位各十個值可以變成一千種組合。Cloudflare 引用一份涵蓋近 50,000 個熱門網站、超過 1.2 億個回應的分析,其中近 3,000 個網站會在四個以上欄位變動,有些甚至到 10、23 或 47 個欄位。結果是一個「完全正確但幾乎永遠冷」的快取:相同回應散落在流量太低的條目裡,互相淘汰,命中率下降,更多請求回到來源。
把決策拆成兩層
新的做法是把責任切開:來源用 Vary 宣告哪些標頭可能影響回應,Cache Rule 決定 Cloudflare 怎麼處理每個標頭的值。三個動作是 normalize、passthrough、bypass。官方建議預設用 normalize;個人化或無上限值的標頭用 bypass;只有當精確值真的會改變回應時才用 passthrough。
這裡有個容易忽略的細節:passthrough 會保留大小寫、空白、順序與重複值的差異。X-View: compact,full、X-View: Compact,full、X-View: compact, full 會變成三個不同的快取鍵,即使來源把它們視為同一件事。另外,Vary: * 一律繞過快取,因為它代表請求的任何層面(包括 IP)都可能影響回應。
順序與責任歸屬
流程上,第一個請求進來時快取未命中,符合條件的 Cache Rule 會先正規化欄位,再把請求送往來源——即使此時還不知道回應會不會帶 Vary。這個順序很重要:如果快取把多個原始值歸成同一個鍵,卻把原始值送給來源,來源可能產生不同回應,而快取之後會誤以為它們可以互換。所以 Cloudflare 會把正規化後的 Accept、Accept-Language 轉發給來源,讓來源的選擇邏輯與快取比對保持一致。
反過來說,來源的責任變重了。每個可能因請求欄位而不同的可快取回應,都必須穩定地帶上正確的 Vary,包含錯誤與 fallback 回應。只要有一個回應漏掉,Cloudflare 就可能把它當成一般回應快取,失去隔離效果。另外,調整 Vary 設定不會自動清除既有內容,舊條目會留到過期或被清除為止。
對產品團隊的實際意義
如果你的架構裡有 CDN 或反向代理,這類「來源宣告、邊緣決定粒度」的分工值得記下來。它和我們先前談 Python Workers 進邊緣執行環境 的脈絡相同:邊緣層能做的事越多,你越需要明確決定哪些邏輯留在來源、哪些交給邊緣。
實務上的下一步不是馬上開 normalize,而是先盤點:你的來源目前對哪些標頭回了 Vary?其中哪些是真正會改變回應內容的?哪些只是客戶端格式差異?把後者收斂掉,命中率才會回來。至於那些你無法預測值域的標頭,bypass 比勉強快取安全。
需要保留的細節是:這套機制依賴來源端持續且正確地宣告 Vary,快取無法替你推斷語意。這既是它的限制,也是它沒有變成另一套猜測邏輯的原因。
參考來源
本文由 AI 協助自上述來源整理,經人工審核後發布。
