Linux之varnish

  一: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設計機構圖

wKioL1Qj02nC2kQsAAE02BxXtwc578.jpg




   


 三:VCL 處理流程

wKioL1Qj1cTDpCRBAAG_JjlJuVQ325.jpg

Varnish 處理 HTTP 請求的過程大致分爲如下幾個步驟。

    - Receive 狀態(vcl_recv)。也就是請求處理的入口狀態,根據 VCL 規則判斷該請求應該 pass(vcl_pass)或是 pipe(vcl_pipe),還是進入 lookup(本地查詢)。

    - Lookup 狀態。進入該狀態後,會在 hash 表中查找數據,若找到,則進入 hit(vcl_hit)狀態,否則進入 miss(vcl_miss)狀態。

    - Pass(vcl_pass)狀態。在此狀態下,會直接進入後端請求,即進入 fetch(vcl_fetch)狀態

    - Fetch(vcl_fetch)狀態。在 fetch 狀態下,對請求進行後端獲取,發送請求,獲得數據,並根據設置進行本地存儲。

    - Deliver(vcl_deliver)狀態。將獲取到的數據發給客戶端,然後完成本次請求

   

1) VCL 內置函數

 vcl_recv 函數

   用於接收和處理請求。當請求到達併成功接收後被調用,通過判斷請求的數據來決定如何處理請求。例如如何響應、怎麼響應、使用哪個後端服務器等。

   此函數一般以如下幾個關鍵字結束。

pass:表示進入 pass 模式,把請求控制權交給 vcl_pass 函數。

pipe:表示進入 pipe 模式,把請求控制權交給 vcl_pipe 函數。

lookup:表示進入 lookup 模式,把請求控制權交給 lookup 指令處理,在緩存中查找被請求的對象,並且根據查找的結果把控制權交給函數 vcl_hit 或函數 vcl_miss。

error code [reason]:表示返回“code”給客戶端,並放棄處理該請求。“code”是錯誤標識,例如 200 和 405 等。“reason”是錯誤提示信息.


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


vcl_pass 函數

   此函數在進入 pass 模式時被調用,用於將請求直接傳遞至後端主機。後端主機在應答數據後將應答數據發送給客戶端,但不進行任何緩存,在當前連接下每次都返回最新的內容。

此函數一般以如下幾個關鍵字結束。

error code [reason]。

pass。

restart 重新啓動流程,增加啓動次數,如果重新啓動次數高於 max_restarts 發出一個錯誤警告


vcl_hash

   當您想把一個數據添加到 hash 上時,調用此函數。

   此函數一般以如下幾個關鍵字結束

vcl_hit 函數

   在執行 lookup 指令後,在緩存中找到請求的內容後將自動調用該函數。

此函數一般以如下幾個關鍵字結束。

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

error code [reason] 。

pass。

restart 重新啓動流程,增加啓動次數,如果重新啓動次數高於 max_restarts 發出一個錯誤警告


  vcl_miss 函數

  在執行 lookup 指令後,在緩存中沒有找到請求的內容時自動調用該方法。此函數可用於判斷是否需要從後端服務器獲取內容。

此函數一般以如下幾個關鍵字結束。

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

error code [reason] 。

pass。


vcl_fetch 函數

  在後端主機更新緩存並且獲取內容後調用該方法,接着,通過判斷獲取的內容來決定是將內容放入緩存,還是直接返回給客戶端。

此函數一般以如下幾個關鍵字結束。

error code [reason]。

pass。

deliver。

esi。

restart 重新啓動流程,增加啓動次數,如果重新啓動次數高於 max_restarts 發出一個錯誤警告


vcl_deliver 函數

  將在緩存中找到請求的內容發送給客戶端前調用此方法。

此函數一般以如下幾個關鍵字結束。

error code [reason]。

deliver。

restart 重新啓動流程,增加啓動次數,如果重新啓動次數高於 max_restarts 發出一個錯誤警告

vcl_error

出現錯誤時調用此函數。

此函數一般以如下幾個關鍵字結束。

deliver。

restart



2)工作流程概述

   Varnish 與一般服務器軟件類似,分爲 master 進程和 child 進程。Master 進程讀入存儲配置文件,調用合適的存儲類型,然後創建 / 讀入相應大小的緩存文件,接着 master 初始化管理該存儲空間的結構體,然後 fork 並監控 child 進程。Child 進程在主線程的初始化的過程中,將前面打開的存儲文件整個 mmap 到內存中,此時創建並初始化空閒結構體,掛到存儲管理結構體,以待分配。Child 進程分配若干線程進行工作,主要包括一些管理線程和很多 worker 線程。

    接着,開始真正的工作,varnish 的某個負責接收新 HTTP 連接線程開始等待用戶,如果有新的 HTTP 連接過來,它總負責接收,然後喚醒某個等待中的線程,並把具體的處理過程交給它。Worker 線程讀入 HTTP 請求的 URI計算出響應的hash值,查找已有的 object,如果命中則直接返回並回複用戶。如果沒有命中,則需要將所請求的內容,從後端服務器中取過來,存到緩存中,然後再回復。

   分配緩存的過程是這樣的:它根據所讀到 object 的大小,創建相應大小的緩存文件。爲了讀寫方便,程序會把每個 object 的大小變爲最接近其大小的內存頁面倍數。然後從現有的空閒存儲結構體中查找,找到最合適的大小的空閒存儲塊,分配給它。如果空閒塊沒有用完,就把多餘的內存另外組成一個空閒存儲塊,掛到管理結構體上,這樣做可以減少磁盤碎片。如果緩存已滿,就根據 LRU(最近做少使用原則) 機制,把最舊的 object 釋放掉。

   釋放緩存的過程是這樣的:有一個超時線程,檢測緩存中所有 object 的生存期,如果超初設定的 TTL(Time To Live)沒有被訪問,就刪除之,並且釋放相應的結構體及存儲內存。注意釋放時會檢查該存儲內存塊前面或後面的空閒內存塊,如果前面或後面的空閒內存和該釋放內存是連續的,就將它們合併成更大一塊內存。

    整個文件緩存的管理,沒有考慮文件與內存的關係,實際上是將所有的 object 都考慮是在內存中,如果系統內存不足,系統會自動將其換到 swap 空間,而不需要 varnish 程序去控制。


四:VCL的內置公共變量

1)當請求到達時,可以使用的公共變量

 

wKioL1Qj5CLDce_gAAE0eTe8Khc657.jpg

2)對客戶端相應時可使用公共變量

wKioL1Qj5DXxGq6fAACvfTrN8A4050.jpg

3)後端主機獲取內容時可使用公共變量

wKioL1Qj5JfA_RjqAAD6jbAvn2s499.jpg


五:varnish試驗

1)試驗拓撲

wKioL1Qj6WqC-KKLAACzIbL95QI407.jpg


2)查看安裝的配置文件

[root@varnish ~]# rpm -ql varnish
/etc/logrotate.d/varnish
/etc/rc.d/init.d/varnish #啓動腳本
/etc/rc.d/init.d/varnishlog
/etc/rc.d/init.d/varnishncsa
/etc/sysconfig/varnish #啓動腳本的配置文件
/etc/varnish #全局配置文件
/etc/varnish/default.vcl #默認VCL
/usr/bin/varnish_reload_vcl #varnish管理工具
/usr/bin/varnishadm
/usr/bin/varnishhist
/usr/bin/varnishlog
/usr/bin/varnishncsa
/usr/bin/varnishreplay
/usr/bin/varnishsizes
/usr/bin/varnishstat
/usr/bin/varnishtest
/usr/bin/varnishtop
/usr/lib64/varnish
/usr/lib64/varnish/libvarnish.so
/usr/lib64/varnish/libvarnishcompat.so
/usr/lib64/varnish/libvcl.so
/usr/lib64/varnish/libvgz.so
/usr/lib64/varnish/vmods
/usr/lib64/varnish/vmods/libvmod_std.so
/usr/sbin/varnishd
/usr/share/doc/varnish-3.0.4
/usr/share/doc/varnish-3.0.4/ChangeLog
/usr/share/doc/varnish-3.0.4/LICENSE
/usr/share/doc/varnish-3.0.4/README
/usr/share/doc/varnish-3.0.4/README.redhat
/usr/share/doc/varnish-3.0.4/examples
/usr/share/doc/varnish-3.0.4/examples/default.vcl
/usr/share/doc/varnish-3.0.4/examples/zope-plone.vcl
/usr/share/man/man1/varnishadm.1.gz #man配置文件
/usr/share/man/man1/varnishd.1.gz
/usr/share/man/man1/varnishhist.1.gz
/usr/share/man/man1/varnishlog.1.gz
/usr/share/man/man1/varnishncsa.1.gz
/usr/share/man/man1/varnishreplay.1.gz
/usr/share/man/man1/varnishsizes.1.gz
/usr/share/man/man1/varnishstat.1.gz
/usr/share/man/man1/varnishtest.1.gz
/usr/share/man/man1/varnishtop.1.gz
/usr/share/man/man3/vmod_std.3.gz
/usr/share/man/man7/varnish-cli.7.gz
/usr/share/man/man7/varnish-counters.7.gz
/usr/share/man/man7/vcl.7.gz
/var/lib/varnish
/var/log/varnish #日誌文件

3)修改啓動腳本配置文件

[root@varnish sysconfig]# vim /etc/sysconfig/varnish
VARNISH_LISTEN_PORT=80 #這裏設置的監聽端口設置爲80
VARNISH_STORAGE="malloc,64M" #我們這裏設置的是64M,因爲我們這裏是測試環境,在生產環境中可以根據實際需求設置很大

4)啓動varnish

[root@varnish ~]# service varnish start
Starting Varnish Cache:                  [確定]

5)配置後端http服務器

[root@web1 ~]# yum install -y httpd
[root@web1 ~]# cat /var/www/html/index.html
<h1>varnish server node1</h1>
[root@web1 ~]# service httpd start
正在啓動 httpd:

6)真假vcl配置文件

[root@varnish ~]# cd /etc/varnish/
[root@varnish varnish]# cp default.vcl test.vcl
[root@varnish varnish]# vim test.vcl
backend webserver {
 .host = "172.16.16.1";
 .port = "80";
}
 sub vcl_recv {
 set req.backend = webserver;
}

7)加載vcl配置文件

[root@varnish ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
200
-----------------------------
Varnish Cache CLI 1.0
-----------------------------
Linux,2.6.32-358.el6.x86_64,x86_64,-smalloc,-smalloc,-hcritbit
varnish-3.0.4 revision 9f83e8f
Type 'help' for command list.
Type 'quit' to close CLI session.
varnish> vcl.load test test.vcl #編譯
200
VCL compiled.
varnish> vcl.list
200
active     0 boot
available    0 test
varnish> vcl.use test
200

OK,進行測試一下

wKiom1QkC9CSFFGGAAB5ZB0K8Lg675.jpg



如何修改配置文件查看我們的緩存是否命中

1)修改配置文件

[root@varnish varnish]# vim test.vcl
backend default {
 .host = "172.16.16.1";
 .port = "80";
}
 sub vcl_recv {
 set req.backend = webserver;
}
 #修改vcl_deliver增一個響應頭部
 sub vcl_deliver {
     if (obj.hits > 0) {
        set resp.http.X-Cache = "Hit from"+" "+server.ip;
    } else {
        set resp.http.X-Cache = "Miss via"+" "+server.ip;
    }
 }

wKioL1QkDv-gcZj5AAMUOlIK48I325.jpg

第一次加載時緩存X-Cache爲Miss(沒有被命中).

wKioL1QkD43jeSC8AAMzH4U-VEo167.jpg

第二次刷新加載時命中緩存此處的X-Cache爲HIT.


如何設置讓某個條件不被命中

1)修改配置文件

[root@varnish ~]# vim /etc/varnish/test.vcl
backend webserver {
    .host = "172.16.16.1";
    .port = "80";
}
#設置條件讓請求test.html文件時不緩存
 sub vcl_recv {
    if (req.url ~ "^/test.html$") {
        return(pass);
    }
    set req.backend = webserver;
}
 sub vcl_deliver {
     if (obj.hits > 0) {
        set resp.http.X-Cache = "Hit from"+" "+server.ip;
    } else {
        set resp.http.X-Cache = "Miss via"+" "+server.ip;
    }
 }
[root@web1 ~]# vim /var/www/html/test.html
<h1>mandela</h1>

2)重新加載配置文件

varnish> vcl.load test2 test.vcl
200
VCL compiled.
varnish> vcl.use test2
200

wKioL1QkE7qx4zudAAMQWvgYFFM511.jpg


不管刷新多少次始終是不會對此網頁信息進行緩存.


如何根據響應內容作出判斷

修改配置文件

[root@varnish ~]# vim /etc/varnish/test.vcl
backend webserver {
    .host = "172.16.16.1";
    .port = "80";
}
sub vcl_recv {
    if (req.url ~ "^/test.html$") {
        return(pass);
    }
    set req.backend = webserver;
}
sub vcl_fetch {
    if (req.request == "GET" && req.url ~ "\.(html|css|js|jpg|jpeg|png|gif)$") {
        set beresp.ttl = 3600s;
    }
}
sub vcl_deliver {
     if (obj.hits > 0) {
        set resp.http.X-Cache = "Hit from"+" "+server.ip;
    } else {
        set resp.http.X-Cache = "Miss via"+" "+server.ip;
    }
 }

重新加載文件

varnish> vcl.load test3 test.vcl
200
VCL compiled.
varnish> vcl.use test3
200

varnish如何實現負載均衡及檢查後端主機狀態

修改配置文件

 
 
 [root@varnish ~]# vim /etc/varnish/test.vcl
backend webserver1 {
    .host = "172.16.16.1";
    .port = "80";
    .probe = {
    .url = "/index.html";
    .interval = 1s;
    .window = 3;
    .threshold = 1;
  }
}
backend webserver2 {
    .host = "172.16.16.4";
    .port = "80";
    .probe = {
    .url = "/index.html";
    .interval = 1s;
    .window = 3;
    .threshold = 1;
  }
}
director webserver random {
    { .backend = webserver1; .weight = 3; }
    { .backend = webserver2; .weight = 1; }
}
sub vcl_recv {
      set req.backend = webserver;
}
sub vcl_deliver {
     if (obj.hits > 0) {
        set resp.http.X-Cache = "Hit from"+" "+server.ip;
    } else {
        set resp.http.X-Cache = "Miss via"+" "+server.ip;
    }
 }

重新裝載

varnish> vcl.load test4 test.vcl
200
VCL compiled.
varnish> vcl.use test4
200

 這樣後端定義了兩個主機16.1和16.2.且實現了輪訓調度加緩存機制加後段的安全狀態檢測,後端的安全狀態檢測是每一秒檢測一次,檢測三次不在線就自動下線.判斷在線次數只需要判斷一次.

varnish> backend.list
200        
Backend name                   Refs   Admin      Probe
default(127.0.0.1,,80)         1      probe      Healthy (no probe)
webserver(172.16.16.1,,80)     4      probe      Healthy (no probe)
webserver1(172.16.16.1,,80)    3      probe      Healthy 3/3
webserver2(172.16.16.4,,80)    3      probe      Healthy 3/3

定義的後端主機分別是16.1和16.4

wKioL1QkHxuj4QsbAAUQzeEmmek539.jpg

每隔一秒鐘就檢測一下後端主機是否在線.200狀態碼說明主機在線.


OK 我們的varnish配置基本完成.希望大家有些收穫.

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