varnish詳解3

1.Varnish簡介html

Varnish是一款高性能的反向代理服務器和HTTP加速器,它的開發者Poul-Henning Kamp是FreeBSD的核心開發成員。web

2.Varnish特色正則表達式

  • 基於內存進行緩存,數據在重啓後將消失;編程

  • 利用虛擬內存方式,I/O性能好;vim

  • 支持0-60s的精確緩存時間;後端

  • VCL配置管理靈活;緩存

  • 32位機器上緩存文件大小最大爲2GB;安全

  • 具備強大的管理功能,如top,stat,admin,list等。bash

3.Varnish與squid對比服務器

squid是一個高性能的代理緩存服務器。

相同點:都是反向代理服務器

不一樣點:

  • Varnish穩定性高,二者在完成相同負荷工做時,squid服務器發生故障概率高於Varnish。

  • Varnish訪問速度更快。Varnish採用「Visual Page Cache"技術,全部緩存數據直接從內存讀取,而squid是從硬盤讀取緩存數據,因此Varnish訪問速度更快。

  • Varnish能夠支持更多的併發鏈接,由於Varnish的TCP鏈接釋放比squid快,所以在高併發鏈接狀況下能夠支持更多的TCP鏈接。

  • Varnish能夠經過管理端口,使用正則表達式批量清除部分緩存,而squid作不到。

varnish缺點:

Varnish在高併發鏈接下CPU,I/O和內存等資源開銷要高於squid.

Varnish一旦重啓,緩存在內存中的數據都會從內存中釋放,這時全部請求都會發送到後端服務器,在高併發狀況下,會給後端服務器形成很大壓力。


4.Varnish系統架構

wKiom1V-5-qhSs3XAAHT87C6TXo291.jpg


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


Management進程主要實現應用新的配置、編譯VCL、監控varnish、初始化varnish以及提供一個命令行接口等。Management進程會每隔幾秒鐘探測一下Child進程以判斷其是否正常運行,若是在指定的時長內未獲得Child進程的迴應,Management將會重啓此Child進程。


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

  • Acceptor線程:接收新的鏈接請求並響應;

  • Worker線程:child進程會爲每一個會話啓動一個worker線程,所以,在高併發的場景中可能會出現數百個worker線程甚至更多;

  • Expiry線程:從緩存中清理過時內容;


Varnish依賴「工做區(workspace)」以下降線程在申請或修改內存時出現競爭的可能性。在varnish內部有多種不一樣的工做區,其中最關鍵的當屬用於管理會話數據的session工做區。



5.varnish日誌


爲了與系統的其它部分進行交互,Child進程使用了能夠經過文件系統接口進行訪問的共享內存日誌(shared memory log),所以,若是某線程須要記錄信息,其僅須要持有一個鎖,然後向共享內存中的某內存區域寫入數據,再釋放持有的鎖便可。而爲了減小競爭,每一個worker線程都使用了日誌數據緩存。


共享內存日誌大小通常爲90M,其分爲兩部分,前一部分爲計數器,後半部分爲客戶端請求的數據。varnish提供了多個不一樣的工具如varnishlog、varnishncsa或varnishstat等來分析共享內存日誌中的信息並可以以指定的方式進行顯示。


6.VCL


Varnish Configuration Language (VCL)是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命令完成。


7.varnish的後端存儲


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

  • file:使用特定的文件存儲所有的緩存數據,並經過操做系統的mmap()系統調用將整個緩存文件映射至內存區域(若是條件容許);

  • (2)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}

file中的granularity用於設定緩存空間分配單位,默認單位是字節,全部其它的大小都會被圓整。

wKioL1V-61qBEdLIAAGrvew5tMk524.jpg


Varnish處理HTTP請求的過程大體分爲以下幾個步驟:

  • Receive狀態,也就是請求處理的入口狀態,根據VCL規則判斷該請求應該Pass或Pipe,仍是進入Lookup(本地查詢)。

  • Lookup狀態,進入此狀態後,會在hash表中查找數據,若找到,則進入Hit狀態,不然進入miss狀態。

  • Pass狀態,在此狀態下,會進入後端請求,即進入Fetch狀態。

  • Fetch狀態,在Fetch狀態下,對請求進行後端獲取,發送請求,得到數據,並進行本地存儲。

  • Deliver狀態, 將獲取到的數據發送給客戶端,而後完成本次請求。


8.VCL函數

1)vcl_recv

vcl_recv是在Varnish完成對請求報文的解碼爲基本數據結構後第一個要執行的子例程,它一般有四個主要用途:

(1)修改客戶端數據以減小緩存對象差別性;好比刪除URL中的www.等字符;

(2)基於客戶端數據選用緩存策略;好比僅緩存特定的URL請求、不緩存POST請求等;

(3)爲某web應用程序執行URL重寫規則;

(4)挑選合適的後端Web服務器;


可使用下面的終止語句,即經過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進行處理,並由其作出相應的處理決策。


2)vcl_fetch

相對於vcl_recv是根據客戶端的請求做出緩存決策來講,vcl_fetch則是根據服務器端的響應做出緩存決策。在任何VCL狀態引擎中返回的pass操做都將由vcl_fetch進行後續處理。vcl_fetch中有許多可用的內置變量,好比最經常使用的用於定義某對象緩存時長的beresp.ttl變量。經過return()返回給arnish的操做指示有:

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

  • hit_for_pass:不緩存此對象,但能夠致使後續對此對象的請求直接送達到vcl_pass進行處理;

  • restart:重啓整個VCL,並增長重啓計數;超出max_restarts限定的最大重啓次數後將會返回錯誤信息;

  • error code [reason]:返回指定的錯誤代碼給客戶端並丟棄此請求;

3)vcl_pipe函數 此函數在進入pipe模式時被調用,用於將請求直接傳遞至後端主機,在請求和返回的內容沒有改變的狀況下,將不變的內容返回給客戶端,直到這個連接被關閉。 此函數通常以以下幾個關鍵字結束。

  • error code [reason]

  • pipe

4).vcl_pass函數 此函數在進入pass模式時被調用,用於將請求直接傳遞至後端主機,後端主機在應答數據後將應答數據發送給客戶端,但不進行任何緩存,在當前鏈接下每次都返回最新的內容。 此函數通常以以下幾個關鍵字結束。

  • error code [reason] 。

  • pass。

5)lookup 表示在緩存中查找被請求的對象,而且根據查找的結果把控制權交給函數vcl_hit或函數vcl_miss。

6)vcl_hit函數 在執行lookup指令後,在緩存中找到請求的內容後將自動調用該函數。 此函數通常以以下幾個關鍵字結束。

  • deliver:表示將找到的內容發送給客戶端,並把控制權交給函數vcl_deliver。

  • error code [reason] 。

  • pass。

(7).vcl_miss函數 在執行lookup指令後,在緩存中沒有找到請求的內容時自動調用該方法,此函數可用於判斷是否須要從後端服務器獲取內容。 此函數通常以以下幾個關鍵字結束。

  • fetch:表示從後端獲取請求的內容,並把控制權交給vcl_fetch函數。

  • error code [reason] 。

  • pass。

8)vcl_deliver 函數 
將在緩存中找到請求的內容發送給客戶端前調用此方法。此函數通常以以下幾個關鍵字結束。

  • error code [reason]

  • deliver

9)vcl_timeout 函數 
在緩存內容到期前調用此函數。此函數通常以以下幾個關鍵字結束。

  • discard:表示從緩存中清除該內容。

  • fetch。

10)vcl_discard 函數 
在緩存內容到期後或緩存空間不夠時,自動調用該函數。該函數通常以以下幾個關鍵字結束。

  • keep:表示將內容繼續保留在緩存中。

  • discard。



9.內置公用變量

VCL內置的公用變量能夠用在不一樣的VCL函數中。下面根據這些公用變量使用的不一樣階段依次進行介紹。

(1).當請求到達後,可使用的公用變量

  • req.backend 指定對應的後端主機

  • server.ip 表示服務器端IP

  • client.ip 表示客戶端IP

  • req.request 指定請求的類型,例如GET、HEAD和POST等

  • req.url 指定請求的地址

  • req.proto 表示客戶端發起請求的HTTP協議版本

  • req.http.header 表示對應請求中的HTTP頭部信息

  • req. restarts ;/.l表示請求重啓的次數,默認最大值爲4

(2).Varnish在向後端主機請求時,可使用的公用變量

  • beresp.request 指定請求的類型,例如GET合HEAD等

  • beresp.url 指定請求的地址

  • beresp .proto 表示客戶端發起請求的HTTP協議版本

  • beresp .http.header 表示對應請求中的HTTP頭部信息

  • beresp .ttl 表示緩存的生存週期,也就是cache保留多長時間,單位是秒

(3).從cache或後端主機獲取內容後,可使用的公用變量

  • obj.status 表示返回內容的請求狀態代碼,例如200、302和504等

  • obj.cacheable 表示返回的內容是否能夠緩存,也就是說,若是HTTP返回的是200、20三、300、30一、30二、404或410等,而且有非0的生存期,則能夠緩存

  • obj.valid 表示是不是有效的HTTP應答

  • obj.response 表示返回內容的請求狀態信息

  • obj.proto 表示返回內容的HTTP協議版本

  • obj.ttl 表示返回內容的生存週期,也就是緩存時間,單位是秒

  • obj.lastuse 表示返回上一次請求到如今的間隔時間,單位是秒

(4).對客戶端應答時,可使用的公用變量

  • resp.status 表示返回給客戶端的HTTP狀態代碼

  • resp.proto 表示返回給客戶端的HTTP協議版本

  • resp.http.header 表示返回給客戶端的HTTP頭部信息

  • resp.response 表示返回給客戶端的HTTP狀態信息



安裝配置Varnish

官網下載這幾個rpm包,貌似要×××才能下載,官方提供的yum源已不能用。

varnish-3.0.7-1.el6.x86_64.rpm  

varnish-docs-3.0.7-1.el6.x86_64.rpm  

varnish-libs-devel-3.0.7-1.el6.x86_64.rpm

varnish-debuginfo-3.0.7-1.el6.x86_64.rpm  

varnish-libs-3.0.7-1.el6.x86_64.rpm

# rpm -ivh varnish*.rpm


# vim /etc/sysconfig/varnish

VARNISH_LISTEN_PORT=80 #這裏設置的監聽端口設置爲80
VARNISH_STORAGE="malloc,128M" #生產環境中儘可能設置大

啓動varnish

# /etc/init.d/varnish start

Starting Varnish Cache:                                    [  OK  ]


varnishadm 命令

# varnishadm -h
varnishadm: invalid option -- 'h'
usage: varnishadm [-n ident] [-t timeout] [-S secretfile] -T [address]:port command [...]
-n is mutually exlusive with -S and -T
[root@www ~]# varnish -S /etc/varnish/secret -T localhost:6082
-bash: varnish: command not found
[root@www ~]# varnishadm -S /etc/varnish/secret -T localhost:6082
200        
-----------------------------
Varnish Cache CLI 1.0
-----------------------------
Linux,2.6.32-504.el6.x86_64,x86_64,-smalloc,-smalloc,-hcritbit
varnish-3.0.7 revision f544cd8
Type 'help' for command list.
Type 'quit' to close CLI session.
varnish> help
200        
help [command]
ping [timestamp]
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
acl purgers {    #設定清理緩存的規則,varnish容許localhost,127.0.0.1,192.168.1.0三個來源 IP經過PURGE方法清楚緩存
        "127.0.0.1";
        "localhost";
        "192.168.1.0"/24;
}
 
backend websrv1 {
        .host="192.168.1.138";
        .port="80";
        .probe={
                .url="/index.html";
                .interval=1s;
                .window=3;
                .threshold=1;
        }
}
backend websrv2 {
        .host="192.168.1.139";
        .port="80";
        .probe={
                .url="/index.html";
                .interval=1s;
                .window=3;
                .threshold=1;
        }
}
 
director websrv random {
        { .backend = websrv1; .weight=3; }
        { .backend = websrv2; .weight=3; }
}
 
sub vcl_recv {
        
    if (req.http.x-forwarded-for) {  #使得後端服務能記錄訪問者的真實IP
       set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
     } 
    else {
       set req.http.X-Forwarded-For = client.ip;
     }
     if (req.request=="PURGE") {  #當發送的PURGE請求的客戶端不是在acl中設定的地址,返回405狀態。
          if (!client.ip ~ purgers) {
                error 405 "NOT allowed.";
          }
           return (lookup);
      }
      set req.backend = websrv;
}
 
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_deliver {  #增長一個響應頭部
        if (obj.hits >0) {
                set resp.http.X-Cache="Hit from"+" "+server.ip;
        }
        else {
                set resp.http.X-Cache="Miss from"+" "+server.ip;
        }
}
相關文章
相關標籤/搜索