Web緩存技術相關簡析

Web緩存最權威的資料就屬RFC了,可惜它太過言簡意賅,本文將對緩存做一些通俗易懂的介紹。

Expires / Cache-Control:

當服務器發出響應的時候,可以通過兩種方式來告訴客戶端緩存請求:

第一種是Expires,比如:

Expires: Sun, 16 Oct 2016 05:43:02 GMT

在此日期之前,客戶端都會認爲緩存是有效的。

不過Expires有缺點,比如說,服務端和客戶端的時間設置可能不同,這就會使緩存的失效可能並不能精確的按服務器的預期進行。

第二種是Cache-Control,比如:

Cache-Control: max-age=315360000

這裏聲明的是一個相對的秒數,表示從現在起,315360000秒內緩存都是有效的,這樣就避免了服務端和客戶端時間不一致的問題。

但是Cache-Control是HTTP1.1纔有的,不適用與HTTP1.0,而Expires既適用於HTTP1.0,也適用於HTTP1.1,所以說在大多數情況下同時發送這兩個頭會是一個更好的選擇,當客戶端兩種頭都能解析的時候,會優先使用Cache-Control。

參考Apache相關文檔

條件GET:Last-Modified / If-Modified-Since和ETag / If-None-Match

Last-Modified / If-Modified-Since

Last-Modified是響應頭,If-Modified-Since是請求頭。Last-Modified把Web組件的最後修改時間告訴客戶端,客戶端在下次請求此Web組件的時候,會把上次服務端響應的最後修改時間作爲If-Modified-Since的值發送給服務器,服務器可以通過這個值來判斷是否需要重新發送,如果不需要,就簡單的發送一個304狀態碼,客戶端將從緩存裏直接讀取所需的Web組件。

ETag / If-None-Match

ETag是響應頭,If-None-Match是請求頭。Last-Modified / If-Modified-Since的主要缺點就是它只能精確到秒的級別,一旦在一秒的時間裏出現了多次修改,那麼Last-Modified / If-Modified-Since是無法體現的。相比較,ETag / If-None-Match沒有使用時間作爲判斷標準,而是使用一個特徵串。Etag把Web組件的特徵串告訴客戶端,客戶端在下次請求此Web組件的時候,會把上次服務端響應的特徵串作爲If-None-Match的值發送給服務端,服務端可以通過這個值來判斷是否需要從重新發送,如果不需要,就簡單的發送一個304狀態碼,客戶端將從緩存裏直接讀取所需的Web組件。

一些建議:

當使用Expires / Cache-Control的時候,儘量給圖片,樣式表,腳本等設置一個足夠大的緩存時間,如果在此期間,緩存文件有過修改,最簡單的更新方式是改名或者設置一個查詢參數,比如開始圖片名是logo.gif,如果做了一個新的圖片,你想更新,可以把圖片改名爲logo_v2.gif,或者給圖片設置一個查詢參數logo.gif?foobar,這樣,瀏覽器就會去請求新的圖片了。不過,並不是所有的Web組件都適合有一個大的緩存時間,比如html,就不適合使用過大的緩存時間,否則你在緩存到期前,就沒機會更新任何東西了。

使用Yslow的都知道,它不建議使用ETag,理由是Etag在分佈式環境裏,會給服務器造成不必要的壓力,比如說在Apache裏,Etag缺省是由三個因素決定的:INode Size MTime,而同一個圖片,在不同服務器上的INode是不同的,所以在兩個服務器上先後請求同一個圖片,會得到兩次200,雖然我們可以通過設置FileETag Size MTime來屏蔽INode,從而達到一次200,一次304的效果,但304也是要通過一次條件GET請求驗證的,所以說,還是通過Expires / Cache-Control來設置一個足夠大的緩存時間更划算一些,如此說來,對圖片,樣式表,腳本等靜態內容而言,設置一個大的過期時間是絕對必要的,而Etag和Last-Modified則不是必要的。

如果你決定禁止ETag的話,簡單的使用FileETag None就能達到目的。

如果你想把Last-Modified也禁止的話,似乎沒有直接的方法,只能通過header模塊的方式:

LoadModule headers_module modules/mod_headers.so

<FilesMatch "...">
Header unset Last-Modified
</FilesMatch>


不理解緩存可能會讓我們作出很多錯誤的判斷,比如說很多人在估算帶寬的時候一般是按照如下的流程來計算帶寬的(以每天百萬訪問量爲例來說明):

如果100萬PV的訪問量在一天內平均分佈的話,摺合到每秒大約12次訪問,如果按平均每次訪問頁面的大小是100K字節左右計算的話,這12次訪 問總計大約就是1200K字節,字節的單位是Byte,而帶寬的單位是bit,它們之間的關係是1Byte = 8bit,所以1200K Byte大致就相當於9600K bit,也就是9Mbps的樣子,實際情況中,我們的網站必須能在峯值流量時保持正常訪問,假設峯值流量是平均流量的5倍,於是得出真實帶寬的需求應該在45Mbps 左右。

如上的計算只在一種情況下是正確的,那就是網站服務器關閉了緩存或者網站的瀏覽者關閉了緩存!不過現實情況我們出於性能的考慮肯定要加入緩存,用戶在有緩存的情況下產生的流量要遠遠小於沒有緩存時產生的流量。所以在估算帶寬的時候,我們還得考慮攜帶緩存瀏覽的瀏覽者在總瀏覽者中所佔的比例,說白了就是回頭客的比例,這樣才能作出準確的判斷,否則會多花很多冤枉錢。

參考資料:Caching Tutorial for Web Authors and Webmasters(英文版)(中文版

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章