1. 程式人生 > >【轉載】掌握 HTTP 快取——從請求到響應過程的一切(上)

【轉載】掌握 HTTP 快取——從請求到響應過程的一切(上)

作者:Ulrich Kautz 
編譯:鬍子大哈

翻譯原文:http://huziketang.com/blog/posts/detail?postId=58b77935204d50674934c3ad 
英文原文:Mastering HTTP Caching - from request to response and everything

轉載請註明出處,保留原文連結以及作者資訊

學習筆記


HTPP 響應快取頭:

1、新版本指的是 HTTP/1.1

2、而舊版本指的是 HTTP/1.0

 

ETag:它是文件版本的識別符號


 通常是內容的 MD5 值,不過它也可以包含其他內容,代表的是文件的版本/日期,如: 1.0 或者 2017-02-27。這裡注意一點是,它必須用雙引號括起來,如:ETag: "d3b07384d113edec49eaa6238ad5ff00"。

客戶端請求了http://doc.tinywan.com:8038/cache2.txt,接著服務端返回瞭如下的響應內容:

第一次訪問:

在響應裡面,有兩個有意思的頭標識:

【1】一個是 ETag,內容的 MD5值。

【2】一個是 Last-Modified,這是 cache2.txt 檔案最後一次被修改的時間。

這裡就是二次驗證起作用的地方:當客戶端在很短的時間內再次訪問上面的 URL,客戶端瀏覽器會使用 If-* 請求頭。如 If-None-Match 檢查 ETag 的內容是否有改變。也就是說,如果 ETag 發生變化,客戶端接收到的一個完整的新響應;如果 ETag 沒變化,客戶端接收到的是一個表明內容沒變化的標識。

 第二次訪問:

正如上面所展示的,這次伺服器的響應裡面不是 200 ok,而是304 Not Modified,這就是說它略過包體部分,讓客戶端直接去自己的快取裡拿資料。

我們修改cache2.txt檔案

注意:以上紅線劃出來的地方,已經發生變化了

在處理上面那個cache2.txt 靜態檔案的例子時,客戶端還可以使用 If-Modified-Since:Sun, 24 Sep 2017 05:27:44 GMT 來達到同樣的效果(返回 304 響應)。這對於靜態檔案來說也很好用,因為響應頭中的 Last-Modified

 標識是根據伺服器磁碟上的“更改時間戳”自動生成的。然而,“更改時間戳”對於動態檔案通常沒什麼用,因為動態生成檔案頻繁更新,時間戳很難確定。我們都知道,你最想快取起來的是內容,生成內容的代價是最大的,所以 ETag 頭是更好的選擇。

 Cache-Control頭


 

Cache-Control 頭相對來講難一些。兩個原因:

第一,Cache-Control 既可以用於請求頭,也可以用於響應頭。本文中著重討論響應頭,因為這是開發者所必須要掌握的。

第二,它控制著兩個快取:本地快取(又稱私有快取)和共享快取。

本地快取,是指在客戶端本地機器中的快取。站在開發者的角度,它並不完全受你的控制,通常瀏覽器會自己決定是否把某些內容放到快取中,這意味著:不要依賴於本地快取。使用者也可能在關閉瀏覽器的時候清理所有快取,而你並不知道有這樣的操作。除非你監測到了某個使用者的流量不斷上漲,導致快取內容迅速失效,這時候你才會意識到。

共享快取,也就是本文所介紹的:處於客戶端和伺服器之間的快取。即 CDN。你對共享快取擁有絕對的控制,應該好好地利用它。

現在我們來用一些程式碼作為示例深入學習一下。

  1. Cache-Control: public max-age=3600
  2. Cache-Control: private immutable
  3. Cache-Control: no-cache
  4. Cache-Control: public max-age=3600 s-maxage=7200
  5. Cache-Control: public max-age=3600 proxy-revalidate

首先是緩衝能力,它關注的是快取到什麼地方,和是否應該被快取。他的幾個重要的屬性是:

  • private:表示它只應該存在本地快取;
  • public:表示它既可以存在共享快取,也可以被存在本地快取;
  • no-cache:表示不論是本地快取還是共享快取,在使用它以前必須用快取裡的值來重新驗證;
  • no-store:表示不允許被快取。

第二個是過期時間,很顯然它關注的是內容可以被快取多久。它的幾個重要的屬性是:

  • max-age=<seconds>:設定快取時間,設定單位為秒。本地快取和共享快取都可以;
  • s-maxage=<seconds>:覆蓋 max-age 屬性。只在共享快取中起作用。

最後一個是二次驗證,表示精細控制。它的幾個重要屬性是:

  • immutable:表示文件是不能更改的。
  • must-revalidate:表示客戶端(瀏覽器)必須檢查代理伺服器上是否存在,即使它已經本地快取了也要檢查。
  • proxy-revalidata:表示共享快取(CDN)必須要檢查源是否存在,即使已經有快取。

通過上面的具體解釋,現在再來描述上面 Cache-Control 的那段程式碼所表達的意思就好理解多了:

  1. 本地快取和 CDN 快取均快取 1 小時;
  2. 不能快取在 CDN,只能快取在本地。並且一旦被快取了,則不能被更新;
  3. 不能快取。如果一定要快取的話,確保對其進行了二次驗證;
  4. 本地快取 1 小時,CDN 上快取 2 小時;
  5. 本地和 CDN 均快取 1 小時。但是如果 CDN 收到請求,則儘管已經快取了 1 小時,還是要檢查源中文件是否已經被改變。