Web前端-HTTP Cache-control

HTTP 協議分別在 1.0 / 1.1 兩個時代推出了 Expires / Cache-control 兩種 cache 策略,這裏我們無需瞭解全部的細節,無需記住整個 RFC 內容

    但是當我們需要使用 HTTP cache 策略時,我們需要注意以下細節:

 

       Expires HTTP 1.0 那個時代的東西了,目前來看,可以不使用了,因爲 HTTP 1.0 user agent 佔有率在 0.1% 以下(我們主要面向的 web 瀏覽器均默認使用 HTTP 1.1

       Cache-control HTTP 1.1 的新特性,也是我們主要做文章使用 cache 策略的工具

 

       Cache 策略:

           #1 保鮮期 only

              這個是最最基礎的一種策略,只需要在響應頭中設定:

                  Cache-control: max-age=[secs]

              [secs] cache 在客戶端存活的秒數,例如 Cache-control: max-age=1800 表明 cache 的時間是半小時

              只使用這樣一個聲明就可以使瀏覽器能夠將這個 HTTP 響應的內容寫入臨時目錄做 cache

 

              這裏是簡要過程:

                  I

(1) 瀏覽器第一次請求資源 http://test.qq.com/test.cgi

(2) 查詢臨時文件目錄發現無 cache 存儲,遂發出請求到 web server

(3) web server 響應資源,並設定 Cache-control:max-age=300

(4) 瀏覽器收到響應將資源呈獻給用戶的同時,在臨時文件目錄以 ”http://test.qq.com/test.cgi” key 緩存這個響應

---5 分鐘內 ---

II

(1) 瀏覽器再一次請求資源 http://test.qq.com/test.cgi

(2) 查詢臨時文件目錄發現存在 cache 存儲,檢查保鮮期 max-age ,還未過期,則直接讀取之,響應給用戶

---5 分鐘後 ---

III

(1) 瀏覽器再一次請求資源 http://test.qq.com/test.cgi

(2) 查詢臨時文件目錄發現存在 cache 存儲,檢查保鮮期 max-age ,已經過期,則發請求到 web server

 

 

 

#2 保鮮期 + 最後修改時間驗證

    這裏的要素是,在給出保鮮期的同時,給出一個資源的驗證方式:

       Last-Modified: [UTC time]

    [UTC time] 標示這個響應資源的最後修改時間,例如 Last-Modified: Mon, 06 Jul 2009 09:21:48 GMT

    這個響應頭只有配合 Cache-control 的時候纔有實際價值,只是聲明校驗資源的方式,並不能影響資源的保鮮期時長

    利用資源的可校驗性,我們可以實現在 cache 的資源超過保鮮期瀏覽器再次請求時的 304 響應,令瀏覽器再次使用之前的 cache

 

              這裏是簡要過程:

                  I

(1) #1 I (1)

(2) #1 I (2)

(3) web server 響應資源,並設定

Cache-control:max-age=300

Last-Modified: Mon, 06 Jul 2009 09:21:48 GMT

(4) #1 I (4)

---5 分鐘內 ---

( #1 II)

---5 分鐘後 ---

III

(1) 瀏覽器再一次請求資源 http://test.qq.com/test.cgi

(2) 查詢臨時文件目錄發現存在 cache 存儲,檢查保鮮期 max-age ,已經過期

發現資源具有 Last-Modified 聲明,則爲請求帶上頭 If-Modified-Since: Mon, 06 Jul 2009 09:21:48 GMT

發送請求到 web server

(3) web server 收到請求後發現有頭 If-Modified-Since 則與被請求資源的最後修改時間進行比對

若最後修改時間較新,說明資源又被改動過,則響應整片資源內容, HTTP 200 ( 需要整塊內容寫爲包體 )

若最後修改時間較舊,說明資源無新修改,則響應 HTTP 304 ( 無需包體 ) ,告知瀏覽器繼續使用所保存的 cache

( 這裏當然也可以根據自己的需要決定是 200 還是 304 ,我們的 CGI 畢竟是一種原始的實現 )

 

 

           #3 保鮮期 + 自定義標識驗證

    這裏的要素是,在給出保鮮期的同時,給出另一種資源的驗證方式:

       ETag: [custom flag]

    [custom flag] 標示這個響應資源的由開發者自己確定的簽名驗證標識 ,例如 ETag: "abcdefg"

    這個響應頭只有配合 Cache-control 的時候纔有實際價值,是聲明校驗資源的方式

    ETag 的使用爲我們實現 304 響應提供了更多的靈活性,我們可以拋開必須將驗證轉化成時間格式的限制

 

              這裏是簡要過程:

                  I

(1) #1 I (1)

(2) #1 I (2)

(3) web server 響應資源,並設定

Cache-control:max-age=300

ETag: "abcdefg"

(4) #1 I (4)

---5 分鐘內 ---

( #1 II)

---5 分鐘後 ---

III

(1) 瀏覽器再一次請求資源 http://test.qq.com/test.cgi

(2) 查詢臨時文件目錄發現存在 cache 存儲,檢查保鮮期 max-age ,已經過期

發現資源具有 ETag 聲明,則爲請求帶上頭 If-None-Match: "abcdefg"

發送請求到 web server

(3) web server 收到請求後發現有頭 If-None-Match 則與被請求資源的相應校驗串進行比對

可以是一個版本號,可以是短時間戳,可以是資源校驗和 ( 強烈不推薦使用 ) ,或者乾脆是一個常量 ( 可以乾脆拿來做容錯 )

 

If-None-Match 發來的串與我們的自有值比對,根據我們自己的任何策略算法,可以自由決定如何返回瀏覽器, 304 200

 

              這裏有一個使用 ETag 來做容錯的例子 ( 應用列表目前在使用 )

(1) 我們的每次正常返回都是

200

Cache-control: max-age=1800

ETag: "anything"

 

這裏 anything 是個常量,我們只用來告訴瀏覽器, cache 過期要髮帶 If-None-Match 的請求過來

 

(2) 這樣來自客戶端的一大部分請求基本上都會帶上 If-None-Match 頭,我們的 CGI 據此可以知道這個請求的客戶端是否有 cache

此時如果 CGI 聯繫 server 失敗,那麼可以直接返回 304 ,驅使客戶端使用上一次 cache 的正確結果,且更新保鮮期 max-age 300

 

              這樣我們實現了一個基於 HTTP cache 的容錯,如果我們的資源還能實現一套時間戳存儲的話

那麼我們可以在正常情況下也實現校驗後的 304 ,從而節省流量

這裏還有一個比較慘的教訓,國內 www 上都沒有文獻記載,全球業界也只有一點文獻可以找到:

 

IE6 在資源有 gzip 壓縮同時有 ETag 頭時, cache 後再次發請求不會帶 If-None-Match 頭!!!

這個教訓導致我們試圖通過 304 減少 u.qzone.qq.com 流量的一次嘗試失敗 ( 當然我們能換一種方式實現 )

非常詭異,不中招是不知道的

發佈了5 篇原創文章 · 獲贊 4 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章