1、Varnish簡介 html
2、Varnish特色web
3、Varnish系統結構正則表達式
4、Varnish日誌算法
5、Varnish的算法編程
6、VCL介紹後端
7、Varnish後端存儲瀏覽器
8、VCL內置函數緩存
9、VCL內置公用變量bash
10、Http與緩存相關的經常使用首部服務器
1、Varnish簡介
Varnish是一款高性能且開源的反向代理服務器和HTTP緩存加速器;它 的做者Poul-Henning Kamp是FreeBSD的內核開發者之一,他認爲如今的計算機比起1975年已經複雜許多。在1975年時,儲存媒介只有兩種:內存與硬盤。但如今計算機系統的內存除了主存外,還包括了CPU內的L一、L2,甚至有L3快取。硬盤上也有本身的快取裝置,所以Squid Cache自行處理物件替換的架構不可能得知這些狀況而作到最佳化,但操做系統能夠得知這些狀況,因此這部份的工做應該交給操做系統處理,這就是 Varnish cache設計架構。
2、Varnish特色
一、是基於內存緩存,重啓後數據將消失 |
二、利用虛擬內存方式,io性能好 |
三、支持設置0~60秒內的精確緩存時間 |
四、VCL配置管理比較靈活 |
五、32位機器上緩存文件大小爲最大2G |
六、具備強大的管理功能,例如top,stat,admin,list等 |
七、狀態機設計巧妙,結構清晰 |
八、利用二叉堆管理緩存文件,達到積極刪除目的 |
3、Varnish系統結構
Varnish主要有兩個進程:Management與Child進程(也稱爲Cache進程);以下圖:
Management進程主要實現了應用新更新的配置,編譯VCL配置、監控Varnish、初始化Varnish及提供一個管理接口等;Management進程會每隔一段時間檢測一下Child進程是否運行正常,若是在指定的時間內沒有響應則Memagement會重啓Child進程
4、Varnish日誌
爲了與系統的其它部分進行交互,Child進程使用了能夠經過文件系統接口進行訪問的共享內存日誌(shared memory log),所以,若是某線程須要記錄信息,其僅須要持有一個鎖,然後向共享內存中的某內存區域寫入數據,再釋放持有的鎖便可。而爲了減小競爭,每一個worker線程都使用了日誌數據緩存。共享內存日誌大小通常爲90M,其分爲兩部分,前一部分爲計數器,後半部分爲客戶端請求的數據。varnish提供了多個不一樣的工具如varnishlog、varnishncsa或varnishstat等來分析共享內存日誌中的信息並可以以指定的方式進行顯示
5、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,當其傾向於使用後端主機不可用時將會從新挑選新的後端其機。
6、VCL介紹
Varnish Configuration Language (VCL)是varnish配置緩存策略的工具,它是一種基於「域」(domain specific)的簡單編程語言,可使用指定運算符:「=」,比較運算符「==」,邏輯運算符「!,&&,!!」等;支持使用正則表達式進行字符串匹配、容許用戶使用set自定義變量、支持if判斷語句,也有內置的函數和變量等;VCL策略在啓用前,會由management進程將其轉換爲C代碼,然後再由gcc編譯器將C代碼編譯成二進制程序。編譯完成後,management負責將其鏈接至varnish實例,即child進程
7、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} |
8、VCL內置函數
一、vcl_recv函數
用於接收和處理請求,當請求到達併成功接收後被調用,經過判斷請求的數據來決定如何處理請求。
此函數通常以以下幾個關鍵字結束:
pass:表示進入pass模式,把請求控制權交給vcl_pass函數。
pipe:表示進入pipe模式,把請求控制權交給vcl_pipe函數。
error code [reason]:表示返回「code」給客戶端,並放棄處理該請求,「code」是錯誤標識,例如200、405等,「reason」是錯誤提示信息。
二、vcl_pipe函數
此函數在進入pipe模式時被調用,用於將請求直接傳遞至後端主機,在請求和返回的內容沒有改變的狀況下,將不變的內容返回給客戶端,直到這個連接關閉
此函數通常以以下幾個關鍵字結束:
error code [reason]
pipe
三、vcl_pass函數
此函數在進入pass模式時被調用,用於將請求直接傳遞至後端主機,後端主機應答數據後送給客戶端,但不進行任何緩存,在當前鏈接下每次都返回最新的內容
此函數通常以以下幾個關鍵字結束:
error code [reason]
pass
四、lookup
表示在緩存裏查找被請求的對象,而且根據查找的結果把控制權交給函數vcl_hit或者函數vcl_miss
五、vcl_hit函數
在執行lookup指令後,若是在緩存中找到請求的內容,將自動調用該函數
此函數通常以以下幾個關鍵字結束:
deliver:表示將找到的內容發送給客戶端,並把控制權交給函數vcl_deliver
error code [reason]
pass
六、vcl_miss函數
在執行lookup指令後,若是沒有在緩存中找到請求的內容時自動調用該方法,此函數能夠用於判斷是否須要從後端服務器取內容
此函數通常以以下幾個關鍵字結束:
fetch:表示從後端獲取請求的內容,並把控制權交給vcl_fetch函數
error code [reason]
pass
七、vcl_fetch函數
在從後端主機更新緩存而且獲取內容後調用該方法,接着,經過判斷獲取的內容來決定是否將內容放入緩存,仍是直接返回給客戶端
此函數通常以以下幾個關鍵字結束:
error code [reason]
pass
deliver
八、vcl_deliver函數
在緩存中找到請求的內容後,發送給客戶端前調用此方法。此函數通常以以下幾個關鍵字結束:
error code [reason]
deliver
九、vcl_timeout 函數
此函數在緩存內容到期前調用。通常以以下幾個關鍵字結束:
discard:表示從緩存中清除該內容。
fetch
十、vcl_discard函數
在緩存內容到期後或緩存空間不夠時,自動調用該方法,通常以以下幾個關鍵字結束:
keep:表示將內容繼續保留在緩存中
discard
下面以一張VCL處理流程圖來VCL函數介紹,對以上VCL函數有一個瞭解以後,再來看每一個函數之間是如何關聯的:
處理過程大體分爲以下幾個步驟:
Receive 狀態: | 也就是請求處理的入口狀態,根據VCL規則判斷該請求應該是Pass或Pipe, 或者進入Lookup(本地查詢) |
Lookup 狀態: | 進入此狀態後,會在hash表中查找數據,若找到,則進入Hit狀態,不然進入miss狀態 |
Pass 狀態: | 在此狀態下,會進入後端請求,即進入fetch狀態 |
Fetch 狀態: | 在Fetch狀態下,對請求進行後端的獲取,發送請求,得到數據,並進行本地的存儲 |
Deliver 狀態: | 將獲取到的數據發送給客戶端,而後完成本次請求 |
9、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、30二、504等 |
obj.cacheable | 返回的內容是否能夠緩存,也就是說,若是HTTP返回 是200、20三、300、30一、30二、40四、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首部
10、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的安裝配置;敬請關注...