varnish緩存策略及緩存時間計算方法說明

jopen 10年前發布 | 21K 次閱讀 Varnish 緩存服務器

varnish作為緩存服務提供者,本身沒有內容,所有內容都是從后端的服務器或其它緩存服務器上取過來的。當varnish收到這些內容之后,需要根椐一定的策略確定是否緩存它,如果需要緩存,還需要確定可以緩存的時間。

1、varnish緩存策略

缺省是根椐后端返回的http狀態碼決定是否緩存。可以緩存的狀態碼如下:

200   
203   
300   
301   
302   
410   
404   

varnish現在還不支持ranges請求,所以不會緩存206狀態的結果。

管理員可以在vcl的配置文件中的vcl_fetch部分,加入自已的緩存策略,方法是修改beresp.cacheable變量。下面的例子,看后端返回中如果設置了cookie,則不緩存:

sub fetch {
    if (beresp.http.Set-Cookie) {
        set beresp.cacheable = false;
    }
}

2、緩存時間的計算方法

缺省的緩存時間計算方法如下:

先根椐max-age確定緩存時間

看返回頭中的Cache-Control頭中,有沒有指定s-maxage或max-age信息,另外,如果后端是一個緩存服務器,它還會指定一個age頭,表明已經緩存過的時間,這樣需要減去age頭指定的時間,計算出對應的緩存時間。

例1 只有max-age,沒有age

CacheControl: max-age=86400

緩存時間:86400秒,即一天

例2 同時有max-age和age信息

CacheControl: max-age=86400
Age: 6400

緩存時間:86400 - 6400 = 80000秒

. 如果沒有max-age信息,則根椐Expires頭部計算緩存時間

先看有沒有Date頭,
   如果沒有Date頭
      看expires指定的時間是否小于收到數據的時間
         小于,表明從后端取得內容已經過期,緩存時間為0,不緩存
         >=,則緩存到Expires指定的時刻再過期
   如果有Date頭
      看Expires指定的時間是否小于Date指定的時間
         小于,取到已經過期的內容,緩存時間為0,不緩存
         >=,則看Date時間跟取到內容的時間差別(判斷本機和后端的時鐘差異)
           小于clock_skew(缺省是10秒,管理員可以設置別的數值),以本機時間為準
              看Expires指定的時間是否小于收到數據的時間
                 小于,表明從后端取得的內容已經過期,緩存時間為0,不緩存
                 >=,則緩存到Expires指定的時刻再過期
           >= clock_skew,以后端的時間為準
             緩存時間為Expires - Date的差值

. 如果既沒有max-age信息,又沒有指定Expires過期信息

則按default_ttl(缺省是2分鐘,管理員可以設置成別的數值)設置緩存時間。

管理員可以在vcl的配置文件中的vcl_fetch部分,手工指定緩存時間,方法是修改beresp.ttl變量。下面的例子,將緩存時間設置成20分鐘(1200秒):

set beresp.ttl = 1200s;

3、給用戶返回已經過期的對象

varnish內部有一個grace模式。當后端不可用,或者已經向后端發過更新請求的情況下,別的客戶再請求這個對象時,會收到已經過期的版本,當然過期的時間在可接受的范圍內。

varnish缺省可接受的過期時間范圍是不超過10秒,可以修改params中的default_grace參數。修改這一數值,但這樣的改法相當于改了全局的參數,適應于所有請求。

如果想只修改特定的url對應的對象的grace時間范圍,則需要修改vcl配置,改兩個地方。首先需要修改vcl_recv過程,在收到用戶請求時指定可以接受過期對象的過期時間范圍。其次需要修改vcl_fetch過程,從后端取到內容時,設置對象過期后還可以保留的時間,這樣以便在過期后不會立即被后臺線程清理掉。

下面的例子針對特定的請求,將接受對象的grace時間設置為2分鐘。

       sub vcl_recv {
         set req.grace = 2m;
       }
       sub vcl_fetch {
         set beresp.grace = 2m;
       }

4、varnish對象過期之后的更新說明

對象過期之后,過了grace時間,就會被后臺線程清理掉。下一次用戶再去訪問的時候,會從后端重新抓取該對象。更合適的方法是發一個ims請求,如果后端對應的對象沒有更新就不抓。這一點squid處理得比varnish好。希望以后的版本能改進這一塊。

參考信息:
/bin/varnishd/cache_center.c的cnt_fetch函數
/bin/varnishd/rfc2616.c的RFC2616_Ttl函數
/bin/varnishd/cache_hash.c的HSH_Lookup函數

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!