varnish原理精解

一、Varnish簡介

二、Varnish特點

三、Varnish系統結構

四、Varnish日誌

五、Varnish的算法

六、VCL介紹

七、Varnish後端存儲

八、VCL內置函數

九、VCL內置公用變量

十、Http與緩存相關的常用首部


一、Varnish簡介

Varnish是一款高性能且開源的反向代理服務器和HTTP緩存加速器;它 的作者Poul-Henning Kamp是FreeBSD的內核開發者之一,他認爲現在的計算機比起1975年已經複雜許多。在1975年時,儲存媒介只有兩種:內存與硬盤。但現在計算機系統的內存除了主存外,還包括了CPU內的L1、L2,甚至有L3快取。硬盤上也有自己的快取裝置,因此Squid Cache自行處理物件替換的架構不可能得知這些情況而做到最佳化,但操作系統可以得知這些情況,所以這部份的工作應該交給操作系統處理,這就是 Varnish cache設計架構。

二、Varnish特點

1、是基於內存緩存,重啓後數據將消失
2、利用虛擬內存方式,io性能好
3、支持設置0~60秒內的精確緩存時間
4、VCL配置管理比較靈活
5、32位機器上緩存文件大小爲最大2G
6、具有強大的管理功能,例如top,stat,admin,list等
7、狀態機設計巧妙,結構清晰
8、利用二叉堆管理緩存文件,達到積極刪除目的

三、Varnish系統結構

Varnish主要有兩個進程:Management與Child進程(也稱爲Cache進程);如下圖:

101020782.png

Management進程主要實現了應用新更新的配置,編譯VCL配置、監控Varnish、初始化Varnish及提供一個管理接口等;Management進程會每隔一段時間檢測一下Child進程是否運行正常,如果在指定的時間內沒有響應則Memagement會重啓Child進程

四、Varnish日誌

爲了與系統的其它部分進行交互,Child進程使用了可以通過文件系統接口進行訪問的共享內存日誌(shared memory log),因此,如果某線程需要記錄信息,其僅需要持有一個鎖,而後向共享內存中的某內存區域寫入數據,再釋放持有的鎖即可。而爲了減少競爭,每個worker線程都使用了日誌數據緩存。共享內存日誌大小一般爲90M,其分爲兩部分,前一部分爲計數器,後半部分爲客戶端請求的數據。varnish提供了多個不同的工具如varnishlog、varnishncsa或varnishstat等來分析共享內存日誌中的信息並能夠以指定的方式進行顯示

五、Varnish的算法

Varnish的director支持的挑選方法中比較簡單的有round-robin和random兩種。其中,round-robin類型沒有任何參數,只需要爲其指定各後端主機即可,挑選方式爲“輪叫”,並在某後端主機故障時不再將其視作挑選對象;random方法隨機從可用後端主機中進行挑選,每一個後端主機都需要一個.weight參數以指定其權重,同時還可以director級別使用.retires參數來設定查找一個健康後端主機時的嘗試次數。

2.1.0後,random挑選方法又多了兩種變化形式client和hash。client類型的director使用client.identity作爲挑選因子,這意味着client.identity相同的請求都將被髮送至同一個後端主機。client.identity默認爲cliet.ip,但也可以在VCL中將其修改爲所需要的標識符。類似地,hash類型的director使用hash數據作爲挑選因子,這意味着對同一個URL的請求將被髮往同一個後端主機,其常用於多級緩存的場景中。然而,無論是client還hash,當其傾向於使用後端主機不可用時將會重新挑選新的後端其機。

六、VCL介紹

Varnish Configuration Language (VCL)是varnish配置緩存策略的工具,它是一種基於“域”(domain specific)的簡單編程語言,可以使用指定運算符:“=”,比較運算符“==”,邏輯運算符“!,&&,!!”等;支持使用正則表達式進行字符串匹配、允許用戶使用set自定義變量、支持if判斷語句,也有內置的函數和變量等;VCL策略在啓用前,會由management進程將其轉換爲C代碼,而後再由gcc編譯器將C代碼編譯成二進制程序。編譯完成後,management負責將其連接至varnish實例,即child進程

七、Varnish後端存儲

varnish支持多種不同類型的後端存儲,這可以在varnishd啓動時使用-s選項指定。後端存儲的類型包括:

file:使用特定的文件存儲全部的緩存數據,並通過操作系統的mmap()系統調用將整個緩存文件映射至內存區域(如果條件允許)
malloc:使用malloc()庫調用在varnish啓動時向操作系統申請指定大小的內存空間以存儲緩存對象
persistent(experimental):與file的功能相同,但可以持久存儲數據(即重啓varnish數據時不會被清除);仍處於測試期

varnish無法追蹤某緩存對象是否存入了緩存文件,從而也就無從得知磁盤上的緩存文件是否可用,因此,file存儲方法在varnish停止或重啓時會清除數據。而persistent方法的出現對此有了一個彌補,但persistent仍處於測試階段,例如目前尚無法有效處理要緩存對象總體大小超出緩存空間的情況,所以,其僅適用於有着巨大緩存空間的場景。

選擇使用合適的存儲方式有助於提升系統性,從經驗的角度來看,建議在內存空間足以存儲所有的緩存對象時使用malloc的方法,反之,file存儲將有着更好的性能的表現。然而,需要注意的是,varnishd實際上使用的空間比使用-s選項指定的緩存空間更大,一般說來,其需要爲每個緩存對象多使用差不多1K左右的存儲空間,這意味着,對於100萬個緩存對象的場景來說,其使用的緩存空間將超出指定大小1G左右。另外,爲了保存數據結構等,varnish自身也會佔去不小的內存空間

爲varnishd指定使用的緩存類型時,-s 選項可接受的參數格式如下:
malloc[,size] 或 file[,path[,size[,granularity]]] 或 persistent,path,size {experimental}

八、VCL內置函數

1、vcl_recv函數
用於接收和處理請求,當請求到達併成功接收後被調用,通過判斷請求的數據來決定如何處理請求。
此函數一般以如下幾個關鍵字結束:
pass:表示進入pass模式,把請求控制權交給vcl_pass函數。
pipe:表示進入pipe模式,把請求控制權交給vcl_pipe函數。
error code [reason]:表示返回“code”給客戶端,並放棄處理該請求,“code”是錯誤標識,例如200、405等,“reason”是錯誤提示信息。
2、vcl_pipe函數
此函數在進入pipe模式時被調用,用於將請求直接傳遞至後端主機,在請求和返回的內容沒有改變的情況下,將不變的內容返回給客戶端,直到這個鏈接關閉
此函數一般以如下幾個關鍵字結束:
error code [reason]
pipe
3、vcl_pass函數
此函數在進入pass模式時被調用,用於將請求直接傳遞至後端主機,後端主機應答數據後送給客戶端,但不進行任何緩存,在當前連接下每次都返回最新的內容
此函數一般以如下幾個關鍵字結束:
error code [reason]
pass
4、lookup
表示在緩存裏查找被請求的對象,並且根據查找的結果把控制權交給函數vcl_hit或者函數vcl_miss
5、vcl_hit函數
在執行lookup指令後,如果在緩存中找到請求的內容,將自動調用該函數
此函數一般以如下幾個關鍵字結束:
deliver:表示將找到的內容發送給客戶端,並把控制權交給函數vcl_deliver
error code [reason]
pass
6、vcl_miss函數
在執行lookup指令後,如果沒有在緩存中找到請求的內容時自動調用該方法,此函數可以用於判斷是否需要從後端服務器取內容
此函數一般以如下幾個關鍵字結束:
fetch:表示從後端獲取請求的內容,並把控制權交給vcl_fetch函數
error code [reason]
pass
7、vcl_fetch函數
在從後端主機更新緩存並且獲取內容後調用該方法,接着,通過判斷獲取的內容來決定是否將內容放入緩存,還是直接返回給客戶端
此函數一般以如下幾個關鍵字結束:
error code [reason]
pass
deliver
8、vcl_deliver函數
在緩存中找到請求的內容後,發送給客戶端前調用此方法。此函數一般以如下幾個關鍵字結束:
error code [reason]
deliver
9、vcl_timeout 函數
此函數在緩存內容到期前調用。一般以如下幾個關鍵字結束:
discard:表示從緩存中清除該內容。
fetch
10、vcl_discard函數
在緩存內容到期後或緩存空間不夠時,自動調用該方法,一般以如下幾個關鍵字結束:
keep:表示將內容繼續保留在緩存中
discard

下面以一張VCL處理流程圖來VCL函數介紹,對以上VCL函數有一個瞭解之後,再來看每個函數之間是如何關聯的:

153839933.png

處理過程大致分爲如下幾個步驟:

Receive 狀態:

也就是請求處理的入口狀態,根據VCL規則判斷該請求應該是Pass或Pipe

或者進入Lookup(本地查詢)

Lookup 狀態:進入此狀態後,會在hash表中查找數據,若找到,則進入Hit狀態,否則進入miss狀態
Pass 狀態: 在此狀態下,會進入後端請求,即進入fetch狀態
Fetch 狀態:在Fetch狀態下,對請求進行後端的獲取,發送請求,獲得數據,並進行本地的存儲
Deliver 狀態:將獲取到的數據發送給客戶端,然後完成本次請求

九、VCL內置公用變量

VCL內置的公用變量可以用在不同的VCL函數中使用,根據這些公用變量使用的不同階段,如下介紹:

當請求到達後,可以使用的公用變量如下所示:
公用變量名稱含義
req.backend 指定對應的後端主機
server.ip 表示服務器端IP
client.ip 表示客戶端IP
req.request指定請求的類型,例如GET、HEAD、POST等
req.url指定請求的地址
req.proto表示客戶端發起請求的HTTP協議版本
req.http.header表示對應請求中的http頭部信息
req. restarts表示請求重啓的次數,默認最大值爲4

Varnish 在向後端主機請求時,可以使用的公用變量如下所示:
公用變量名稱含義
beresp.request指定請求的類型,例如GET、HEAD等
beresp.url指定請求的地址
beresp .proto表示客戶端發起請求的HTTP協議版本
beresp .http.header表示對應請求中的http頭部信息
beresp .ttl表示緩存的生存週期,也就是cache保留多長時間,單位是秒

從cache或者後端主機獲取內容後,可以使用的公用變量如下所示:
公用變量名稱含義
obj.status返回內容的請求狀態代碼,例如200、302、504等
obj.cacheable

返回的內容是否可以緩存,也就是說,如果HTTP返回

是200、203、300、301、302、404、410等,並且有非0的生存期,則可以緩存

obj.valid表示是否是有效的HTTP應答
obj.response返回內容的請求狀態信息
obj.proto返回內容的HTTP協議版本
obj.ttl返回內容的生存週期,也就是緩存時間,單位是秒
obj.lastuse返回上一次請求到現在的間隔時間,單位是秒

對客戶端應答時,可以使用的公用變量如下所示
公用變量名稱含義
resp.status返回客戶端的HTTP狀態代碼
resp.proto返回客戶端的HTTP協議版本
resp.http.header返回客戶端的HTTP頭部信息
resp.response返回客戶端的HTTP狀態信息

上面主要介紹了一些常用的VCL內置公用變量,如果想要了解更多請查閱Varnish官方文檔 查看文檔


如果想要精確熟練的配置緩存,需要對Http協議有個詳細瞭解,這裏只介紹一些常用的與緩存相關的Http首部

十、Http與緩存相關的常用首部

Expires:指定WEB對象的過期時間,不宜設置緩存時間過長

Cache-Control:定義所有緩存機制必須遵循的緩存指示,包括如下一些指令:

max-age=[seconds]:執行緩存被認爲是最新的最長時間。類似於過期時間,這個參數是基於請求時間的相對時間間隔,而不是絕對過期時間

s-maxage=[seconds]:類似於max-age屬性,除了他應用於共享(如:代理服務器)緩存

public:響應被緩存,並且在多用戶之間共享

no-cache:強制每次請求直接發送給源服務器,而不經過本地緩存

no-store:絕對禁止緩存,用於一些敏感數據

Must-revalidate:保證緩存的數據都是最新的,會到服務器端驗證當前數據是不是最新的數據

proxy-revalidate:和must-revalidate類似,除了他只對緩存代理服務器起作用

Etag:響應首部,是實體標籤(EntityTag)的縮寫,用於在響應報文中爲某web資源定義版本標識符

Last-Mofified:響應首部,用於迴應客戶端關於Last-Modified-Since或If-None-Match首部的請求,以通知客戶端其請求的web對象最近的修改時間

If-Modified-Since:條件式請求首部,如果在此首部指定的時間後其請求的web內容發生了更改,則服務器響應更改後的內容,否則就響應304狀態碼(not modified);

If-None-Match:條件式請求首部;web服務器爲某web內容定義了Etag首部,客戶端請求時能獲取並保存這個首部的值(即標籤);而後在後續的請求中會通過If-None-Match首部附加其認可的標籤列表並讓服務器端檢驗其原始內容是否有可以與此列表中的某標籤匹配的標籤;如果有,則響應304,否則,則返回原始內容

Vary:響應首部,原始服務器根據請求來源的不同響應的可能會有所不同的首部,最常用的是Vary: Accept-Encoding,用於通知緩存機制其內容看起來可能不同於用戶請求時Accept-Encoding-header首部標識的編碼格式

Age:緩存服務器可以發送的一個額外的響應首部,用於指定響應的有效期限;瀏覽器通常根據此首部決定內容的緩存時長;如果響應報文首部還使用了max-age指令,那麼緩存的有效時長爲“max-age減去Age”的結果

下面以實際請求與響應報文來介紹:

######打開百度的請求報文信息
----------------------------------------------------------------------
Request URL:http://www.baidu.com/        #請求的URL
Request Method:GET                       #請求方法
Status Code:200 OK                       #狀態碼
Request Headers    view source       
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 #通知服務器可以發送的類型
Accept-Encoding:gzip,deflate,sdch        #通知服務器可以發送的編碼方式
Accept-Language:zh-CN,zh;q=0.8           #通知服務器可以發送的語言
Cache-Control:max-age=0                  #報文傳送緩存指示
Connection:keep-alive                    #保持長連接狀態
Cookie:BAIDUID=6CB063786195FA7025F715DDACDB9D32:FG=1; BDSVRTM=5; H_PS_PSSID=3524_2777_1464_3421_2975_3090_3501_3439  #Cookie,服務器存儲在客戶端的信息
Host:www.baidu.com                       #主機地址
Referer:http://baidu.com/        
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.76 Safari/537.36 #將發起請求的應和程序名稱告知服務器,也就是瀏覽器

######打開百度的響應報文信息
----------------------------------------------------------------------
Response Headers    view source
BDPAGETYPE:1                     
BDQID:0xf06adb8c076aa3fa
BDUSERID:0
Cache-Control:private                  #緩存指示
Connection:Keep-Alive                  #狀態爲保持連接
Content-Encoding:gzip                  #對主體執行的編碼方式爲gzip
Content-Length:4386                    #響應主體內容的長度爲4386個字節
Content-Type:text/html;charset=utf-8   #響應類型爲HTML文本,編碼類型爲utf-8
Date:Sun, 06 Oct 2013 03:35:47 GMT     #響應的時間日期
Expires:Sun, 06 Oct 2013 03:35:47 GMT  #實體不在有效,要從原始的源端再次獲取此實體的日期和時間
Server:BWS/1.0    #服務器應用程序軟件的名稱和版本 BWS/1.0
Set-Cookie:BDSVRTM=2; path=/    #設置cookie,path
Set-Cookie:H_PS_PSSID=3524_2777_1464_3421_2975_3090_3501_3439; path=/; domain=.baidu.com    #設置cookie,path,domain都是cookie的信息(作用範圍等等)

到此,Varnish的基本原理已經講清楚了,下一篇博客將會寫Varnish的安裝配置;敬請關注...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章