緩存的目 的是減少相應延遲 和 減少網絡帶寬消耗, 比如 css、 js、圖檔這類靜态資源應該進行緩存。
實際項目 一般使用反向代理伺服器(如 nginx、 apache 等) 進行緩存。
關鍵字:
cache-control, expire, if-none-match, if-modified-since, etag, last-modified
請求處理過程:
當一個使用者發起一個靜态資源請求的時候,浏覽器會通過以下幾步來擷取資源
1.本地緩存階段:先在本地查找該資源,如果有發現該資源,而且該資源還沒有過期,就使用這一個資源,完全不會發送http請求到伺服器
2.協商緩存階段:如果在本地緩存找到對應的資源,但是不知道該資源是否過期或者已經過期, 則發一個http請求到伺服器,然後伺服器判斷這個請求,如果請求的資源在伺服器上沒有改動過,則傳回304, 讓浏覽器使用本地找到的那個資源
3.緩存失敗階段:當伺服器發現請求的資源已經修改過,或者這是一個新的請求(在本來沒有找到資源),伺服器則傳回該資源的資料,并且傳回200, 當然這個是指找到資源的情況下,如果伺服器上沒有這個資源,則傳回404
經過上面的流程整理,我們會有以下幾個問題需要處理.
1.本地緩存階段,如何判斷資源在本地是否過期?
2.協商緩存階段,如何判斷本地資源是否和伺服器的資源是否一樣?
expire:
如果apache開啟了expire子產品, 當浏覽器發送該資源請求的時候, apache傳回資源的同時,會傳回一個名為expire的http頭,expire頭的内容是一個時間值, 這一個值就是資源在本地的過期時間, 這個值會存在本地.
也就是說,在本地緩存階段,在本地找到了一個對應的資源值,而且目前時間還沒超過資源的過期時間, 那麼就直接使用這一個資源,不會發送http請求.
cache-control:
cache-control是http協定中常用的頭部之一,顧名思義, 他是負責控制頁面的緩存機制,如果該頭部訓示緩存, 緩存的内容也會存在本地, 操作流程和expire相似,但也有不同的地方, cache-control有更多的選項, 而且也有更多的處理方式.
該頭部有過個值,下面我們來看下各個值的作用
1.public
訓示響應可被任何緩存區緩存。
2.private
訓示對于單個使用者的整個或部分響應消息,不能被共享緩存處理。這允許伺服器僅僅描述當使用者的部分響應消息,此響應消息對于其他使用者的請求無效。
3.no-cache
訓示請求或響應消息不能緩存
4.no-store
用于防止重要的資訊被無意的釋出。在請求消息中發送将使得請求和響應消息都不使用緩存
5.max-age
訓示客戶機可以接收生存期不大于指定時間(以秒為機關)的響應。
6.no-transform
不允許轉換存儲系統
7.must-revalidate
使得用戶端再次浏覽目前頁時必須發送相關 http 頭資訊到伺服器進行驗證,然後才決定是否加載用戶端本地 cache
if-modified-since 和 last-modified:
當apache接收到一個資源請求(假設是使用者是第一次通路,沒有任何緩存), 伺服器傳回資源的同時,還會發送一個last-modified的http響應頭, last-modified響應頭的内容值是該資源在伺服器上最後修改的時間.浏覽器接受到這個http頭後,會
把其内容值和資源同時儲存起來.
當使用者第二發送資源請求(假設這裡expire沒有生效或者已經過期), 浏覽器在本地找到了一個相同的資源,但是不能确定該資源是否和伺服器上的一樣(有可能在兩次通路期間,伺服器上的資源已經被修改過),此時浏覽器發送請求的時候,請求頭内會
附帶一個if-modified-since的請求頭, 這個頭部的内容就是上一次last-modified傳回的值, 伺服器把這個頭的值和請求資源的最後修改時間對比,如果兩個值相同,則認為資源沒有修改,将會傳回304,讓浏覽器使用本地資源.否則伺服器将傳回資源,而且
傳回200狀态
if-none-match 和 etag:
其實這兩個頭部和if-modified-since, last-modified的工作原理是一樣的, if-none-match作為請求頭, etag作為響應頭.既然工作原理一樣, 為什麼etag這對頭部會出現呢?
原因在于, last-modified請求頭的内容是以檔案最後修改的時間作為對比的,但是unix系統裡面, 檔案修改的時間隻儲存到了秒. 如果某些應用記憶體在1秒内對檔案做了多次修改,這樣last-modified是不能完成比較功能的.是以要引入一個新的機制(原因可能不止這一個);
etag的值一般由3個數值組成,資源的inode值, 最後修改時間, 資源大小,以16進制組成一個字元串, 例如:1a-182b-10f; 但這個格式不是固定的, 隻要保證該值的唯一性,但不限格式.
浏覽器中的操作對緩存的影響:
1.強制重新整理 – 當按下ctrl+f5來重新整理頁面的時候, 浏覽器将繞過各種緩存(本地緩存和協商緩存), 直接讓伺服器傳回最新的資源;
2.普通重新整理 – 當按下f5來重新整理頁面的時候,浏覽器将繞過本地緩蹲來發送請求到伺服器, 此時, 協商緩存是有效的
3.回車或轉向 – 當在位址欄上輸入回車或者按下跳轉按鈕的時候, 所有緩存都生效
cache-control 和 expire:
1.兩者都是控制本地緩存的頭部兩者同時存在的時候
2.expire會被cache-control的max-age覆寫
3.expire的值是一個确定的日期, 而max-age的值是一個以秒為機關的數字通路, 表示生存時間.
4.expire隻針對靜态資源, 而cache-control針對所有頁面,但預設為所有的動态頁面不緩存(例如php頁面).
pragma 和 cache-control:
pragma是http/1.0實作的頭部, pragma的值會出現在頁面meta标簽的http-equiv屬性中,以此來控制頁面緩存
cache-control是http/1.1實作的頭部,在http/1.0下不相容.
if-modified-since 和 if-none-match的優先級:
伺服器會優先驗證if-modified-since請求頭,再驗證if-none-match,但是必須要兩者頭通過驗證的時候才傳回304,其中一個驗證失敗,都将傳回新資源和200狀态;