[譯] HTTP 緩存頭部 - 徹底指南

原文: http://cncc.bingj.com/cache.aspx?q=max-age+expires+Last-Modified&d=4997458151473641&mkt=en-US&setlang=en-US&w=obLC-DXYkHDglJJNfr5xl1yTc4LW9a_ocss


本文着重論述了關於 HTTP 緩存頭部的重要信息,以及有關的 CDN 行爲。假如你正在尋找現代 web 中  HTTP cache headers 的深刻信息,這裏有你所需的一切。


HTTP 緩存頭部

主要經過新鮮度有效性,來決定對資源的緩存。若是一個有效的資源沒有改變過,不多會再次發送完整的資源,此時緩存中的一個新鮮的副本是當即可用的。假設沒有校驗器(如 ETag/Last-modified 頭部),而且缺乏明確的新鮮度信息的話,那就要常常(但並不老是)被認定爲沒法緩存了。如今把焦點轉移到須要被考慮到的幾種 HTTP 頭部上:web

1. Cache-control

  • 每一個資源均可以經過 Cache-Control HTTP 頭部來定義其緩存策略
  • Cache-Control 指令控制了誰、在什麼條件下來緩存響應,以及緩存多久

cache control header

不須要服務器通訊的請求被認爲是最佳的請求:使用響應的本地副本,既能夠消除網絡延遲,又能避免數據傳輸帶來的網絡負載。HTTP 規範容許服務器發送多個不一樣的 Cache-Control 指令,用以控制身處諸如CDN的中間人緩存中,瀏覽器如何(以及什麼時候)緩存個別的響應:
數據庫

Cache-control: private, max-age=0, no-cache複製代碼

這些設置項被稱爲響應指令,以下所示:瀏覽器

Public vs. Private

被標記爲 `public` 的響應,即使在其關聯了一個 HTTP 認證或其 HTTP 響應狀態碼一般不可緩存的狀況下,也均可以被緩存。在大多數狀況下,標記 `public` 不是必要的,由於明確的緩存信息(如 `max-age`)已經表示響應是可緩存的。
緩存

反之,被標記爲`private`的響應,能夠被(瀏覽器)緩存,可是這樣的響應是典型地面向單個用戶的,所以不能被中間人緩存(好比含有用戶私人信息的 HTML 頁面能夠被用戶的瀏覽器緩存而非 CDN)。
bash

No-cache 和 No-store

no-cache header

`no-cache`表示在檢查過服務器響應是否已經改變以前,返回的響應不能被用於隨後向同一 URL 的請求。若是一個適當的 Etag (校驗記號) 做爲一個結果出現,`no-cache`就會引起一次往返動做以試圖校驗已緩存過的響應。若是資源未改變過,緩存就會避免下載行爲。換句話說,web 瀏覽器可能會緩存資源,但不得不在每次請求都檢查資源是否已改變(未改變則返回 304)。
服務器

與之相反的是,`no-store`更簡單些。這樣說是由於它禁止瀏覽器和全部中間人從返回的響應中緩存任何版本的資源,例如響應中包含隱私/我的的信息或銀行數據等。用戶每次請求這個資源都是請求服務器,每次資源都要被下載。
網絡

max-age

`max-age` 指令表示獲取到的資源被容許重複使用的最長時間,以秒爲單位(從請求發起的時刻算起)。舉例來講,`max-age=90`指示了資源在以後的 90 秒鐘可被重用(保存在瀏覽器緩存中)。
併發

s-maxage

`s-`表明`shard cache`。這個指令是明確針對中間人緩存中的 CDN 的。當這個指令出如今頭部中時,會覆蓋掉 `max-age``expires` 的設置。app


`Cache-Control` 是做爲 HTTP/1.1 標準的一部分定義的,用來接替以前的頭部信息(如 `expires`)來規定響應的緩存策略。 `Cache-Control` 被全部現代瀏覽器支持,實乃咱們必備的。

2. Pragma

舊的 `pragma` 頭部承擔了許多工做,其中大部分都有了更新的實現。咱們通常將cache-control: no-cache視爲pragma: no-cache的更新一些的實現。在總體的理解上了解這個指令是有必要的,但從此不會再爲其定義新的 HTTP 指令了。

3. Expires

expires header

幾年前,這是指定資源有效期的主要途徑。Expires 只是個基本的 date-time 時間戳,對那些遊走在不規範地帶的用戶代理來講,仍是至關管用的;而對於現代系統,則是優先使用cache-control頭部,設置max-ages-maxage等。爲了兼容的目的,在此設置匹配的值是個好的作法;一樣重要的是確保日期的格式正確,否則會被認爲過時。

Expires: Sun, 03 May 2015 23:02:37 GMT複製代碼

爲了不破壞規範,不要設置超過一年的日期值。(譯註:規範中的說明爲 -- To mark a response as "never expires," an origin server sends an Expires date approximately one year from the time the response is sent. HTTP/1.1 servers SHOULD NOT send Expires dates more than one year in the future. )

4. Validators

ETag

etag header

這種在 HTTP/1.1 中定義的有效性 token:

  • 經過服務器的 `ETag` HTTP頭部傳達
  • 確保資源更新的有效性,也就是說,若是資源沒改變,就不會發生數據傳輸

這個例子將展現其做用:在首次獲取一個資源 90 秒後,發起一次新的瀏覽器請求(徹底同樣的資源);瀏覽器尋找本地緩存,當找到上一次緩存的請求後並發現其過時時,就會從服務器請求完整的內容 -- 問題是,若是資源沒有改變過,在其已存在於 CDN 緩存的狀況下,絕無理由再下載一遍。

有效性 token 正是用來解決此類問題。邊緣服務器(edge server, 譯註:如專門負責緩存、防火牆、負載均衡等的第一層服務器;其後是提供web服務的第二層和提供數據庫的第三層)建立並返回特製的 token,存放在 ETag 頭部域中,做爲既有文件的指紋信息,通常用一個 hash  值來表示。客戶端不須要知道該 token 如何產生,只肖在隨後的請求中攜帶之即可。若是 token 相同,也就意味着資源沒變,這樣一來也就跳過了從新下載。

web 瀏覽器自動提供了「If-None-Match」 請求頭,用來包含 ETag token;服務器將根據此 token 比對緩存中的當前資源。若是緩存中的資源未發生變化,瀏覽器將收到一個 `304 Not Modified` 的響應,有效性續期 90 秒。特別是由於不用從新下載資源,帶寬和時間都被節省了。

web 開發者如何從從新生效中獲益?

瀏覽器爲 web 開發者承擔了大多數工做。好比,瀏覽器自動檢測到前一次指定的有效性 token ,將其附加到隨後的請求中,並按需基於服務器響應更新緩存的時間戳。web 開發者所以只須要確保服務器提供所需的 ETag token 就好了。

Last-Modified

last modified header

`Last-Modified` 頭部做爲一個常見的校驗器,指示了文件最後一次改變的時間。能夠將其視爲一個 HTTP/1.0 時代遺留的校驗器。當緩存保存了一個包含此頭部的資源時,能夠利用其查詢服務器資源是否已超時(從資源上次被使用時)。相應的請求頭部爲 `If-Modified-Since`。

一個 HTTP/1.1 的源服務器應該同時發送 ETag 和 Last-Modified。更多細節能夠在 RFC2616 規範中找到。

一個例子:

HTTP/1.1 200 OK
Server: keycdn-engine
Date: Mon, 27 Apr 2015 18:54:37 GMT
Content-Type: text/css
Content-Length: 44660
Connection: keep-alive
Vary: Accept-Encoding
Last-Modified: Mon, 08 Dec 2014 19:23:51 GMT
ETag: "5485fac7-ae74"
Cache-Control: max-age=533280
Expires: Sun, 03 May 2015 23:02:37 GMT
X-Cache: HIT
X-Edge-Location: defr
Access-Control-Allow-Origin: *
Accept-Ranges: bytes複製代碼

TL;DR

Cache-Control 和 ETag 頭部域是用來控制資源新鮮度和有效性的現代機制。其餘值則「僅僅」用來向後兼容。




----------------------------------------

長按二維碼或搜索 fewelife 關注咱們哦
相關文章
相關標籤/搜索