緩存首先得有個位置放置,共有4個:
service worker: 瀏覽器與服務器之間的中間人角色,可以自由控制緩存文件memory cache:內存緩存,一般用來緩存html頁,圖片,腳本等disk cache:硬盤緩存,一般用來緩存大文件,或者csspush cache: HTTP2產物,以上3種緩存都取不到的時候才能輪到它
主要探討內存緩存和硬盤緩存
===誰來決定緩存位置===
瀏覽器
===如何選擇緩存位置===
- 對於大文件來説,大概率是不存儲在內存中的,反之優先
- 當前系統內存使用率高的話,文件優先存儲進硬盤
===緩存優先級===
內存 > 硬盤
===為什麼css要放在disk,js要放在memory===
css只需加載一次,js需要頻繁讀取
===緩存消除===
memory cache 在進程結束後就會清除,disk cache根據過期時間清除
下面將瀏覽器與服務器之間關於緩存的事情
這裏要引出兩個概念:強緩存和協商緩存
強緩存:瀏覽器不發送HTTP請求,直接從緩存中取,比如上一次緩存下來的圖片,腳本等
關鍵字段:
- 狀態碼200,顯示從內存緩存中獲取
Expires:緩存過期時間,HTTP1.0產物,當時間沒有過期,就可直接命中緩存。缺點是,客户端時間不一定準確,會造成緩存混亂Cache-Control: 緩存的持續時間,HTTP1.1產物,優先級大於Expires,在第一次從服務器請求到該資源後,在緩存的持續時間內再次請求直接命中緩存。它有幾個設置值:
no-cache:每次請求需要協商緩存
no-store:禁止使用緩存
協商緩存:當沒有命中強緩存後,瀏覽器會發送一個請求,請求header裏面帶一些信息,然後服務器判斷是否命中緩存, 命中則返回304
瀏覽器請求header中包含一下字段:
-
If-Modified-Since
上面強緩存的圖裏面有一個屬性Last-Modified,這是服務器返回資源時攜帶的信息,表示該資源的最後修改時間。
於是瀏覽器將這個值賦給If-Modified-Since傳給服務器,服務器根據該值與服務器中修改這個資源的最後時間對比,如果沒有變化,返回304和空響應,如果發生了變化,返回200和響應,而瀏覽器會把這個新的資源再次緩存缺點:
- 它是以秒為最小計量單位的,如果變化在1秒內完成,無法捕獲;
- 如果一個資源在一個週期內修改會原來的樣子,它本來是可以使用緩存的,但是因為修改時間的問題,就必須重新請求
If-None-Match
當服務器支持ETag和已經開啓了ETag的情況下,返回資源時會在header中攜帶一個ETag,表示當前資源的唯一標識
瀏覽器將ETag的值賦給If-None-Match傳給服務器,與服務器上該資源的ETag比對,比對一致則返回304,不一致返回200和響應,並返回新的ETag
===誰控制緩存時間===
服務器
===ETag是如何生成的===
根據算法圍繞資源計算出來的,比如
char *mketag(char *s, struct stat *sb)
{
sprintf(s, "%d-%d-%d", sb->st_mtime, sb->st_size, sb->st_ino);
return s;
}
// 根據文件的修改時間,大小,信息生成
nginx 中 etag 由響應頭的 Last-Modified 與 Content-Length 表示為十六進制組合而成。