<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Cache-Key on Tarragon</title><link>https://tarrragon.github.io/blog/tags/cache-key/</link><description>Recent content in Cache-Key on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Fri, 02 Oct 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/cache-key/index.xml" rel="self" type="application/rss+xml"/><item><title>Vary（快取鍵變體標頭）</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/vary/</link><pubDate>Fri, 02 Oct 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/vary/</guid><description>&lt;p>快取找保存的回應時，規範要求至少比對請求方法與網址；同一個網址會因為某個請求標頭回出不同內容時（例如依 &lt;code>Accept-Encoding&lt;/code> 回 gzip 或 br 壓縮的版本），origin 在回應上寫 &lt;code>Vary: &amp;lt;標頭名稱&amp;gt;&lt;/code>，快取就把那個請求標頭的值也加進比對條件，不同的值各存一份、各自重用。它是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-control/" data-link-title="Cache-Control（快取控制標頭）" data-link-desc="看到回應帶 Cache-Control、或要決定某個回應能被誰保存、保存多久、使用前要不要先問 origin 時，查這個標頭各指令的分工">Cache-Control&lt;/a> 以外，回應影響「誰拿到哪一份保存內容」的另一個標頭。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Vary 屬於快取鍵這一層：Cache-Control 決定一份回應能不能保存、能用多久，Vary 決定保存的這一份可以拿去回應哪些請求。它與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-hit-rate/" data-link-title="Cache Hit Rate" data-link-desc="說明快取命中比例如何衡量加速效果與下游保護">Cache Hit Rate&lt;/a> 直接相關，列進去的標頭值越分散，同一個網址就被切成越多份，每一份被重用的機會越少。&lt;code>Vary: *&lt;/code> 讓比對永遠失敗，這份回應每次被重用前都要先向 origin 驗證。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>&lt;code>Vary: Accept-Encoding&lt;/code> 是最常見的用法。規範只允許快取在比對前做去掉空白這類不改變語意的正規化，所以 &lt;code>gzip&lt;/code>、&lt;code>br&lt;/code>、&lt;code>gzip, deflate, br&lt;/code> 三種寫法照字面會被當成三種值；實作可以自己再正規化（例如 Varnish 預設把它收斂成同一份），各產品的做法不同。&lt;/p>
&lt;p>&lt;code>Vary: Cookie&lt;/code> 是另一端：Cookie 的值幾乎每個使用者都不同，共用快取存下的份數接近使用者數，命中率接近零。個人化回應的建議做法是寫 &lt;code>Cache-Control: private&lt;/code> 讓共用快取不保存，而不是用 &lt;code>Vary: Cookie&lt;/code>。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>看到一個回應帶 Vary，先問列出的標頭在實際流量裡有幾種值：值少而且有意義（壓縮方式、語系）時 Vary 讓不同版本安全地共用快取；值幾乎一人一種（Cookie、未經正規化的完整 &lt;code>User-Agent&lt;/code> 字串）時它實質上關掉了共用快取，要改用 &lt;code>private&lt;/code> 或在快取前先把標頭正規化成少數幾種值。&lt;/p>
&lt;p>&lt;code>Authorization&lt;/code> 不必列進 Vary：規範已經禁止共用快取把帶 &lt;code>Authorization&lt;/code> 請求的回應拿去回應別人，除非回應用 &lt;code>public&lt;/code> 這類指令明確允許。這是規範的要求，實作不一定遵守（實測預設設定的 nginx 1.27 會共用），需登入的回應仍由 origin 明寫 &lt;code>private&lt;/code> 或 &lt;code>no-store&lt;/code>。反過來，自訂的請求標頭（例如以標頭指定 API 版本）沒有列進 Vary 時，快取會把一個版本的回應發給要另一個版本的請求。&lt;/p>
&lt;p>規範的比對規則、Varnish 與 nginx 的實測差異，以及 Cookie、Authorization 在共用快取上的處理，見 &lt;a href="https://tarrragon.github.io/blog/backend/12-http-caching/cache-key/" data-link-title="12.4 快取鍵與副本共用：Vary、Cookie 與 Authorization" data-link-desc="快取用什麼條件挑出一份副本回應請求：快取鍵的組成、Vary 如何把請求標頭加進快取鍵、帶 Authorization 的請求在共用快取的規則、Cookie 與 Set-Cookie 在規範與實作上的處理，個人化回應的標頭選擇，以及沒有列進快取鍵的輸入造成的快取投毒與快取規則造成的 web cache deception">12.4 快取鍵與副本共用：Vary、Cookie 與 Authorization&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>快取找保存的回應時，規範要求至少比對請求方法與網址；同一個網址會因為某個請求標頭回出不同內容時（例如依 <code>Accept-Encoding</code> 回 gzip 或 br 壓縮的版本），origin 在回應上寫 <code>Vary: &lt;標頭名稱&gt;</code>，快取就把那個請求標頭的值也加進比對條件，不同的值各存一份、各自重用。它是 <a href="/blog/backend/knowledge-cards/cache-control/" data-link-title="Cache-Control（快取控制標頭）" data-link-desc="看到回應帶 Cache-Control、或要決定某個回應能被誰保存、保存多久、使用前要不要先問 origin 時，查這個標頭各指令的分工">Cache-Control</a> 以外，回應影響「誰拿到哪一份保存內容」的另一個標頭。</p>
<h2 id="概念位置">概念位置</h2>
<p>Vary 屬於快取鍵這一層：Cache-Control 決定一份回應能不能保存、能用多久，Vary 決定保存的這一份可以拿去回應哪些請求。它與 <a href="/blog/backend/knowledge-cards/cache-hit-rate/" data-link-title="Cache Hit Rate" data-link-desc="說明快取命中比例如何衡量加速效果與下游保護">Cache Hit Rate</a> 直接相關，列進去的標頭值越分散，同一個網址就被切成越多份，每一份被重用的機會越少。<code>Vary: *</code> 讓比對永遠失敗，這份回應每次被重用前都要先向 origin 驗證。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p><code>Vary: Accept-Encoding</code> 是最常見的用法。規範只允許快取在比對前做去掉空白這類不改變語意的正規化，所以 <code>gzip</code>、<code>br</code>、<code>gzip, deflate, br</code> 三種寫法照字面會被當成三種值；實作可以自己再正規化（例如 Varnish 預設把它收斂成同一份），各產品的做法不同。</p>
<p><code>Vary: Cookie</code> 是另一端：Cookie 的值幾乎每個使用者都不同，共用快取存下的份數接近使用者數，命中率接近零。個人化回應的建議做法是寫 <code>Cache-Control: private</code> 讓共用快取不保存，而不是用 <code>Vary: Cookie</code>。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>看到一個回應帶 Vary，先問列出的標頭在實際流量裡有幾種值：值少而且有意義（壓縮方式、語系）時 Vary 讓不同版本安全地共用快取；值幾乎一人一種（Cookie、未經正規化的完整 <code>User-Agent</code> 字串）時它實質上關掉了共用快取，要改用 <code>private</code> 或在快取前先把標頭正規化成少數幾種值。</p>
<p><code>Authorization</code> 不必列進 Vary：規範已經禁止共用快取把帶 <code>Authorization</code> 請求的回應拿去回應別人，除非回應用 <code>public</code> 這類指令明確允許。這是規範的要求，實作不一定遵守（實測預設設定的 nginx 1.27 會共用），需登入的回應仍由 origin 明寫 <code>private</code> 或 <code>no-store</code>。反過來，自訂的請求標頭（例如以標頭指定 API 版本）沒有列進 Vary 時，快取會把一個版本的回應發給要另一個版本的請求。</p>
<p>規範的比對規則、Varnish 與 nginx 的實測差異，以及 Cookie、Authorization 在共用快取上的處理，見 <a href="/blog/backend/12-http-caching/cache-key/" data-link-title="12.4 快取鍵與副本共用：Vary、Cookie 與 Authorization" data-link-desc="快取用什麼條件挑出一份副本回應請求：快取鍵的組成、Vary 如何把請求標頭加進快取鍵、帶 Authorization 的請求在共用快取的規則、Cookie 與 Set-Cookie 在規範與實作上的處理，個人化回應的標頭選擇，以及沒有列進快取鍵的輸入造成的快取投毒與快取規則造成的 web cache deception">12.4 快取鍵與副本共用：Vary、Cookie 與 Authorization</a>。</p>
]]></content:encoded></item></channel></rss>