HTTP—缓存
?
1. ETag
HTTP 1.1中引入了ETag來解決緩存的問題。ETag全稱是Entity Tag,由服務端生成,服務端可以決定它的生成規則。如果根據文件內容生成散列值。那么條件請求將不會受到時間戳的改動造成帶寬浪費。下面是根據內容生成散列值的方法:
1 var getHash = function(str) { 2 var shasum = crypto.createHash('sha1'); 3 return shasum.update(str).digest('base64'); 4 }與If-Modified-Since/Last-Modified不同的是,ETag的請求和響應是If-None-Match/ETag。瀏覽器在收到帶有ETag:'14-389247298365'字段的響應頭后,會在后面的請求中將其設置在請求頭中:If-None-Match: '14-389247298365'。服務器端收到帶If-None-Match: '14-389247298365'的報頭后,會進行如下判斷來決定返回新的內容還是只響應一個304狀態碼讓瀏覽器使用本地緩存版本:
1 var handle = function(req, res) { 2 fs.readFile(filename, function(err, file){ 3 var hash = getHash(file); 4 var noneMatch = req['if-none-match']; 5 if (hash === noneMatch) { 6 res.writeHead(304, "Not Modified"); 7 res.end(); 8 } else { 9 res.setHeader("ETag", hash); 10 res.writeHead(200, "OK"); 11 res.end(file); 12 } 13 }) 14 }2.?Last-Modified
通常來說,如果請求頭中不包含ETag,服務端會通過判斷Last-Modified值來決定響應304狀態碼還是新的文件內容。Last-Modified顧名思義指的是文件的最后一次修改時間。與ETag一樣,在瀏覽器首次訪問站點后,服務端會在其響應頭中設置一個Last-Modified的字段,它的值是一個UTC格式的時間字符串。隨后,在瀏覽器對站點的第二次訪問中,會在其請求頭中設置一個If-Modified-Since,其值就是上一次返回的Last-Modified的值。服務器端會根據這個值是否與其本地文件的最后一次修改時間相同來判斷是否使用緩存。代碼如下:
3. Expires 和 Cache-Control
以上兩種的緩存判斷都需要客戶端向服務端先發送一個條件請求,根據返回來決定是否使用緩存。需要一定的時間開銷和帶寬。而實際上瀏覽器最先判斷的是Expires 和 Cache-Control。在服務端相應里設置Expires 或 Cache-Control,瀏覽器會根據該值進行緩存。Expires是一個GMT格式的時間字符串。瀏覽器再接收到這個過期值后,只要本地還存在對應緩存文件,在到期時間之前它都不會再發起請求。但它的缺陷是瀏覽器與服務器之間的時間可能不一致,導致文件提前過期或已經過期卻還沒刪除。
而Cache-Control恰恰解決了這個問題:
1 var handle = function(req, res) { 2 fs.readFile(filename, function(err, file){ 3 res.setHeader("Cache-Control", "max-age=" + 10*365*24*60*60); 4 res.writeHead(200, "OK"); 5 res.end(file); 6 }); 7 }上面的代碼為Cache-Control設置了max-age值為10年,max-age會告訴瀏覽器文件多長時間后過期,進行倒計時式的計算。這樣就可以避免客戶端與服務器端時間不一致帶來的問題了。此外Cache-Control還可以public、private、no-cache、no-store等更精細地控制緩存的選項。HTTP1.0時還不支持max-age,如今的服務端在模塊的支持下多半同時對Expires 和 Cache-Control進行支持,如果瀏覽器中兩個值都存在且同時被支持,max-age會覆蓋Expires。
這兩種方法雖然節省了帶寬和請求時間,但其缺陷是當服務端的文件內容進行了更新時,無法通知客戶端更新。因為瀏覽器是根據URL進行緩存的,所以我們一般在對靜態資源使用緩存時也會對其設定版本號。使得客戶端能請求到新的內容。一般更新機制有如下兩種方式:
- 每次發布,web應用或靜態資源的路徑中附帶對應的版本號:http://url.com/?v=20141216
- 每次發布,web應用或靜態資源的路徑中附帶文件內容的hash碼:http://url.com/?hash=sdasd4d
因為文件內容更新并不意味著新的版本。所以使用hash值得方式會更加妥當一些。
轉載于:https://www.cnblogs.com/WhiteCusp/p/4168304.html
總結
- 上一篇: 对KVC和KVO的理解
- 下一篇: drozer