varnish的瞭解與常用配置使用


Varnish是一款高性能的開源HTTP加速器及反向代理服務器。

varnish架構圖:


wKioL1mVUDejtnnAAAGEvDyp-uQ564.png

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

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

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

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

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


配置使用varnish

CentOS7上epel源上直接安裝使用:varnish-4.0.5

[root@node3 dylan]# yum install varnishepel源

[root@node3 dylan]# cd /etc/varnish/

[root@node3 varnish]# cp varnish.params{,.bak}

[root@node3 varnish]# systemctl start varnish.service

示例:

一臺web服務器安裝httpd作爲後端服務器

[root@localhost ~]# vim /var/www/html/index.html

<h1> Backend Server 1</h1>

varnish主機上編輯:

[root@node3 varnish]# vim default.vcl 

backend default {

    .host = "192.168.0.150";                 ###後端服務器地址

    .port = "80";###端口

[root@node3 varnish]# systemctl reload varnish.service


舉幾個常用示例:

1、.測試緩存命中情況:

[root@node3 ~]# vim /etc/varnish/default.vcl

sub vcl_deliver {

    # Happens when we have all the pieces we need, and are about to send the

    # response to the client.

    #

    # You can do accounting or modifying the final object here.

    if (obj.hits>0) {###增加

        set resp.http.X-Cache = "HIT";

    }   else {

        set resp.http.X-Cache = "Miss";

    }

}

sub vcl_deliver {

    # Happens when we have all the pieces we need, and are about to send the

    # response to the client.

    #

    # You can do accounting or modifying the final object here.

    if (obj.hits>0) {

        set resp.http.X-Cache = "HIT via" + " " + server.ip;

    }   else {

        set resp.http.X-Cache = "Miss via" + " " + server.ip;

    }

}


###使varnishadm工具來管理

[root@node3 ]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082    ###varnishadm命令

vcl.load test1 default.vcl 

200        

VCL compiled.

varnish> vcl.use test1

200        

VCL 'test1' now active


2、緩存對象修剪

acl purgers {     ###添加訪問控制varnish4.0

        "127.0.0.0"/8;

        "192.168.0.0"/16;

}


sub vcl_recv {

    # Happens before we check if we have this in cache already.

    #

    # Typically you clean up the request here, removing cookies you don't need,

    # rewriting the request, etc.

        if (req.url ~"^/test.html$") {

                return(pass);

        }

        if (req.method == "PURGE"){

                if (!client.ip ~ purgers){###ip不屬於定義端內的返回405錯誤

                        return(synth(405,"Purging not allow for" + client.ip));

                }

        return(purge);

        }

}


sub vcl_purge {

        return(synth(200,"Purged,"));###修剪

}

管理端:

varnish> vcl.load test9 default.vcl         ###重新配置

200        

VCL compiled.

vcl.use test9        ###使用新配置

200        

VCL 'test9' now active



3、###設定多個後端主機

backend default {

    .host = "192.168.0.150";

    .port = "80";

}

backend appsrv {###定義一個後端主機

    .host = "192.168.0.113";

    .port = "80";

}

sub vcl_recv {

    # Happens before we check if we have this in cache already.

    #

    # Typically you clean up the request here, removing cookies you don't need,

    # rewriting the request, etc.

    if (req.url ~"(?i)\.php$") {

        set req.backend_hint = appsrv;

    }  else {

        set req.backend_hint = default;

}

}

vcl.load test10 default.vcl

200        

VCL compiled.

vcl.load 

varnish> vcl.use test10

200        

VCL 'test10' now active



4、設定負載均衡效果:

Directors:

import directors;###首先import

backend websrv1 {###定義兩個後端主機

    .host = "192.168.0.150";

    .port = "80";

}

backend websrv2 {

    .host = "192.168.0.115";

    .port = "80";

}

sub vcl_init {

        new websrvs = directors.round_robin();

        websrvs.add_backend(websrv1);

        websrvs.add_backend(websrv2);

}

sub vcl_recv {

  set req.backend_hint = websrvs.backend();

}


管理端使用:

varnish> vcl.load test13 default.vcl

200        

VCL compiled.

vcl.use test13

200        

VCL 'test13' now active



5、健康狀態檢測:

backend websrv1 {

.host = "192.168.0.115";

.host = "80";

.prode = {

.url = "/";                                                ###檢測時要請求的url,默認爲”/”

.interval = 1s;                                         ###檢測頻率

.window = 8;                                          ###基於最近的多少次檢查

.threshold = 5;                                       ###檢查最近8次檢查5次成功即爲健康

.timeout = 2s;                                        ###超時時長

}

}

.request =                                             ###可添加具體的請求

"GET /HTTP/1.1"

"Host: 192.168.0.115"

"connection:Close"

.expected_response=200;                    ###期望的響應碼

完整性示例:

vcl 4.0;

import directors;

# Default backend definition. Set this to point to your content server.

backend websrv1 {

    .host = "192.168.0.150";

    .port = "80";

    .probe = {

.url = "/";

.interval = 2s;

.window = 5;

.threshold = 4;

     }

}

backend websrv2 {

    .host = "192.168.0.115";

    .port = "80";

    .probe = {

.url = "/";

.interval = 2s;

.window = 5;

.threshold = 4;

     }

}

sub vcl_init {

new websrvs = directors.round_robin();

websrvs.add_backend(websrv1);

websrvs.add_backend(websrv2);

}


sub vcl_recv {

    

#    if (req.url ~"(?i)\.php$") {

#set req.backend_hint = appsrv;

#    }  else {

set req.backend_hint = websrvs.backend();

#    }

if (req.url ~"^/login") {

return(pass);

}

if (req.method == "PURGE"){

if (!client.ip ~ purgers){

return(synth(405,"Purging not allow for" + client.ip));

}

return(purge);

}

}


sub vcl_purge {

return(synth(200,"Purged,"));

}

acl purgers {

"127.0.0.0"/8;

"192.168.0.0"/16;

}


sub vcl_backend_response {

   

    if (beresp.http.cache-control !~ "s-masage") {

if (bereq.url ~ "(?i)\.jpg$") {

set beresp.ttl = 7200s;

unset beresp.http.Set-Cookie;

}

if (bereq.url ~ "(?i)\.css$"){

set beresp.ttl = 3600s;

unset beresp.http.Set-Cookie;

}

    }

}


sub vcl_deliver {

   

    if (obj.hits>0) {

set resp.http.X-Cache = "HIT via" + " " + server.ip;

    }   else {

set resp.http.X-Cache = "Miss via" + " " + server.ip;

    }

#    if (beresp.backend.name ~  "appsrv") {

#set resp.htttp.X-Server = "appsrv";

#   }

}




varnish幾個常用的命令工具:

varnishadm

varnishtop

varish log entry ranking

varnishlog

varnishlog.service

varnishncsa

varnishncsa.service

varnishstat

Varnish Cache statistics


varnish的運行時參數:                                配置文件中修改全局生效

[root@node3 ~]# vim /etc/varnish/varnish.params

DAEMON_OPTS="-p thread_pools=4"                     ###設置線程池爲4

[root@node3 ~]# systemctl restart varnish.service    ###不能隨便重啓,否則緩存全部失效

[root@node3 varnish]# varnishstat      ###查看狀態


附:

變量

內鍵變量:

req.*:由客戶端發來的http請求相關

    req.http.*:請求報文各首部

bereq.*:由varnish向backend主機發出的http請求

bere.http.*

beresp.*:由backend主機發來的http響應報文

resp.*: 由varnish響應給client的http響應報文

resp.http.*:響應報文各首部

obj.*:存儲在緩存空間的緩存對象屬性,只讀


client.*,server.*,storage.*:可用在所有的client side 的sub riutines中

        自定義: set

常用的變量:

bereq:

bereq.http.HEADERS

bereq.request:請求方法

bereq.url:請求的url

bereq.proto:協議版本

bereq.backend:指明要調用的後端主機

beresp:

beresp.proto

beresp.status:響應的狀態碼

beresp.reason

beresp.backend.name

baresp.http.HEADERA:

beresp.ttl:後端服務器響應中的內容餘下的生存時長

obj:

obj.hits:此對象從緩存中命中的次數;

obj.ttl:對象的ttl值

server:

server.ip

server.hostname

req.method:請求方法

req.url:請求的url


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