Varnish 3.X詳解

1、varnish定義php

Varnish與通常服務器軟件相似,分爲master(management)進程和child(worker,主要作cache的工做)進程。master進程讀入命令,進行一些初始化,而後fork並監控child進程。child進程分配若干線程進行工做,主要包括一些管理線程和不少woker線程。css

在網站併發量過大時;沒法經過向上或向外擴展來解決時;必須引入緩存來減少服務器的壓力;而互聯網在傳輸過程當中三個關鍵點:客戶端入口、傳輸中間路由、服務器端出口;相對於響應報文緩存能夠解決第一千米問題;用於緩存到用戶本地網絡中;避免瞬間擁塞;減低因距離傳輸帶來的延時。html

判斷緩存的有效性:根據文檔命中率和字節命中率綜合起來評估。node

2、varnish引擎和存儲python

VCL用於讓管理員定義緩存策略,而定義好的策略將由varnish的management進程分析、轉換成C代碼、編譯成二進制程序並鏈接至child進程。varnish內部有幾個所謂的狀態(state),在這些狀態上能夠附加經過VCL定義的策略以完成相應的緩存處理機制,所以VCL也常常被稱做「域專用」語言或狀態引擎,「域專用」指的是有些數據僅出現於特定的狀態中。nginx

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

狀態引擎:子例程;函數;可使用return()函數返回狀態給varnish進程;正則表達式

vcl_recv --> vcl_hash, vcl_pipe, vcl_passshell

  • vcl_hash:vcl_hit, vcl_missexpress

  • vcl_pass:vcl_fetch

  • vcl_hit:vcl_deliver, vcl_pass

  • vcl_miss:vcl_fetch, vcl_pass

  • vcl_fetch:vcl_deliver

具體工做模式:

wKioL1Nt4UqxeVXNAAE5mt8RPuQ725.jpg

varnish存儲

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

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

  • malloc:使用malloc()庫調用在varnish啓動時向操做系統申請指定大小的內存空間以存儲緩存對象;

  • persistent(experimental):與file的功能相同,但能夠持久存儲數據(即重啓varnish數據時不會被清除);仍處於測試期;

各參數對應的位置:

Variable recv fetch pass miss hit error deliver pipe hash
req.* R/W R/W R/W R/W R/W R/W R/W R/W R/W
bereq.*
R/W R/W R/W


R/W
obj.hits



R
R

obj.ttl



R/W R/W


obj.grace



R/W



obj.*



R R/W


beresp.*
R/W






resp.*




R/W R/W

3、安裝varnish及配置文件詳解

2.X、3.X、4.X最新版本都是能夠用的;安裝直接使用yum便可。

[root@node1 ~]# ls
anaconda-ks.cfg     php-5.4.26.tar.bz2                         xcache-3.1.0
install.log         varnish-3.0.4-1.el6.x86_64.rpm             xcache-3.1.0.tar.bz2
install.log.syslog  varnish-libs-3.0.4-1.el6.x86_64.rpm
php-5.4.26          varnish-libs-devel-3.0.4-1.el6.x86_64.rpm
[root@node1 ~]# rpm -ivh varnish-*.rpm
Preparing...                ########################################### [100%]
   1:varnish-libs           ########################################### [ 33%]
   2:varnish                ########################################### [ 67%]
   3:varnish-libs-devel     ########################################### [100%]
[root@node1 ~]#
#這裏安裝的3.x版本的;且2.x與3.x的命令格式有不一樣;具體能夠搜索下
[root@node1 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

安裝完成後直接查看配置文件:

[root@node1 ~]# vim /etc/sysconfig/varnish
# Configuration file for varnish
#
# /etc/init.d/varnish expects the variable $DAEMON_OPTS to be set from this
# shell script fragment.
#
# Maximum number of open files (for ulimit -n)
NFILES=131072    容許打開的最大鏈接數
# Locked shared memory (for ulimit -l)
# Default log size is 82MB + header
MEMLOCK=82000    指定內存空間大小保存日誌
# Maximum size of corefile (for ulimit -c). Default in Fedora is 0
# DAEMON_COREFILE_LIMIT="unlimited"    進程核心轉儲所使用的內存空間
# Set this to 1 to make init script reload try to switch vcl without restart.
# To make this work, you need to set the following variables
# explicit: VARNISH_VCL_CONF, VARNISH_ADMIN_LISTEN_ADDRESS,
# VARNISH_ADMIN_LISTEN_PORT, VARNISH_SECRET_FILE, or in short,
# use Alternative 3, Advanced configuration, below
RELOAD_VCL=1    從新啓動時是否重讀VCL
# This file contains 4 alternatives, please use only one.
# content server on localhost:8080.  Use a fixed-size cache file.
# Listen on port 6081, administration on localhost:6082, and forward to
# one content server selected by the vcl file, based on the request.  Use a
# fixed-size cache file.
#
#DAEMON_OPTS="-a :6081 \
#             -T localhost:6082 \
#             -f /etc/varnish/default.vcl \
#             -u varnish -g varnish \
#             -S /etc/varnish/secret \
#             -s file,/var/lib/varnish/varnish_storage.bin,1G"
## Alternative 3, Advanced configuration
#
# See varnishd(1) for more information.
#
# # Main configuration file. You probably want to change it :)
VARNISH_VCL_CONF=/etc/varnish/default.vcl    默認讀取的VCL配置文件
#
# # Default address and port to bind to
# # Blank address means all IPv4 and IPv6 interfaces, otherwise specify
# # a host name, an IPv4 dotted quad, or an IPv6 address in brackets.
# VARNISH_LISTEN_ADDRESS=
#VARNISH_LISTEN_PORT=6081
VARNISH_LISTEN_PORT=80    監聽的端口
#
# # Telnet admin interface listen address and port
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1    管理接口監聽的地址
VARNISH_ADMIN_LISTEN_PORT=6082            管理接口監聽的端口
#
# # Shared secret file for admin interface
VARNISH_SECRET_FILE=/etc/varnish/secret    使用的密鑰文件
#
# # The minimum number of worker threads to start
VARNISH_MIN_THREADS=1        最少線程數
#
# # The Maximum number of worker threads to start
VARNISH_MAX_THREADS=1000    最大線程數
#
# # Idle timeout for worker threads
VARNISH_THREAD_TIMEOUT=120    線程超時時長
#
# # Cache file location
VARNISH_STORAGE_FILE=/var/lib/varnish/varnish_storage.bin
#基於文件存儲時文件的路徑
# # Cache file size: in bytes, optionally using k / M / G / T suffix,
# # or in percentage of available disk space using the % suffix.
VARNISH_STORAGE_SIZE=1G    存儲空間大小
#
# # Backend storage specification
#VARNISH_STORAGE="file,${VARNISH_STORAGE_FILE},${VARNISH_STORAGE_SIZE}"
存儲類型
VARNISH_STORAGE="malloc,100M"
#
# # Default TTL used when the backend does not specify one
VARNISH_TTL=120    超時時間
#
# # DAEMON_OPTS is used by the init script.  If you add or remove options, make
# # sure you update this section, too.
DAEMON_OPTS="-a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \
             -f ${VARNISH_VCL_CONF} \
             -T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \
             -t ${VARNISH_TTL} \
             -w ${VARNISH_MIN_THREADS},${VARNISH_MAX_THREADS},${VARNISH_THREAD_TIMEOUT} \
             -u varnish -g varnish \
             -S ${VARNISH_SECRET_FILE} \
             -s ${VARNISH_STORAGE}"
#
## Alternative 4, Do It Yourself. See varnishd(1) for more information.
#
# DAEMON_OPTS=""
#只更改了存儲類型和監聽的端口

啓動測試:

[root@node1 ~]# service varnish start
Starting varnish HTTP accelerator:                         [  OK  ]
[root@node1 ~]# netstat -tunlp | grep 80
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      13101/varnishd 
tcp        0      0 :::80                       :::*                        LISTEN      13101/varnishd 
[root@node1 ~]#

varnish命令行工具

[root@node1 ~]# varnish
varnishadm          varnishlog          varnishreplay       varnishtest    
varnishd            varnishncsa         varnishsizes        varnishtop     
varnishhist         varnish_reload_vcl  varnishstat
#能夠對每一個命令進行命令幫助的獲取
[root@node1 ~]# varnishadm -h
varnishadm: invalid option -- 'h'
usage: varnishadm [-t timeout] [-S secretfile] -T [address]:port command [...]
[root@node1 ~]# varnishstat -h
varnishstat: invalid option -- 'h'
usage: varnishstat [-1lV] [-f field_list] [-n varnish_name] [-w delay]
    -1                           # Print the statistics once and exit
    -f field_list                # Comma separated list of fields to display.
                                 # If it starts with '^' it is used as an exclusion list
    -l                           # Lists the available fields to use with the -f option
    -n varnish_name              # The varnishd instance to get logs from
    -V                           # Display the version number and exit
    -w delay                     # Wait delay seconds between updates.  The default is 1.
    -x                           # Print statistics once as XML and exit.
[root@node1 ~]#

登錄管理接口測試:

[root@node1 ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
200   
-----------------------------
Varnish Cache CLI 1.0
-----------------------------
Linux,2.6.32-431.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> 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列表
vcl.show <configname>               #顯示VCL信息
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                            #在url中定義的ban列表

4、參數詳解

VCL的內置函數

regsub(str,regex,sub)/regsuball(str,regex,sub):這兩個用於基於正則表達式搜索指定的字符串並將其替換爲指定的字符串;但regsuball()能夠將str中可以被regex匹配到的字符串通通替換爲sub,regsub()只替換一次;

ban(expression)/ban_url(regex):Bans全部其URL可以由regex匹配的緩存對象;

purge:從緩存中挑選出某對象以及其相關變種一併刪除,這能夠經過HTTP協議的PURGE方法完成;

return():當某VCL域運行結束時將控制權返回給Varnish,並指示Varnish如何進行後續的動做;其能夠返回的指令包括:lookup、pass、pipe、hit_for_pass、fetch、deliver和hash等;但某特定域可能僅能返回某些特定的指令,而非前面列出的所有指令;

return(restart):從新運行整個VCL,即從新從vcl_recv開始進行處理;每一次重啓都會增長req.restarts變量中的值,而max_restarts參數則用於限定最大重啓次數。

vcl_recv

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

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

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

  • 爲某web應用程序執行URL重寫規則;

  • 挑選合適的後端Web服務器;

可使用下面的終止語句,即經過return()向Varnish返回的指示操做:

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

  • pipe:不對客戶端進行檢查或作出任何操做,而是在客戶端與後端服務器之間創建專用「管道」,並直接將數據在兩者之間進行傳送;此時,keep-alive鏈接中後續傳送的數據也都將經過此管道進行直接傳送,並不會出如今任何日誌中;

  • lookup:在緩存中查找用戶請求的對象,若是緩存中沒有其請求的對象,後續操做極可能會將其請求的對象進行緩存;

  • error:由Varnish本身合成一個響應報文,通常是響應一個錯誤類信息、重定向類信息或負載均衡器返回的後端web服務器健康狀態檢查類信息;

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

  • 僅處理能夠識別的HTTP方法,而且只緩存GET和HEAD方法;

  • 不緩存任何用戶特有的數據;

vcl_fetch

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 [reason]:返回指定的錯誤代碼給客戶端並丟棄此請求;

其餘參數能夠參照:https://www.varnish-cache.org/docs/3.0/reference/index.html

5、具體實例

[root@node1 ~]# cd /etc/varnish/
[root@node1 varnish]# ls
default.vcl  default.vcl.bak  secret
[root@node1 varnish]# vim test.vcl
#新建一個vcl文件;也可使用默認的進行更改便可。
backend node2 {        #定義後端主機
  .host = "192.168.0.112";
  .port = "80";
  .probe = {
     .url = "/index.html";
     .window = 5;
     .threshold = 2;
     .interval = 2s;
  }
}
backend node3 {
  .host = "192.168.0.113";
  .port = "80";
  .probe = {
     .url = "/index.html";
     .window = 5;
     .threshold = 2;
     .interval = 2s;
  }
}
director webserver random {    #定義組;相似nginx中的upstream
  {
     .backend = node2;
     .weight = 2;            #權重
  }
  {
     .backend = node3;
     .weight = 2;
  }
}
acl purgers {        #acl訪問控制列表
  "127.0.0.1";
  "192.168.0.0"/16;
}
sub vcl_recv {
#    set req.backend = webserver;    #全部請求都代理到該組
    if (req.url ~ "\.(html|htm|css|js)$") {    #若是url爲指定條件;則轉到node2
       set req.backend = node2;
   } else {
       set req.backend = node3;    #不然到node3
   }
    if (req.url ~ "nocache.html") {    #若是請求url爲指定條件;則不作緩存;直接pass
        return(pass);
    }
    if (req.request == "PURGE") {    #請求方法爲PURGE
       if(!client.ip ~ purgers) {    #不符合ACL中的IP
          error 405 "Method not allowd.";    #返回自定義錯誤代碼及信息
       }
     }
#    if (req.restarts == 0) {    #重啓次數爲0;
#      if (req.http.x-forwarded-for) {    #請求首部中含有x-forwarded-for
#          set req.http.X-Forwarded-For =    #則設定
#              req.http.X-Forwarded-For + ", " + client.ip;   #原首部+客戶端IP
#      } else {    #若是原首部不存在
#          set req.http.X-Forwarded-For = client.ip; #直接設置首部爲客戶端IP
#      }
#    }
#    if (req.request != "GET" &&    #若是請求不是一下方法;就說明不是一個正常的請求;沒法識別;
#      req.request != "HEAD" &&
#      req.request != "PUT" &&
#      req.request != "POST" &&
#      req.request != "TRACE" &&
#      req.request != "OPTIONS" &&
#      req.request != "DELETE") {
#        /* Non-RFC2616 or CONNECT which is weird. */
#        return (pipe);
#    }
#    if (req.request != "GET" && req.request != "HEAD") {   #只要不是這兩種方法;就不予緩存
        /* We only deal with GET and HEAD by default */
#        return (pass);
#    }
#    if (req.http.Authorization || req.http.Cookie) {  #請求若是是客戶端認證信息或cookie;都不查緩存
        /* Not cacheable by default */
#        return (pass);
#   }
    return (lookup);
}
sub vcl_hit {        #命中後
  if(req.request == "PURGE") {
    purge;
    error 200 "Purged Success.";    #返回自定義錯誤代碼及信息
  }
}
sub vcl_miss {    #未命中
  if(req.request == "PURGE") {
    purge;
    error 404 "Not in cache.";    #返回自定義錯誤代碼及信息
  }
}
sub vcl_pass {       #若是直接是pass中
  if(req.request == "PURGE") {
    error 502 "Purged on a passed object.";    #返回自定義錯誤代碼及信息
  }
}
sub vcl_fetch {    #在獲取的引擎中
  if(req.url ~"\.(jpg|png|gif|jpeg)$") {  #若是url爲圖片
    set beresp.ttl = 7200s;               #緩存指定時間
  }
  if(req.url ~"\.(html|htm|css|js)$") {   #若是url爲靜態頁面
    set beresp.ttl = 1200s;               #緩存指定時間
  }
}
sub vcl_deliver {        #在deliver引擎中
  if(obj.hits > 0) {     #如命中
    set resp.http.X-Cache = "HIT from " + server.ip;   #則在響應報文添加對應信息
  } else {
    set resp.http.X-Cache = "MISS";    #不然添加對應信息
  }
}

定義完成後進行編譯並使用:

[root@node1 ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
200    
-----------------------------
Varnish Cache CLI 1.0
-----------------------------
Linux,2.6.32-431.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 test1 test.vcl
200    
VCL compiled.
varnish> vcl.use test1
200    
varnish> backend.list
200    
Backend name                   Refs   Admin      Probe
default(127.0.0.1,,80)         2      probe      Healthy (no probe)
node2(192.168.0.112,,80)       1      probe      Healthy 5/5
node3(192.168.0.113,,80)       1      probe      Healthy 5/5
#能夠看出狀態和後端的列表

上述實例中;有不少功能是作了註釋的;由於不能同時使用;主要是作了對不一樣資源進行的代理:

訪問圖片代理到node3上;靜態頁面代理到node2上;此處還能夠作分組代理;能夠根據須要作處理:

wKiom1NuN83TyR3bAAE7_N3KM8k932.jpg

wKiom1NuN9uDDGzoAAEIXldtAZY173.jpg

[root@node2 ~]# curl -I http://192.168.0.111
HTTP/1.1 200 OK
Server: Apache/2.2.15 (CentOS)
Last-Modified: Sat, 26 Apr 2014 12:53:54 GMT
ETag: "100102-2b-4f7f19324fe41"
Content-Type: text/html; charset=UTF-8
Content-Length: 43
Accept-Ranges: bytes
Date: Mon, 24 Mar 2014 00:21:09 GMT
X-Varnish: 1655448565 1655448560
Age: 19
Via: 1.1 varnish
Connection: keep-alive
X-Cache: HIT from 192.168.0.111
#查看緩存已生效

6、param.show參數注意和varnishstat的參數含義

param

connect_timeout 鏈接超時時間
fetch_chunksize 獲取文件時的chunksize的大小
lru_interval 最近最少間隔時間清理過去緩存
nuke_limit 一批清理緩存個數
shm_workspace 共享內存大小
thread_pool_add_delay 建立線程的時間間隔;默認2ms
thread_pool_add_threshold work線程建立時溢出的閾值
thread_pool_fail_delay 建立線程失敗後間隔多久再次建立
thread_pool_max 每個線程池內部最多能夠容納的線程數量
thread_pool_min 線程的最小值;當線程池之間的線程不均衡時保證均衡性
thread_pool_purge_delay 間隔多久清理空閒線程
thread_pool_stack 工做線程的棧空間大小;32位系統需按需調整
thread_pool_timeout 線程空閒閾值;達到後清理;結合thread_pool_min控制
thread_pool_workspace 線程池的工做區大小
thread_pools 線程池的個數;運行時調大當即生效;可是減少需重啓
thread_stats_rate 一次收集指定個數的線程信息

varnishstat:

client_conn 客戶端鏈接數
client_req 客戶端的請求數
cache_hit 命中次數
cache_miss 未命中次數
backend_conn 對後端測試鏈接測試
n_wrk 工做線程個數
n_wrk_create 建立線程個數
n_backend 後端個數
n_expired 過時線程數
n_lru_moved 基於LRU清理的線程
s_hdrbytes 整體傳輸首部字節數
s_bodybytes 整體傳輸實體字節數

其餘具體參數能夠查看其文檔。




若有錯誤;懇請糾正。

相關文章
相關標籤/搜索