緩存的新鮮度判斷——HTTP權威指南讀書心得(十二)


                                  緩存的新鮮度判斷

      這回主要來說一說緩存是如何進行新鮮度判斷的。上回書說到緩存中的每個資源都有它自己的保質期,我們稱之為新鮮度。當資源處於這個保質期之內,那么緩存就認為它是新鮮的,無需進行再次驗證就可以發送給客戶端。那么這個保質期是怎么定義的呢?而如果當保質期過了之后如何進行在驗證呢?

    資源過期

       通過 Cache-Control首部和expires首部,原始服務器可以對資源定義其保質期。在保質期之內,緩存就認為該資源是新鮮的,可以直接傳回給客戶端,如果過期那么就需要進行再驗證。

       Cache-Control首部和Expires首部其實定義的都是資源的過期時間,Cache-Control使用的是相對時間,而expires使用的是絕對時間,絕對時間依賴於計算機時鍾,所以建議使用Cache-Control首部。

       百度首頁這個事務使用的就是Expires首部,而 Cache-Control首部的形式是這樣的:

        Cache-Control:max-age=484200

       這個單位是秒。Expires首部比較好看懂,他就是表示過了這個日期這個資源就過期了。Cache-Control首部則表示從服務器生成該資源開始經過多少秒之后該資源過期。

     服務器再驗證

       資源過期了怎么辦?再驗證。怎么再驗證?為什么要再驗證?當緩存中的資源過期了以后,並不代表着這個資源真正的過期了,這個資源服務器有可能在這段時間內沒有進行過變更。所以為了驗證已經過期的資源是否真的不同了,就要進行再驗證。如果再驗證顯示資源發生了變化,那么緩存就會獲取一份新的資源副本。如果再驗證顯示資源沒有發生變化,那么緩存就只獲取新的首部,包括一個新的過期日期並對緩存中信息進行更新。

        HTTP協議要求緩存正確的返回以下內容之一:

  • 足夠新鮮的資源副本
  • 與服務器進行過再驗證,確認其仍然新鮮的資源副本
  • 如果需要進行再驗證的服務器出現了故障,則返回一條錯誤報文
  • 附有警告信息說明內容可能不正確的資源副本

        如何進行緩存驗證?

        http可以使用條件方法高效的再驗證。協議允許緩存向服務器發送一條條件GET,如果資源發生改變,則只返回相關報頭。如果資源發生了改變,則在相應報文中直接返回對應的資源對象。HTTP中定義了五個條件請求首部,其中If-Modified-Since和If-None-Match兩個首部了。

        If-Modified-Since:如果從指定日期之后資源被修改過了,那么就返回新的資源,可以與Last-Modified首部配合使用

        If-None-Match:服務器可以為每一個資源定義一個特定的標簽,如果說進行再驗證的副本資源的標簽與當前服務器上的標簽不同,則返回新的資源。

        最常用的是If-Modified-Since,If-Modified-Since請求一般被稱為IMS請求,由字面意思可知,它表明自某個日期之后資源發生了變換之后,服務器才會返回新的資源。如果自指定日期之后,資源被修改了,那么服務器就會返回一條包括新的首部新的過期日期和新的資源的響應報文。如果資源沒有被修改過,那么服務器就不會發送資源,只會發送新的報頭和過期時間,

        If-Modified-Since首部可以與Last-Modified首部配合使用,服務器會將最后修改時間附加到所回送的報文上去。當進行在驗證的時候,可以使用If-Modified-Since:(最后修改時間) 這種方式來進行驗證,這個就表示看該資源在上一次修改之后有沒有發生變化。如果資源沒有發生變化的話,服務器就會回送一個304 NOT Modified響應。

        有些服務器並沒有將If-Modified-Since中的信息當做時間進行比較,而是進行字符串匹配。這種方法驗證的是該資源是不是特定時間的資源了。這種方法能很好的識別出緩存是否過期,但是如果客戶端想用該時間做一些其他的真正基於時間的工作的話就會出現問題。

       有些情況下僅僅使用日期驗證是不夠的

        例如:有些文檔可能會進行周期性的重寫,但實際上並沒有發生變化。有些文檔發生了變化,但是這些變化並不重要,不需要緩存對其進行更新等等。遇到這種情況,就需要使用ETag和 If-None-Match進行在驗證了。可以把實體標簽比喻成資源的版本號,當進行在驗證的時候,就把緩存中的ETAG和服務器中資源的ETAG進行比較,看是否滿足要求,如果不匹配,那么就回送新的資源。

  

       If-None-Match首部可以包含幾個ETag,告訴服務器緩存中已經存在這些實體了。例如:

       If-None-Match:“v1.0”,“v1.1”,“v1.2”

       強弱驗證器

       有時候,服務器希望在對文檔進行一些非實質性的或者不重要的更改時,不需要使所有的緩存都失效,那么就可以使用弱驗證器。例如版本號在v2.6之下的,如v2.63等都看做它是新鮮的。那么如何使用弱驗證器呢?例子:

       ETag:W/"v1.0"

       If-None-Match:W/“v1.0”

      (只要加W/就好了。)

       原始服務器一定不能為兩個不同的實體重用一個特定的強實體標簽值,或者為兩個語義不同的實體重用一個特定的弱實體標簽值,因為副本在緩存內留存的時間不固定,容易發生沖突。

       什么時候使用實體標簽和最近修改日期呢?

       如果服務器回送一個ETag,客戶端就必須使用實體標簽驗證器了,如果服務器回送了一個Last-Modified值,客戶端就可以使用 If-Modified-Since驗證。如果都提供了的話,那么就都可以使用了。

       除非HTTP/1.1原始服務器無法生成實體標簽驗證器,否則就應該發送一個出去。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM