日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

高性能缓存服务器Varnish详解

發布時間:2025/3/21 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 高性能缓存服务器Varnish详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、簡介

? ?Varnish是一款高性能的開源HTTP加速器,挪威最大的在線報紙 Verdens Gang 使用3臺Varnish代替了原來的12臺Squid,性能比以前更好。

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

? ?varnish項目是2006年發布的第一個版本0.9.距今已經八年多了,此文檔之前也提過varnish還不穩定,那是2007年時候編寫的,經過varnish開發團隊和網友們的辛苦耕耘,現在的varnish已經很健壯。很多門戶網站已經部署了varnish,并且反應都很好,甚至反應比squid還穩定,且效率更高,資源占用更少。相信在反向代理,web加速方面,varnish已經有足夠能力代替squid。

? ?varnish的官網為https://www.varnish-cache.org,rpm,rpm包的下載位置為:http://repo.varnish-cache.org。

二、關于Varnish

1.varnish系統架構

? ?varnish主要運行兩個進程:Management進程和Child進程(也叫Cache進程)。

? ?Management進程主要實現應用新的配置、編譯VCL、監控varnish、初始化varnish以及提供一個命令行接口等。Management進程會每隔一段時間探測一下Child進程以判斷其是否正常運行,如果在指定的時長內未得到Child進程的回應,Mangagement將會重啟此Child進程。

? ?Child進程包含多種類型的線程,常見的如:

? ? ? ?Acceptor進程:接受新的連接請求并響應

? ? ? ?worker進程:child進程會為每個用戶啟動一個worker進程,因此,在高并發的場景中可能會出現數百個worker進程甚至更多

? ? ? ?Expiry進程:從緩存中清理過期內容

? ? ? ?Varnish依賴“工作區(workspace)”以降低線程在申請或修改內存時出現競爭的可能性。在varnish內部有多種不同的工作區,其中最關鍵的當屬用于管理會話數據的session工作區

2.varnish日志

? ?為了與系統的其他部分進行交互,Child進程使用了可以通過文件系統接口進行訪問的共享內存日志(shared memory log),因此,如果某線程需要記錄信息,其僅需要持有一個鎖,而后向共享內存中的某內存區域寫入數據,再釋放持有的鎖即可。而為了減少競爭,每個worker線程都使用了日志數據緩存

? ?共享內存大小一般為90M,其分為兩部分,前一部分為計數器,后半部分為客戶端請求的數據。varnish通過了多個不同的工具,如varnishlog、varnishncsa或varnishstst等來分析共享內存日志中的信息并能夠以指定的方式進行顯示

? ?3.varnish的后端存儲

? ? ?varnish支持多種不同類型的后端存儲。這可以在varnish啟動時使用-s選項指定。后端存儲的類型包括

? ? ?(1)file:使用特定的文件存儲全部的緩存數據,并通過操作系統的mmap()系統調用整個緩存文件映射至內存區域(如果條件允許)

? ? ?(2)mallco: 使用mallco()庫調用在varnish啟動時向操作系統申請指定的大小的內存空間以存儲緩存數據

? ? ?(3)persistent(experimental):與file的功能相同,但是可以持久存儲數據(即重啟varnish時數據不會被清楚),仍處于測試階段

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

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

? ? 為varnish指定使用的緩存類型時,-s選項可接受的參數格式如下:

? ? ? ?malloc[,size]或file[,path[,size[,granularity]]]或persistent,path,size{experimental}

三、VCL

? ?1.簡介

? ? ?VCL(Varnish Configuration Language)是varnish配置緩存策略的工具,它是一種基于“域”(domain specific)的簡單編程語言,他支持有限的算術運算和邏輯運算操作、允許使用正則表達式進行字符串匹配、允許用戶使用set自定義變量、支持if判斷語句,也要內置的函數和變量等。使用VCL編寫的緩存策略通常保存至.vcl文件中,其需要編譯成二進制的格式后才能有varnish調用。事實上,整個緩存策略就是由幾個特定的子歷程如vcl_recv、vcl_fetch等組成,他們分別在不同的位置(或時間)執行,如果沒有實現為某個位置自定義子例程,varnish將會執行默認的定義

? ? VCL策略在啟用前,會由management進程將其轉換為C代碼,而后再有gcc編譯器將C代碼編譯成二進制程序。編譯完成后,management負責將其連接至varnish實例,即Child進程。正式由于編譯工作在child進程之外完成,它避免了轉載錯誤格式VCL的風險,因此,varnish修改配置的開銷非常小,其可以同時保有幾分尚在引用的舊版本配置,也能夠讓新的配置即刻生效,編譯后的舊版本配置通常在varnish重啟時才會被丟棄,如果需要手動清理,則可以使用varnishadm的vcl.discard命令來完成

2.VCL狀態引擎

? ? 在VCL狀態引擎中,狀態之間具有相關性,但彼此間互相隔離,每個引擎使用return(x)來退出當前狀態并指示varnish進入下一個狀態

? ? varnish開始處理一個請求時,首先需要分析HTTP請求本身,比如從首部獲取請求方法、驗證其是否為一個合法的HTTP請求等,當這些基本分析結束后就需要做出第一個決策,即varnish是否從緩存中查找請求的資源,這個決定的實現則需要有VCL來完成,簡單來說,要有vcl_recv方法來完成,如果說管理員沒有定義vcl_recv函數,varnish將會執行默認的vcl_recv函數,然而,即便管理員自定義了vcl_recv,但如果沒有為自定義的vcl_recv函數指定其終止操作(terminating),其仍將會指定默認的vcl_recv函數,事實上,varnish官方強烈建議讓varnish執行默認的vcl_recv以便處理自定義vcl_recv函數中可能出現的漏洞

3.VCL語法

? ? VCL的設計參考了C和perl語言,因此,對有著C或Perl編程經驗者來說,其非常容易理解。其基本語法說明如下:

? ? (1)//、#或/* comment */用于注釋

? ? (2)sub name 定義函數

? ? (3)不支持循環,有內置變量

? ? (4)使用終止語句,沒有返回值

? ? (5)域專用

? ? (6)操作符:=(賦值)、==(等值比較)、~(模式匹配)、!(非,取反)、&&(邏輯與)、||(邏輯或)

? ? VCL的函數不接受參數并且沒有返回值,因此,其并非真正意義上的函數,這也限定了VCL內部的數據傳遞只能隱藏在HTTP首部內部進行。VCL的return語句用于將控制權從VCL狀態引擎返回給varnish,而非默認函數,這就是為什么VCL只有終止語句而沒有返回值的原因,同時,對于每個“域”來說,可以定義一個或多個終止語句,以告訴varnish下一步采取何種操作,如查詢緩存或不查詢緩存

4.VCL的內置函數

? ? ?VCL提供了結果函數來實現字符串的修改,如添加bans,重啟VCL狀態引擎因將控制權轉回varnish等

? ? regsub(str,reget,sub):基于正則表達式搜索指定的字符串并將其替換成指定的字符串,只替換匹配到的第一個

? ? regsuball(str,reget,sub):基于正則表達式搜索指定的字符串并將其統統替換成指定的字符串

? ? ban(expression):

? ? ban_url(regex):Bans所有其URL能夠由regex匹配的緩存對象

? ? purge:從緩存中挑選出某對象以及其相關變種一并刪除,這可以通過通過HYTP協議的PURGE方法完成

? ? hash_data(str):

? ? return():當某個VCL與運行結束時,將控制權返回給Varnish,并指示Varnish如何進行后續的操作:其可以返回的指令包括:lookup、pass、pipe、hit_for_pass、fetch、deliver和hash等:但某特定域可能技能返回某些特定的指令,而非前面列出的全部指令:

? ? return(restart):重新運行整個VCL,即重新從vcl_recv開始進行處理;每一次重啟都會增加req.restaets變量中的值,而max_restaets參數則用于限定最大重啟次數

5.vcl_recv

? ? ?vcl_recv是在varnish完成對請求報文的解碼為基本數據結構后第一個要指定的子例程,他通常有四個主要用途:

? ? ?(1)修改客戶端數據以減少緩存對象差異性,比如刪除URL中的www.等字符串

? ? ? (2)基于客戶端數據選用緩存策略:比如僅緩存特定的額URL請求、不緩存POST請求等

? ? ?(3)為某web應用程序執行URL重寫

? ? ?(4)挑選合適的后端服務器;

? ? 可以使用下面的終止語句,即通過return()向varnish返回指示操作

? ? ? pass:繞過緩存,即不從緩存中查詢內容或不將內容存儲至緩存中;

? ? ? pipe:不對客戶端進行檢查或做出任何操作,而是在客戶端與后端服務器之間建立專業“通道”,并直接將數據在二者之間進行傳送:此時,keep-alive連接中后續傳送的數據也都將在通過此管道進行直接傳送,并不會出現在任何日志中

? ? ? lookup:在緩存中查找用戶請求的對象,如果緩存中沒有其指定的對象,后續操作很可能會將其請求的對象進行緩存

? ? ? error:有varnish自己合成一個響應報文,一般是響應一個錯誤類信息、重定向類信息或緩存均衡器返回的后端web服務器健康狀態檢查類信息

? ? ?vcl_recv也可以通過精巧的策略完成一定意義上的安全功能,以將某特定的攻擊扼殺于搖籃中,同時,它也可以檢查出一些拼寫的錯誤并將其進行修改

? ? ?varnish默認的vcl_recv專門設計用來實現安全的緩策略,它主要完成兩種功能:

? ? ? ?(1)僅處理可以識別的HTTP方法,并且只緩存GET和HEAD方法

? ? ? ?(2)不緩存任何用戶特有的數據

? ? ?安全起見,一般都在自定義的vcl_recv中不要使用return()終止語句,而是再由默認vcl_recv進行處理,并有其做出響應的的處理決策

6.vcl_fetch

? ? ?如前面所述,想對于vcl_recv是根據客戶端的請求做出緩存策略來說,vcl_fetch則是根據服務器端的響應做出緩存決策,在任何VCL狀態引擎中發揮pass操作都將有vcl_fetch進行后續處理。vcl_fetch中有許多可用的內置變量,比如最常見的用于定義某對象緩存時長的beresp.ttl變量,通過return()返回給varnish的操作指令有:

? ? ? ?deliver:緩存此對象,并將其發送給客戶端(經由vcl_deliver)

? ? ? ?hit_for_pass:不緩存此對象,但可以導致后續對此對象的請求直接送達到vcl_pass進行處理

? ? ? ?restart:重啟整個VCL,并增加重啟次數,超出max_restarts限定的最大重啟次數將會發揮錯誤信息

? ? ? ?error code [reson]:返回指定的錯誤代碼給客戶端并丟棄此請求,“code”是錯誤標識,例如200、405等,“reason”是錯誤提示信息。

? ? ? 默認的vcl_fetch放棄了緩存任何使用了Set-Cookie首部的響應

7.vcl_deliver

? ? ?在緩存中找到緩存內容,發送給客戶端時調用此參數,通過return()返回給varnish的操作指令有: ?

? ? ? ?deliver:緩存此對象,并將其發送給客戶端(經由vcl_deliver)

? ? ? ?error code [reson]:返回指定的錯誤代碼給客戶端并丟棄此請求,“code”是錯誤標識,例如200、405等,“reason”是錯誤提示信息。

8.val_pass

? ? ? 此函數在進入pass模式時被調用,用于將請求直接傳遞至后端主機,后端主機應答數據后發送給客戶端,但是不緩存任何數據,在當前連接下,每次都是犯回最新的內容,通過return()返回給varnish的操作指令有: ?

? ? ? ? error code [reson]:返回指定的錯誤代碼給客戶端并丟棄此請求,“code”是錯誤標識,例如200、405等,“reason”是錯誤提示信息。

? ? ? ? pass:繞過緩存,即不從緩存中查詢內容或不將內容存儲至緩存中;

9.vcl_pipe

? ? ? ?不對客戶端進行檢查或做出任何操作,而是在客戶端與后端服務器之間建立專業“通道”,并直接將數據在二者之間進行傳送:此時,keep-alive連接中后續傳送的數據也都將在通過此管道進行直接傳送,并不會出現在任何日志中,通過return()返回給varnish的操作指令有: ?

? ? ? ? ?error code [reson]:返回指定的錯誤代碼給客戶端并丟棄此請求,“code”是錯誤標識,例如200、405等,“reason”是錯誤提示信息。

? ? ? ? pipe:不對客戶端進行檢查或做出任何操作,而是在客戶端與后端服務器之間建立專業“通道”,并直接將數據在二者之間進行傳送:此時,keep-alive連接中后續傳送的數據也都將在通過此管道進行直接傳送,并不會出現在任何日志中

10.lookup

? ? ? 表示在緩存里查找被請求的對象,并且根據查找的數據把控制權交給vcl_miss或vcl_hit

11.vcl_hit

? ? ? ?在執行lookup指令后,如果在緩存中找到請求的內容,將自動調用此函數,通過return()返回給varnish的操作指令有:

? ? ? ? deliver:緩存此對象,并將其發送給客戶端(經由vcl_deliver)

? ? ? ? error code [reson]:返回指定的錯誤代碼給客戶端并丟棄此請求,“code”是錯誤標識,例如200、405等,“reason”是錯誤提示信息。

? ? ? ? ?pass:繞過緩存,即不從緩存中查詢內容或不將內容存儲至緩存中;

12.vcl_miss函數

? ? ? 在執行lookup指令后,如果在緩存中找不到請求的內容,將自動調用此函數,此函數可以判斷是否在后端服務器上獲取內容,通過return()返回給varnish的操作指令有:

? ? ? ? ?error code [reson]:返回指定的錯誤代碼給客戶端并丟棄此請求,“code”是錯誤標識,例如200、405等,“reason”是錯誤提示信息。

? ? ? ? ?pass:繞過緩存,即不從緩存中查詢內容或不將內容存儲至緩存中;

13.VCL處理流程圖

? ? ? ?通過上面對VCL函數的介紹,大家應該對每個函數實現的功能有一個了解,,起始每個函數之間是有聯系的,如下圖所示

四、與緩存相關的HTTP首部

? ?HTTP協議提供了很多個首部以實現頁面緩存及緩存失效的相關功能,這其中常用的有:

?1.Expires

? ? ? ? 用于指定某web對象的過期時間/日期,通常為GMT格式,一般不應該將此設定的未來過長的時間,一年的長度對大多數場景來說足矣,其常用于為靜態內容或JavaScript樣式表或圖片指定緩存周期

2.Cache-Control

? ? ? ?用于定義所有的緩存機制都必須遵循的緩存指示,這些指示是一些特定的指令,包括pubilc、private、no-cache(表示可以存儲,但在重新驗證其有效性之前不能用于響應客戶端請求)、no-store、max-age、s-maxage以及must-revalidate等,Cache-Control中設定的時間會覆蓋Expires中指定的時間

3.Etag

? ? ? ? 響應首部,用于子啊響應報文中為某web資源定義版本標識符

4.Last-Mofified

? ? ? ? 響應報文,用戶回應客戶端關于Last-Mofified-Since或If-None-Match首部的請求,以通知客戶端其請求的web對象最近修改時間

5.Last-Mofified-Since

? ? ? ?條件式請求首部,如果在此首部指定的時間后其請求的web內容發生了更改,則服務器響應更改后的內容,否則,則響應304(not modified)

6.If-None-Match

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

7.Vary

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

8.Age

? ? ? ?緩存服務器可以發送一個額外的響應首部,用于指定響應的有效期限,瀏覽器通常根據此首部絕對內容的緩存時長:如果響應報文中還使用了max-age指令,那么緩存的有效時長為max-age減去Age結果

五、安裝使用varnish

1.ip規劃與使用說明

? ? 192.168.1.201 varnish?

? ? 192.168.1.202 web(靜態頁面)

? ? 192.168.1.203 web(圖片服務器)

? ? 說明:本處安裝的varnish3.0.5系列的包,故本處使用的一些命令可能會不適用于varnish2系列和varnish4系列

2.下載與安裝

? ? ?可以使用rpm包的安裝方式,也可以使用源碼編譯安裝的方式,官方也提供有rpm,本處使用的為rpm安裝的方式

1 2 3 4 [root@node1 ~]# wget http://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/varnish-3.0.5-1.el6.x86_64.rpm [root@node1 ~]# wget http://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/varnish-libs-3.0.5-1.el6.x86_64.rpm [root@node1 ~]# wget http://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/varnish-docs-3.0.5-1.el6.x86_64.rpm [root@node1 ~]# rpm -ivh?varnish*

3.為192.168.1.202提供靜態頁面 ?

1 2 [root@node2 ~]# echo?"web1"?> /var/www/html/index.html [root@node2 ~]# service httpd start

4.修改varnish的啟動文件

1 2 3 4 5 [root@node1 ~]# vi /etc/sysconfig/varnish 修改一下參數 VARNISH_LISTEN_PORT=80?//表示將varnish對外的監聽端口改為80 VARNISH_STORAGE="malloc,100M"?//將數據緩存在內存中,內存大小為100M 其余的使用默認即可

5.配置varnish

? ? ?本處使用varnishadm命令行接口來刷新varnish

? ? ? 命令格式:varnishadm [-n ident] [-t timeout] [-S secretfile] -T [address]:port command [...]

? ? ? 通過命令行的方式連接至varnishd進行管理操作的工具,指定要連接的varnish實例有兩種方法:

? ? ? ?-T [address]:port 來接指定套接字上的實例

? ? ? ?-n ident 連接指定名稱的實例

? ? 其運行模式有兩種,當不在命令行中給出指定要指定的“command”時,要將進入交互模式,否則,varnish將指定指定的“command”并退出。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 [root@node1 ~]#?varnishadm -S /etc/varnish/secret -T?127.0.0.1:6082 help [command] ping [timestamp]??//ping節點是否在線 auth response quit banner status?//運行狀態 start??//統計數據 stop vcl.load <configname> <filename>?//加載某個文件,作為配置文件 vcl.inline <configname> <quoted_VCLstring> vcl.use?<configname>?//編譯當前的實例 vcl.discard <configname> vcl.list vcl.show <configname>?//查看當前的實例 param.show [-l] [<param>] param.set?<param> <value> panic.show panic.clear storage.list backend.list backend.set_health matcher state ban.url <regexp> ban <field> <operator> <arg> [&& <field> <oper> <arg>]... ban.list

? ? ? ?①、定義一個文件test.vcl,定義一個后端服務器為192.168.1.201,由于varnish不能查看是否命中緩存,并寫VCL,查看緩存是否能命中

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 backend web1 { ??.host="192.168.1.202";?//定義后端主機 ??.port="80";??//后端主機監聽的端口 } sub vcl_deliver{ ??if?(obj.hits >0?){ ????????set?resp.http.X-Cache=?"HIT from "?+ client.ip;?//如果命中,則顯示HIT from +客戶端ip地址 ????????}?else?{ ????????set?resp.http.X-Cache=?"MISS";?//否則顯示"MISS" ????????} } 編譯 varnish> vcl.load test1 test.vcl 200????? VCL compiled. varnish> vcl.use?test1 200

? ? ? ?測試

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 [root@node1 ~]# curl -I http://192.168.1.201/index.html HTTP/1.1?200?OK Server: Apache/2.2.15?(CentOS) Last-Modified: Wed,?23?Apr?2014?16:10:19?GMT ETag:?"20101-5-4f7b7f8092275" Content-Type: text/html; charset=UTF-8 Content-Length:?5 Accept-Ranges: bytes Date: Wed,?23?Apr?2014?16:49:38?GMT X-Varnish:?1409659707 Age:?0 Via:?1.1?varnish Connection: keep-alive X-Cache: MISS 第一次請求為MISS,表示沒有命中緩存 [root@node1 ~]# curl -I http://192.168.1.201/index.html HTTP/1.1?200?OK Server: Apache/2.2.15?(CentOS) Last-Modified: Wed,?23?Apr?2014?16:10:19?GMT ETag:?"20101-5-4f7b7f8092275" Content-Type: text/html; charset=UTF-8 Content-Length:?5 Accept-Ranges: bytes Date: Wed,?23?Apr?2014?16:49:38?GMT X-Varnish:?1409659707 Age:?0 Via:?1.1?varnish Connection: keep-alive X-Cache: HIT from?192.168.1.201 可以看到第二次請求命中,可以多請求幾次,以后每次都會是緩存命中

? ? ? ?②、比如說我們有一個test.html頁面不想緩存,

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 sub vcl_recv { ??if?(req.url ~?"^/test.html$"){ ????????return(pass); ?} } varnish> vcl.load test3 test.vcl 200????? VCL compiled. varnish> vcl.use?test3 200 我們請求test.html [root@node1 ~]# curl -I http://192.168.1.201/test.html HTTP/1.1?404?Not Found Server: Apache/2.2.15?(CentOS) Content-Type: text/html; charset=iso-8859-1 Accept-Ranges: bytes Date: Wed,?23?Apr?2014?16:55:26?GMT X-Varnish:?1409659726 Age:?0 Via:?1.1?varnish Connection: keep-alive X-Cache: MISS 可以看到第一次沒有命中 [root@node1 ~]# curl -I http://192.168.1.201/test.html HTTP/1.1?404?Not Found Server: Apache/2.2.15?(CentOS) Content-Type: text/html; charset=iso-8859-1 Accept-Ranges: bytes Date: Wed,?23?Apr?2014?16:55:27?GMT X-Varnish:?1409659727 Age:?0 Via:?1.1?varnish Connection: keep-alive X-Cache: MISS 可以看到第二次也沒有命中,請求多次都不會命中

? ? ? ?③、為每一種資源定義緩存時長

1 2 3 4 5 6 7 8 sub vcl_fetch { ?if?(req.request ==?"GET"?&& req.url ~?"\.html$"){ ????????set?beresp.ttl = 3600s; ????????} ?if?(req.request ==?"GET"?&& req.url ~?"\.{jpg|jpeg|png|gif}$"){ ????????set?beresp.ttl = 86400s; ????????} }

? ? ? ④、修剪緩存對象

? ? ? ?1.緩存內容修剪

? ? ? ?提高緩存命中率的最有效途徑之一是增加緩存對象的生存時間(TTL),但是這也可能會帶來副作用,比如緩存的內容在到達為其指定的有效期之前就已經失效,因此,手動檢查緩存對象的有效性或者刷新緩存是緩存很有可能稱為服務器管理員的日常工作之一,相應地,varnish為完成這類的任務提供了三種途徑:HTTP修剪(HTTP purging)、禁用某緩存對象(banning)和強制緩存未命中(forced cache misses)

? ? ? ?這里需要特殊說明的是,varnish2中的purge()操作在varnish3中被替換成了ban()操作,而varnish3也使用了purge操作,但未其賦予了新功能,且只能用于vcl_hit或vcl_miss中替換varnish2中重用的set obj.ttl=0s

? ? ? ?在具體執行某清理工作時,需要實現確認如下問題:

? ? ? ?僅需要檢驗一個特定的緩存對象,還是多個

? ? ? ?目的是釋放內存空間,還是僅替換緩存的內容

? ? ? ?是不是需要很長世間才能完成內容替換

? ? ? ?這類操作是個日常工作,還是僅此一次的特殊需求

? ? ? ?2.移除單個緩存對象

? ? ? ?purge用于清理緩存中的特定對象及其變種(variants),因此,在有著明確要修剪的緩存對象時可以使用此種方法,http協議的PURGE方法可以實現purge功能,不過,其僅能用于vcl_hit或vcl_miss中,它會釋放內存工作并移除指定緩存對象的所有vary變種,并期待下一個針對此內容的客戶端請求道此時刷新此內容,另外,其一般要與return(restart)一起使用。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 acl purgers { ????????"127.0.0.1"; ????????"192.168.1.0"/24; } sub vcl_recv { ????????if?(req.request ==?"PURGE") { ????????????????if?(!client.ip ~ purgers) { ????????????????????????error?405?"Method not allowed"; ????????????????} ????????????????return?(lookup); ????????} } sub vcl_hit { ????????if?(req.request ==?"PURGE") { ????????????????purge; ????????????????error?200?"Purged"; ????????} } sub vcl_miss { ????????if?(req.request ==?"PURGE") { ????????????????purge; ????????????????error?404?"Not in cache"; ????????} } sub vcl_pass { ????????if?(req.request ==?"PURGE") { ????????????????error?502?"PURGE on a passed object"; ????????} } 說明:一般把這一項應該放在最前面,以免被別的規則匹配到 varnish> vcl.load test6 test.vcl 200????? VCL compiled. varnish> vcl.use?test6 200 測試 [root@node1 ~]# curl -I http://192.168.1.201/index.html HTTP/1.1?200?OK Server: Apache/2.2.15?(CentOS) Last-Modified: Wed,?23?Apr?2014?16:10:19?GMT ETag:?"20101-5-4f7b7f8092275" Content-Type: text/html; charset=UTF-8 Content-Length:?5 Accept-Ranges: bytes Date: Wed,?23?Apr?2014?17:25:12?GMT X-Varnish:?1409659756?1409659755 Age:?1 Via:?1.1?varnish Connection: keep-alive X-Cache: HIT from?192.168.1.201 清除緩存 [root@node1 ~]# curl -X PURGE http://192.168.1.201/index.html <?xml version="1.0"?encoding="utf-8"?> <!DOCTYPE html PUBLIC?"-//W3C//DTD XHTML 1.0 Strict//EN" ?"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> ??<head> ????<title>200?Purged</title> ??</head> ??<body> ????<h1>Error?200?Purged</h1> ????<p>Purged</p> ????<h3>Guru Meditation:</h3> ????<p>XID:?1409659762</p> ????<hr> ????<p>Varnish cache server</p> ??</body> </html> 在請求測試 [root@node1 ~]# curl -I http://192.168.1.201/index.html HTTP/1.1?200?OK Server: Apache/2.2.15?(CentOS) Last-Modified: Wed,?23?Apr?2014?16:10:19?GMT ETag:?"20101-5-4f7b7f8092275" Content-Type: text/html; charset=UTF-8 Content-Length:?5 Accept-Ranges: bytes Date: Wed,?23?Apr?2014?17:27:35?GMT X-Varnish:?1409659763 Age:?0 Via:?1.1?varnish Connection: keep-alive X-Cache: MISS

? ? ? ?3.強制緩存為命中

? ? ? ?在VCL_RECV中使用return(pass)能夠強制到上游服務器取得請求內容,但這也會導致無法將其緩存,使用purge會移除就的緩存對象,但如果上游服務器宕機而無法取得新版本的內容時,此內容將無法在響應給客戶端。使用req.has_always_miss=ture,可以讓Varnish在緩存中搜尋相應的內容但卻總是回應“未命中”,于是vcl_miss將后續地負責啟動vcl_fetch從上游服務器取得新內容,并以新內容緩存覆蓋舊內容。此時,如果上游服務器宕機或未響應,舊的內容將保持原狀,并能夠繼續服務于那些未使用req.has_always_miss=true的客戶端,直到其過期失效或由其它方法移除。

? ? ? ?4、Banning

? ? ? ?ban()是一種從已緩存對象中過濾(filter)出某此特定的對象并將其移除的緩存內容刷新機制,不過,它并不阻止新的內容進入緩存或響應于請求。在Varnish中,ban的實現是指將一個ban添加至ban列表(ban-list)中,這可以通過命令行接口或VCL實現,它們的使用語法是相同的。ban本身就是一個或多個VCL風格的語句,它會在Varnish從緩存哈希(cache hash)中查找某緩存對象時對搜尋的對象進行比較測試,因此,一個ban語句就是類似匹配所有“以/downloads開頭的URL”,或“響應首部中包含nginx的對象”。例如:

? ? ? ?ban req.http.host == "wangfeng7399.com" && req.url ~ "\.gif$"

? ? ? ?定義好的所有ban語句會生成一個ban列表(ban-list),新添加的ban語句會被放置在列表的首部。緩存中的所有對象在響應給客戶端之前都會被ban列表檢查至少一次,檢查完成后將會為每個緩存創建一個指向與其匹配的ban語句的指針。Varnish在從緩存中獲取對象時,總是會檢查此緩存對象的指針是否指向了ban列表的首部。如果沒有指向ban列表的首部,其將對使用所有的新添加的ban語句對此緩存對象進行測試,如果沒有任何ban語句能夠匹配,則更新ban列表。

? ? ? ?對ban這種實現方式持反對意見有有之,持贊成意見者亦有之。反對意見主要有兩種,一是ban不會釋放內存,緩存對象僅在有客戶端訪問時被測試一次;二是如果緩存對象曾經被訪問到,但卻很少被再次訪問時ban列表將會變得非常大。贊成的意見則主要集中在ban可以讓Varnish在恒定的時間內完成向ban列表添加ban的操作,例如在有著數百萬個緩存對象的場景中,添加一個ban也只需要在恒定的時間內即可完成。其實現方法本處不再詳細說明。

? ? ? ?⑤、Varnish檢測后端主機的健康狀態

? ? ? ? varnish可以堅持后端主機的健康狀態,在判斷后端主機失效時能自動將其從可用后端主機列表中移除,而一旦其重新變得可用還可以自動給將其設定為可用。為了避免誤判,varnish在探測后端的健康狀態發生轉變時(比如某次探測是某后端主機突然變成不可以狀態),通常需要連續執行幾次探測均為新狀態才能將其標記為轉換后的狀態。

? ? ? ?每個后端服務器當前探測的方法通過.probe進行設定,其結果可由req.backend.healthy變量獲取,也可以通過varnishlog中的Backend_health查看或varnishadm的debug.health查看

? ? ? ?.probe中的探測指令常用的有:

? ? ? ? ? .url:探測后端主機監控狀態時請求的URL,默認為“/”

? ? ? ? ? .request:探測后端主機健康狀態時所請求內容的詳細格式,定義后,它會替換.url指定的探測方法

? ? ? ? ? .window:設定在判斷后端服務器健康狀態是基于最近多少次的探測進行,默認為8

? ? ? ? ? .threshold:在.window中指定的次數中,至少有多少次是成功的才判定后端主機正健康運行

? ? ? ? ? .initial:varnish啟動時對后端主機至少需要多少次的成功探測,默認同.threshold

? ? ? ? ? .expencted_response:期望后端主機響應的狀態碼,默認為200

? ? ? ? ? .interval:探測請求的發送周期,默認為5秒

? ? ? ? ? .timeout:每次探測請求的過期時長,默認為2秒

? ? ? ?如果varnish在某時刻沒有任何可用的后端主機,它將嘗試使用緩存對象的“寬容副本”(graced copy),擔任,此時VCL中的各種規則依然有效,因此,更好的辦法是在VCL規則中判斷req.backend.healthy變量顯示后端某主機不可用時,為此后端主機增大req.grace變量的值以設定適當的寬容期限長度。

? ? ? ?⑥、使用多臺后端主機

? ? ? ?varnish中可以使用director指令將一個或多個相似的后端主機定義為一個邏輯組,并可以指定調度方式(也叫挑選方法)來輪流將請求發送至這些主機上,不同的director可以使用同一個后端主機,而某director也可以使用“匿名”后端主機(在director中直接進行定義)。每個director都必須有其專用名,且在定義后必須在VCL中進行調用,VCL中任何可以指定后端主機的位置均可以按需將其替換為調用某已定義的director。

? ? ? ?varnish的dorector支持的挑選方法中比較簡單的有round-robin和random兩種,其中,round-robin類型沒有任何參數,挑選方法為“輪詢”,并在某后端主機故障時不在將其視為挑選對象,random方法隨機從可用后端主機中挑選,每一個后端主機都需要一個.wegith參數來指定其權重,同時還可以director級別使用.retires參數來設定查找一個健康后端主機時的嘗試次數

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

? ? ? ?另外還有一中成為fallback的director,用于定義備用服務器

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 backend web1 { ??.host="192.168.1.202"; ??.port="80"; ??.probe = { ????????.url="/index.html"; ????????.interval =2s; ????????.window =5; ????????.threshold=2 } } backend web2 { ??.host="192.168.1.203"; ??.port="80"; ??.probe = { ????????.url="/index.html"; ????????.interval =2s; ????????.window =5; ????????.threshold=2 } } 定義每個2s檢查后端主機的主頁,如果最近5次的探測請求中至少有2次是成功的就判斷此后端主機為正常工作狀態 director websv random { ??.retries =4; ??{ ?????.backend = web1; ?????.weight =2; } ??{ ?????.backend = web2; ?????.weight =4; } } 定義主機組 sub vcl_recv { set?req.backend =websv; } 調用主機組 [root@node1 ~]# curl http://192.168.1.201/index.html web1 我們將web1的httpd關掉 [root@node1 ~]# curl http://192.168.1.201/index.html web2

? ? ? ?⑦、后端服務器的分離

? ? ? ?varnish支持基于URL將后端的服務器分離 ?

1 2 3 4 5 6 7 8 9 在vcl_decv中添加如下行 ???????if?(req.url ~"\.(html)$"){ ???????????set?req.backend = web1; ????????}else{ ???????????set?req.backend = web2; ????????} 通過curl訪問index.html [root@node1 ~]# curl http://192.168.1.201/index.html web1

? ?我們只在web2上放置了頁面? 大功告成,由于本人水平有限,可能操作中有錯誤,請各位大神批評指正



本文轉自wangfeng7399 51CTO博客,原文鏈接:http://blog.51cto.com/wangfeng7399/1407418,如需轉載請自行聯系原作者


總結

以上是生活随笔為你收集整理的高性能缓存服务器Varnish详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。