varnish緩存服務(wù)

緩存系統(tǒng)相關(guān)概念

緩存概念 說(shuō)明
時(shí)間局部性 一個(gè)數(shù)據(jù)被訪問(wèn)過(guò)之后,可能很快會(huì)被再次訪問(wèn)到
空間局部性 一個(gè)數(shù)據(jù)被訪問(wèn)時(shí)肥哎,其周邊的數(shù)據(jù)也有可能被訪問(wèn)到
數(shù)據(jù)緩存 例如MySQL到web應(yīng)用服務(wù)器之間的緩存服務(wù)器緩存的資源是數(shù)據(jù)緩存
頁(yè)面緩存 接入層和應(yīng)用層中間的緩存服務(wù)器緩存的是可緩存的頁(yè)面,這層就是緩存層
緩存命中率 hit/(hit+miss),一般高于30%命中率則是正向收益,好的設(shè)計(jì)系統(tǒng)可以達(dá)到80%到95%以上
字節(jié)命中率 按照數(shù)據(jù)的字節(jié)大小來(lái)計(jì)算命中率
請(qǐng)求命中率 按照請(qǐng)求的數(shù)量來(lái)計(jì)算命中率
private cache 私有緩存饥伊,用戶代理附帶的本地緩存機(jī)制
public cache 公共緩存,反向代理服務(wù)器的緩存功能
CND Content Delivery Network 內(nèi)容投遞系統(tǒng)
GSLB 全網(wǎng)均衡調(diào)度

代理式緩存:客戶端訪問(wèn)緩存服務(wù)器蔫饰,緩存服務(wù)器沒(méi)有命中緩存時(shí)到后端服務(wù)器請(qǐng)求數(shù)據(jù)琅豆,此時(shí)它作為反向代理服務(wù)器工作,這種類型的緩存服務(wù)器叫做代理式緩存

旁掛式緩存:客戶端親自去查詢數(shù)據(jù)庫(kù)篓吁,并且將數(shù)據(jù)復(fù)制給緩存服務(wù)器一份茫因,下次先去找緩存服務(wù)器,如果沒(méi)有命中則再去數(shù)據(jù)庫(kù)服務(wù)器查詢杖剪,此時(shí)這種工作方式的緩存叫做旁掛式緩存冻押,這個(gè)客戶端叫做胖客戶端

緩存有效性判斷機(jī)制:

  • 過(guò)期時(shí)間
  • 條件式驗(yàn)證
    Last-Modified/If-Modified-Since:基于文件的修改時(shí)間戳來(lái)判別
    Etag/If-None-Match:基于文件的校驗(yàn)碼來(lái)判別

http協(xié)議緩存常見(jiàn)的首部

Expires

Expires是HTTP 1.0所提供的控制字段,是web服務(wù)器響應(yīng)報(bào)文的字段盛嘿,用于告訴客戶端瀏覽器在Expires所指定的過(guò)期時(shí)間到來(lái)前翼雀,瀏覽器可直接從瀏覽器本地緩存中讀取緩存響應(yīng)請(qǐng)求,無(wú)需再次發(fā)送請(qǐng)求到服務(wù)器孩擂。

Data表示請(qǐng)求報(bào)文發(fā)送的時(shí)間,而Expires則表示緩存在此日期到來(lái)前都是有效的箱熬。因此客戶再次訪問(wèn)這類資源時(shí)类垦,瀏覽器會(huì)直接從本地緩存中響應(yīng)。

Cache-control

Cache-Control和Expires的作用差不多城须,都是用于指明當(dāng)前資源的緩存有效期蚤认。通知客戶端瀏覽器是從本地緩存中直接讀取數(shù)據(jù)還是說(shuō)重新發(fā)送請(qǐng)求到服務(wù)器中獲取數(shù)據(jù)。Cache-control提供了多種資源有效期的選擇糕伐,其優(yōu)先級(jí)高于Expires砰琢。

請(qǐng)求報(bào)文用于通知緩存服務(wù)如何使用緩存響應(yīng)請(qǐng)求:

cache-request-directive =
"no-cache" 不能使用緩存系統(tǒng)中的緩存響應(yīng)我,必須先去應(yīng)用服務(wù)器做緩存驗(yàn)證
"no-store" 不能使用緩存系統(tǒng)中的緩存響應(yīng)我良瞧,必須去應(yīng)用服務(wù)器請(qǐng)求響應(yīng)我
"max-age" "=" delta-seconds
"max-stale" [ "=" delta-seconds ]
"min-fresh" "=" delta-seconds
"no-transform"
"only-if-cached"
cache-extension

響應(yīng)報(bào)文用于通知緩存服務(wù)器如何存儲(chǔ)上級(jí)服務(wù)器響應(yīng)的內(nèi)容:

cache-response-directive =
"public" 所有緩存系統(tǒng)都可以緩存
"private" [ "=" <"> 1#field-name <"> ] 僅能夠被私有緩存所緩存
"no-cache" [ "=" <"> 1#field-name <"> ]陪汽,可緩存,但響應(yīng)給客戶端之前需要revalidation褥蚯,即必須發(fā)出條件式請(qǐng)求進(jìn)行緩存有效性驗(yàn)正
"no-store" 挚冤,不允許存儲(chǔ)響應(yīng)內(nèi)容于緩存中
"no-transform" 不能轉(zhuǎn)換格式
"must-revalidate" 必須重新驗(yàn)證
"proxy-revalidate"
"max-age" "=" delta-seconds 私有緩存最大緩存時(shí)長(zhǎng)
"s-maxage" "=" delta-seconds 公共緩存最大緩存時(shí)長(zhǎng)
cache-extension

Last-Modified/If-Modified-Since

Last-Modified/If-Modified-Since需要配置Cache-control一起使用。

Last-Modified:web服務(wù)器在響應(yīng)請(qǐng)求時(shí)赞庶,會(huì)使用此字段來(lái)告訴瀏覽器训挡,其請(qǐng)求的資源的最后修改時(shí)間澳骤。
If-Modified-Since:當(dāng)資源過(guò)期時(shí)或者請(qǐng)求中帶有Cache-Control:max-age=0,并且發(fā)現(xiàn)該資源的緩存具有Last-Modified聲明澜薄,則向web服務(wù)器發(fā)送請(qǐng)求時(shí)帶上If-Modified-Since为肮。web服務(wù)器收到請(qǐng)求后,將比較If-Modified-Since與被請(qǐng)求資源的最后修改時(shí)間肤京。如果最后修改時(shí)間比If-Modified-Since的值更新颊艳,說(shuō)明資源已經(jīng)被改動(dòng)過(guò),服務(wù)器會(huì)響應(yīng)此請(qǐng)求的資源蟆沫,響應(yīng)狀態(tài)碼為200籽暇;否則,說(shuō)明資源沒(méi)更新饭庞,則響應(yīng)HTTP 304戒悠,告知瀏覽器可繼續(xù)使用本地緩存。

Etag/If-None-Match

Etag:web服務(wù)器響應(yīng)請(qǐng)求時(shí)舟山,告訴瀏覽器當(dāng)前資源在服務(wù)器的唯一標(biāo)識(shí)(生成規(guī)則由服務(wù)器決定)绸狐。Apache中,ETag的值累盗,默認(rèn)是對(duì)文件的索引節(jié)(INode)寒矿,大小(Size)和最后修改時(shí)間(MTime)進(jìn)行Hash后得到的若债。
Etag 可以解決 Last-Modified 無(wú)法解決的一些問(wèn)題符相。

1、一些文件也許會(huì)周期性的更改蠢琳,但是他的內(nèi)容并不改變(僅僅改變的修改時(shí)間)啊终,這個(gè)時(shí)候我們并不希望客戶端認(rèn)為這個(gè)文件被修改了,而重新GET;
2傲须、某些文件修改非常頻繁蓝牲,比如在秒以下的時(shí)間內(nèi)進(jìn)行修改,(比方說(shuō)1s內(nèi)修改了N次)泰讽,If-Modified-Since能檢查到的變化時(shí)秒為單位的例衍,這種修改無(wú)法判斷。因此需要Etag來(lái)判斷已卸。
3佛玄、某些服務(wù)器不能精確的得到文件的最后修改時(shí)間;

如果Last-Modified與ETag一起使用時(shí)咬最,服務(wù)器會(huì)優(yōu)先驗(yàn)證ETag翎嫡。而Last-Modified的優(yōu)先級(jí)又高于Expires
也就是優(yōu)先級(jí):ETag>Last-Modified>Expires

If-None-Match:當(dāng)資源過(guò)期時(shí)或者請(qǐng)求報(bào)文帶有Cache-Control:max-age=0時(shí),并且發(fā)現(xiàn)該資源的緩存具有Etage聲明永乌,則再次向web服務(wù)器請(qǐng)求時(shí)帶上頭If-None-Match (Etag的值)惑申。web服務(wù)器收到請(qǐng)求后發(fā)現(xiàn)有頭If-None-Match 則與被請(qǐng)求資源的相應(yīng)校驗(yàn)串進(jìn)行比對(duì)具伍,決定返回200或304。

http協(xié)議緩存工作原理

當(dāng)瀏覽器第一次發(fā)送http請(qǐng)求時(shí)圈驼,本地通常來(lái)說(shuō)是沒(méi)有緩存的人芽,因此瀏覽器需要發(fā)送請(qǐng)求到服務(wù)器上去獲取響應(yīng)資源。此時(shí)瀏覽器向服務(wù)器發(fā)送的請(qǐng)求報(bào)文中通常會(huì)包含Cache-Control來(lái)告知服務(wù)器本地將對(duì)緩存作出何種處理绩脆。而服務(wù)器收到請(qǐng)求后萤厅,會(huì)將相關(guān)的緩存信息(Etag、Last-Modified等等)連通請(qǐng)求資源一起響應(yīng)客戶端靴迫。后續(xù)客戶端的再次訪問(wèn)的請(qǐng)求報(bào)文惕味,將結(jié)合緩存資源中的相關(guān)緩存字段來(lái)做出判斷,最后決定使用本地緩存還是服務(wù)器再次響應(yīng)該請(qǐng)求玉锌。

沒(méi)有緩存的http協(xié)議工作流程
客戶端再次發(fā)送web請(qǐng)求時(shí)的工作流程

Web Page Cache解決方案:squid和varnish

squid出現(xiàn)比較早名挥,但面臨較大負(fù)載時(shí)工作非常穩(wěn)定,且功能豐富主守,同時(shí)支持正向禀倔、反向代理;
varnish是比較輕量参淫,主要用來(lái)實(shí)現(xiàn)反代救湖;但超過(guò)承受的負(fù)載時(shí),可能很不穩(wěn)定涎才;

varnish

Varnish cache鞋既,或稱Varnish,是一套高性能的反向網(wǎng)站緩存服務(wù)器(reverse proxy server)
varnish官方站點(diǎn): http://www.varnish-cache.org/

varnish的程序架構(gòu)圖

varnish擁有倆套配置文件耍铜;一套配置文件用于varnish自身進(jìn)程的參數(shù)配置涛救,另一套用于定義緩存規(guī)則;定義緩存規(guī)則需要使用靈活的語(yǔ)言來(lái)定義业扒,這就是VCL(varnish語(yǔ)言);應(yīng)用時(shí)需要將VCL編寫的規(guī)則送給VCC編譯后才能運(yùn)行舒萎,所以安裝varnish需要依賴gcc編譯器程储。

varnish的安裝:yum install varnish -y,依賴epel源臂寝,目前CentOS7的epel源提供的版本是v4.0.5

varnish的程序環(huán)境:

/etc/varnish/varnish.params: 配置varnish服務(wù)進(jìn)程的工作特性章鲤,例如監(jiān)聽(tīng)的地址和端口,緩存機(jī)制
/etc/varnish/default.vcl:配置各Child/Cache線程的緩存策略
/usr/sbin/varnishd:主程序
/usr/bin/varnishadm:命令行工具
/usr/bin/varnishlog:查看內(nèi)存中的日志
/usr/bin/varnishncsa:以NCSA格式查看日志
/usr/bin/varnishstat:查看緩存日志狀態(tài)信息
/usr/bin/varnishtop:以rank方式查看日志
/usr/bin/varnishtest:測(cè)試工具程序
/usr/sbin/varnish_reload_vcl:VCL配置文件重載程序
/usr/lib/systemd/system/varnish.service:varnish服務(wù)
/usr/lib/systemd/system/varnishlog.service:日志持久的服務(wù)
/usr/lib/systemd/system/varnishncsa.service:日志持久的服務(wù)

varnish管理工具

varnishd
  • -s [name=]type[,options] :定義緩存數(shù)據(jù)的存儲(chǔ)方式
    malloc[,size]:內(nèi)存存儲(chǔ)咆贬,[,size]用于定義空間大邪芑病;重啟后所有緩存項(xiàng)失效
    file[,path[,size[,granularity]]]:磁盤文件存儲(chǔ)掏缎,黑盒皱蹦;重啟后所有緩存項(xiàng)失效
    persistent,path,size:文件存儲(chǔ)煤杀,黑盒;重啟后所有緩存項(xiàng)有效沪哺;實(shí)驗(yàn)階段沈自,不建議使用
  • -a address[:port][,address[:port][...]:服務(wù)監(jiān)聽(tīng)端口,默認(rèn)為6081端口
  • -T address[:port]:管理服務(wù)監(jiān)聽(tīng)端口辜妓,默認(rèn)為6082端口
  • -f config:VCL配置文件
  • -F:運(yùn)行于前臺(tái)
  • -p param=value:設(shè)定運(yùn)行參數(shù)及其值枯途; 可重復(fù)使用多次
  • -r param[,param...]: 設(shè)定指定的參數(shù)為只讀狀態(tài)
varnishstat
[root@varnish ~]# varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss #顯示指定參數(shù)的當(dāng)前統(tǒng)計(jì)數(shù)據(jù)
[root@varnish ~]# varnishstat -l -f MAIN -f MEMPOOL #列出指定配置段的每個(gè)參數(shù)的意義
varnishtop
  • -1:打印統(tǒng)計(jì)信息一次并退出,而不是持續(xù)更新的顯示
  • -i taglist:可以同時(shí)使用多個(gè)-i選項(xiàng)籍滴,也可以一個(gè)選項(xiàng)跟上多個(gè)標(biāo)簽
  • -I <[taglist:]regex>:對(duì)指定的標(biāo)簽的值基于regex進(jìn)行過(guò)濾
  • -x taglist:排除列表
  • -X <[taglist:]regex>:對(duì)指定的標(biāo)簽的值基于regex進(jìn)行過(guò)濾酪夷,符合條件的予以排除
varnishadm
[root@varnish ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 #登錄管理程序
help [<command>] 獲取幫助
ping [<timestamp>] 測(cè)試服務(wù)器
auth <response>
quit 退出cli
banner
status 顯示狀態(tài)
start 啟動(dòng)
stop 停止
vcl.load <configname> <filename> 加載VCL配置文件
vcl.inline <configname> <quoted_VCLstring>
vcl.use <configname> 激活VCL配置文件
vcl.discard <configname> 刪除VCL配置
vcl.list 列出VCL配置
param.show [-l] [<param>] 列出當(dāng)前運(yùn)行的參數(shù)
param.set <param> <value> 運(yùn)行參數(shù)臨時(shí)調(diào)整
panic.show
panic.clear
storage.list 列出數(shù)據(jù)存儲(chǔ)信息
vcl.show [-v] <configname> 列出VCL詳細(xì)配置
backend.list [<backend_expression>] 列出后端服務(wù)器
backend.set_health <backend_expression> <state>
ban <field> <operator> <arg> [&& <field> <oper> <arg>]...
ban.list

配置文件

默認(rèn)配置文件:

RELOAD_VCL=1
VARNISH_VCL_CONF=/etc/varnish/default.vcl  #指定加載VCL配置文件
VARNISH_LISTEN_ADDRESS=192.168.1.5  #服務(wù)監(jiān)聽(tīng)的地址
VARNISH_LISTEN_PORT=6081  #默認(rèn)監(jiān)聽(tīng)端口
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1  #管理服務(wù)監(jiān)聽(tīng)的地址
VARNISH_ADMIN_LISTEN_PORT=6082 #管理服務(wù)監(jiān)聽(tīng)的端口
VARNISH_SECRET_FILE=/etc/varnish/secret  #連接秘鑰
VARNISH_STORAGE="malloc,256M"  #用內(nèi)存提供保存緩存,大小為256M
VARNISH_USER=varnish  #用戶身份
VARNISH_GROUP=varnish #組身份
DAEMON_OPTS="-p thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300" #指定進(jìn)程的運(yùn)行參數(shù)

VCL

Varnish配置語(yǔ)言(VCL)是一種特定于域的語(yǔ)言,用于描述Varnish Cache的請(qǐng)求處理和文檔緩存策略孽惰。加載新配置時(shí)晚岭,由Manager進(jìn)程創(chuàng)建的VCC進(jìn)程將VCL代碼轉(zhuǎn)換為C.此C代碼通常由gcc共享對(duì)象編譯。然后將共享對(duì)象加載到cacher進(jìn)程中灰瞻。

vcl是域配置語(yǔ)言腥例,每一個(gè)sub的作用是定義一個(gè)域:

varnish的有限狀態(tài)機(jī):

上圖適用于前端線程,即客戶端請(qǐng)求酝润,其中:
1.vcl_pass:無(wú)論請(qǐng)求是否命中的第二種處理方法燎竖,例如命中時(shí)不響應(yīng),由pass處理轉(zhuǎn)發(fā)到后端服務(wù)器
2.vcl_purge:緩存清理的方法之一要销。
如果緩存的內(nèi)容與元數(shù)據(jù)不符构回,并響應(yīng)給用戶,同時(shí)響應(yīng)給用戶不能緩存的直接獲取的元數(shù)據(jù)疏咐,則整個(gè)響應(yīng)內(nèi)容就會(huì)混亂纤掸,此時(shí),需要介入外力強(qiáng)行清理緩存浑塞。緩存清理的方法有兩種:
(1)purge:請(qǐng)求內(nèi)容在緩存中命中借跪,則緩存繼續(xù)生效,如果未命中酌壕,則失效掏愁,即清理緩存磨总。
(2)ban機(jī)制:可以自定義正則表達(dá)式模式狸涌,匹配到模式的內(nèi)容禁止從緩存中響應(yīng),要從元數(shù)據(jù)獲取瞄勾,然后再次進(jìn)行緩存糊昙,覆蓋之前的緩存內(nèi)容辛掠,達(dá)到清理緩存的效果。
3.vcl_pipe:不能緩存的請(qǐng)求释牺,直接與后端聯(lián)系萝衩。兩種情況:
(1)正常的http協(xié)議請(qǐng)求回挽,但是其中只有g(shù)et和head可以緩存,其他的method都不能緩存
(2)非http協(xié)議的請(qǐng)求

上圖適用于向服務(wù)器發(fā)送請(qǐng)求欠气,其中:
vcl_synth:負(fù)責(zé)清理緩存厅各,之前的vcl_purge用來(lái)監(jiān)控是否有清理緩存權(quán)限
以上兩圖中,橢圓形的代表子例程预柒,即域队塘,也叫狀態(tài)引擎。

vcl有多個(gè)狀態(tài)引擎宜鸯,狀態(tài)之間存在相關(guān)性憔古,但狀態(tài)引擎彼此間互相隔離;每個(gè)狀態(tài)引擎可使用return(x)指明關(guān)聯(lián)至哪個(gè)下一級(jí)引擎淋袖;每個(gè)狀態(tài)引擎對(duì)應(yīng)于vcl文件中的一個(gè)配置段鸿市,即為subroutine

倆個(gè)特殊的引擎:
vcl_init:在處理任何請(qǐng)求之前要執(zhí)行的vcl代碼:主要用于初始化VMODs;
vcl_fini:所有的請(qǐng)求都已經(jīng)結(jié)束即碗,在vcl配置被丟棄時(shí)調(diào)用焰情;主要用于清理VMODs;

vainish默認(rèn)的VCL配置

默認(rèn)VCL配置也叫做隱式規(guī)則剥懒,在配置文件中無(wú)法看到内舟,即使我們修改了配置文件,默認(rèn)配置規(guī)則也是在最后做處理初橘。

varnish> vcl.show -v boot  #在客戶端cli工具中查看
sub vcl_recv {
    if (req.method == "PRI") {  #如果客戶端的請(qǐng)求方法是PRI验游,不支持SPDY或HTTP/2.0
        return (synth(405));  #則構(gòu)建一個(gè)405的包響應(yīng)給客戶端
    }
    if (req.method != "GET" &&  #如果客戶端的請(qǐng)求方法不是GET
      req.method != "HEAD" &&  #并且不是HEAD
      req.method != "PUT" &&  #并且不是PUT
      req.method != "POST" &&  #并且不是...
      req.method != "TRACE" &&
      req.method != "OPTIONS" &&
      req.method != "DELETE") {
        return (pipe);  #即,不是標(biāo)準(zhǔn)HTTP請(qǐng)求方法的交給pipe(管道)
    }
    if (req.method != "GET" && req.method != "HEAD") {  #請(qǐng)求方法不是GET和HEAD的
        return (pass);  #交給pass處理保檐,也就是除了GAT和HEAD方法其他的無(wú)法緩存
    }
    if (req.http.Authorization || req.http.Cookie) {  #http的請(qǐng)求首部包含Authorization(認(rèn)證)或Cookie耕蝉,即個(gè)人專有信息
        return (pass);  #交給pass處理,因?yàn)檫@些帶有個(gè)人信息的數(shù)據(jù)無(wú)法緩存
    }
    return (hash);  #以上的規(guī)則都沒(méi)有做處理的請(qǐng)求交給hash做處理夜只,剩下的是可以查詢緩存的請(qǐng)求了
}

sub vcl_pipe
sub vcl_pass
sub vcl_hash
sub vcl_purge
sub vcl_hit
sub vcl_miss
sub vcl_deliver
sub vcl_synth
sub vcl_backend_fetch
sub vcl_backend_response
sub vcl_backend_error
sub vcl_init
sub vcl_fini
內(nèi)建函數(shù)
  • regsub(str, regex, sub)
  • regsuball(str, regex, sub)
  • ban(boolean expression)
  • hash_data(input)
  • synthetic(str)
  • hash_data():指明哈希計(jì)算的數(shù)據(jù)垒在;減少差異,以提升命中率
  • regsub(str,regex,sub):把str中被regex第一次匹配到字符串替換為sub扔亥;主要用于URL Rewrite
  • regsuball(str,regex,sub):把str中被regex每一次匹配到字符串均替換為sub
  • return()
  • ban(expression)
  • ban_url(regex):Bans所有的其URL可以被此處的regex匹配到的緩存對(duì)象
  • synth(status,"STRING"):生成響應(yīng)報(bào)文
Keywords
  • call subroutine
  • return(action)
  • new
  • set
  • unset
操作符
  • ==, !=, ~, >, >=, <, <=
  • 邏輯操作符:&&, ||, !
  • 變量賦值:=

示例1:obj.hits是內(nèi)建變量爪膊,用于保存某緩存項(xiàng)的從緩存中命中的次數(shù)

[root@varnish ~]# vim /etc/varnish/varnish.params
VARNISH_LISTEN_PORT=80
[root@varnish ~]# vim /etc/varnish/default.vcl
backend default {
    .host = "192.168.0.9";
    .port = "80";
}
sub vcl_deliver {
    if (obj.hits>0) {
        set resp.http.X-Cache = "HIT via" + " " + server.ip;
    } else {
        set resp.http.X-Cache = "MISS from " + server.ip;
    }
}
[root@varnish ~]# systemctl restart varnish  #謹(jǐn)慎重啟varnish服務(wù),會(huì)導(dǎo)致之前的緩存失效
[root@varnish ~]# for i in {1..5}; do curl -I -s 192.168.0.8 |grep "X-Cache"; done  #在客戶端測(cè)試砸王,第一次Miss
X-Cache: MISS from 192.168.0.8
X-Cache: HIT via 192.168.0.8
X-Cache: HIT via 192.168.0.8
X-Cache: HIT via 192.168.0.8
X-Cache: HIT via 192.168.0.8
內(nèi)建變量
內(nèi)建變量
req.* request,表示由客戶端發(fā)來(lái)的請(qǐng)求報(bào)文相關(guān)
bereq.* 由varnish發(fā)往BE主機(jī)的httpd請(qǐng)求相關(guān)
beresp.* 由BE主機(jī)響應(yīng)給varnish的響應(yīng)報(bào)文相關(guān)
resp.* 由varnish響應(yīng)給client相關(guān)
obj.* 存儲(chǔ)在緩存空間中的緩存對(duì)象的屬性峦阁;只讀
常用變量
bereq.request, req.request 請(qǐng)求方法
bereq.url, req.url 請(qǐng)求的url谦铃;
bereq.proto 請(qǐng)求的協(xié)議版本;
bereq.backend 指明要調(diào)用的后端主機(jī)榔昔;
req.http.Cookie 客戶端的請(qǐng)求報(bào)文中Cookie首部的值驹闰;
req.http.User-Agent ~ "chrome" 用戶代理
beresp.status, resp.status 響應(yīng)的狀態(tài)碼
reresp.proto, resp.proto 協(xié)議版本
beresp.backend.name BE主機(jī)的主機(jī)名
beresp.ttl BE主機(jī)響應(yīng)的內(nèi)容的余下的可緩存時(shí)長(zhǎng)
obj.hits 此對(duì)象從緩存中命中的次數(shù)
obj.ttl 對(duì)象的ttl值
server.ip varnish主機(jī)的IP
server.hostname varnish主機(jī)的Hostname
client.ip 發(fā)請(qǐng)求至varnish主機(jī)的客戶端IP

示例2:強(qiáng)制對(duì)某類資源的請(qǐng)求不檢查緩存

[root@varnish ~]# vim /etc/varnish/default.vcl
sub vcl_recv {
    if (req.url ~ "(?i)^/(login|admin)") {  #"?i"表示忽略大小寫瘪菌,匹配到url中帶有l(wèi)ogin或admin的不查詢緩存
        return(pass);
    }
}
[root@varnish ~]# varnish_reload_vcl
[root@varnish ~]# for i in {1..5}; do curl -I -s http://192.168.0.8/login |grep "X-Cache"; done  #客戶端測(cè)試
X-Cache: MISS from 192.168.0.8  #全部Miss
X-Cache: MISS from 192.168.0.8
X-Cache: MISS from 192.168.0.8
X-Cache: MISS from 192.168.0.8
X-Cache: MISS from 192.168.0.8
# for i in {1..5}; do curl -I -s http://192.168.0.8/admin |grep "X-Cache"; done
X-Cache: MISS from 192.168.0.8
X-Cache: MISS from 192.168.0.8
X-Cache: MISS from 192.168.0.8
X-Cache: MISS from 192.168.0.8
X-Cache: MISS from 192.168.0.8
# for i in {1..5}; do curl -I -s http://192.168.0.8/ |grep "X-Cache"; done  #其他網(wǎng)頁(yè)正常查詢緩存
X-Cache: MISS from 192.168.0.8
X-Cache: HIT via 192.168.0.8
X-Cache: HIT via 192.168.0.8
X-Cache: HIT via 192.168.0.8
X-Cache: HIT via 192.168.0.8

示例3:對(duì)于特定類型的資源,例如公開(kāi)的圖片等嘹朗,取消其私有標(biāo)識(shí)师妙,并強(qiáng)行設(shè)定其可以由varnish緩存的時(shí)長(zhǎng)

sub vcl_backend_response {
    if (beresp.http.cache-control !~ "s-maxage") {
        if (bereq.url ~ "(?i)\.(jpg|jpeg|png|gif|css|js)$") {
            unset beresp.http.Set-Cookie;
            set beresp.ttl = 3600s;
        }
    }
}

示例4:在報(bào)文首部添加真正的客戶端IP,使得后端server可以記錄真正客戶端來(lái)源

[root@varnish ~]# vim /etc/varnish/default.vcl
sub vcl_recv {
    if (req.restarts == 0) {  #匹配沒(méi)有被重寫的URL請(qǐng)求屹培,即第一次請(qǐng)求
        if (req.http.X-Forwarded-For) {  #變量存在并且有值則為真
            set req.http.X-Forwarded-For = req.http.X-Forwarded-For + "," + client.ip;  #將真正的client.ip添加到此變量中默穴,用","隔開(kāi)
        } else {
            set req.http.X-Forwarded-For = client.ip;  #如果變量不存在或值為空,則直接將client.ip賦值與
        }
    }
}
[root@varnish ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
varnish> vcl.load conf1 /etc/varnish/default.vcl
varnish> vcl.use conf1
varnish> vcl.list   
available       0 boot
available       0 reload_2018-07-14T09:55:58
active          0 conf1  #當(dāng)前正在使用的配置
[root@web1 ~]# vim /etc/httpd/conf/httpd.conf
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
[root@web1 ~]# systemctl restart httpd
[root@client ~]# for i in {1..5}; do curl -I -s http://192.168.0.8/login |grep "X-Cache"; done #在客戶端測(cè)試
[root@web1 ~]# tail /var/log/httpd/access_log 
192.168.0.8 - - [14/Jul/2018:09:56:49 +0800] "HEAD /login HTTP/1.1" 301 - "-" "curl/7.29.0"
192.168.0.8 - - [14/Jul/2018:09:56:49 +0800] "HEAD /login HTTP/1.1" 301 - "-" "curl/7.29.0"
192.168.0.8 - - [14/Jul/2018:09:56:49 +0800] "HEAD /login HTTP/1.1" 301 - "-" "curl/7.29.0"
192.168.0.8 - - [14/Jul/2018:09:56:49 +0800] "HEAD /login HTTP/1.1" 301 - "-" "curl/7.29.0"
192.168.0.8 - - [14/Jul/2018:09:56:49 +0800] "HEAD /login HTTP/1.1" 301 - "-" "curl/7.29.0"
192.168.0.7 - - [14/Jul/2018:10:25:11 +0800] "HEAD /login HTTP/1.1" 301 - "-" "curl/7.29.0"
192.168.0.7 - - [14/Jul/2018:10:25:11 +0800] "HEAD /login HTTP/1.1" 301 - "-" "curl/7.29.0"
192.168.0.7 - - [14/Jul/2018:10:25:11 +0800] "HEAD /login HTTP/1.1" 301 - "-" "curl/7.29.0"
192.168.0.7 - - [14/Jul/2018:10:25:11 +0800] "HEAD /login HTTP/1.1" 301 - "-" "curl/7.29.0"
192.168.0.7 - - [14/Jul/2018:10:25:11 +0800] "HEAD /login HTTP/1.1" 301 - "-" "curl/7.29.0"  #拿到了真正客戶端IP褪秀,而不是之前的varnish服務(wù)器的IP

示例5:訪問(wèn)控制蓄诽,拒絕curl客戶端的訪問(wèn)

sub vcl_recv {
    if(req.http.User-Agent ~ "curl") {
        return(synth(403));
    }
}
緩存對(duì)象的修剪:purge

1、能執(zhí)行purge操作

sub vcl_purge {
    return (synth(200,"Purged"));
}

2媒吗、何時(shí)執(zhí)行purge操作

sub vcl_recv {
    if (req.method == "PURGE") {
        return(purge);
    }
    ...
}

示例6:清除指定緩存

[root@varnish ~]# vim /etc/varnish/default.vcl
acl purgers {
    "127.0.0.0"/8;
    "192.168.0.0"/24;
}
sub vcl_recv {
    if (req.method == "PURGE") {
        if (!client.ip ~ purgers) {
            return(synth(405,"Purging not allowed for " + client.ip));
        }
        return(purge);
    }
}
varnish> vcl.load conf3 /etc/varnish/default.vcl
varnish> vcl.use conf3
[root@client ~]# curl -I http://192.168.0.8/
X-Cache: HIT via 192.168.0.8
[root@client ~]# curl -I -X "PURGE"  http://192.168.0.8/
[root@client ~]# curl -I http://192.168.0.8/
X-Cache: MISS from 192.168.0.8
緩存對(duì)象的修剪:Banning

1仑氛、arnishadm: ban <field> <operator> <arg>

varnish> ban req.url ~ (?i)^/javascripts

2、在配置文件中定義闸英,使用ban()函數(shù)

sub vcl_recv {
    if (req.method == "BAN") {
        ban("req.http.host == " + req.http.host + " && req.url == " + req.url);  #將規(guī)則拼接起來(lái)傳遞給ban函數(shù)
        return(synth(200, "Ban added"));
    }
}
# curl -I -X "BAN" http://192.168.0.8/javascripts/
多個(gè)后端主機(jī)實(shí)現(xiàn)調(diào)度功能
動(dòng)靜分離示例:
backend default {
    .host = "172.16.0.9";
    .port = "80";
}
backend appsrv {
    .host = "172.16.0.10";
    .port = "80";
}
sub vcl_recv {
    if (req.url ~ "(?i)\.php$") {
        set req.backend_hint = appsrv;
    } else {
        set req.backend_hint = default;
    }
}
輪詢調(diào)度
import directors;
backend srv1 {
    .host = "192.168.0.9";
    .port = "80";
}
backend srv2 {
    .host = "192.168.0.10";
    .port = "80";
}
sub vcl_init {
    new websrvs = directors.round_robin();  #round_robin()調(diào)度算法锯岖,不支持加權(quán)
    websrvs.add_backend(srv1);
    websrvs.add_backend(srv2);
}
sub vcl_recv {
    set req.backend_hint = websrvs.backend();
}
基于cookie的session sticky
sub vcl_init {
    new h = directors.hash();
    h.add_backend(one, 1);
    h.add_backend(two, 1);
}
sub vcl_recv {
    set req.backend_hint = h.backend(req.http.cookie);
}
隨機(jī)調(diào)度,支持權(quán)重
sub vcl_init {
    new websrvs = directors.random();
    websrvs.add_backend(srv1, 1);
    websrvs.add_backend(srv2, 2);
}
后端健康檢查

.probe:定義健康狀態(tài)檢測(cè)方法甫何;
.url:檢測(cè)時(shí)要請(qǐng)求的URL出吹,默認(rèn)為”/";
.request:發(fā)出的具體請(qǐng)求;
.request =
"GET /.healthtest.html HTTP/1.1"
"Host: www.dongfei.tech"
"Connection: close"
.window:基于最近的多少次檢查來(lái)判斷其健康狀態(tài)沛豌;
.threshold:最近.window中定義的這么次檢查中至有.threshhold定義的次數(shù)是成功的趋箩;
.interval:檢測(cè)頻度;
.timeout:超時(shí)時(shí)長(zhǎng)加派;
.expected_response:期望的響應(yīng)碼叫确,默認(rèn)為200;

import directors;
probe http_chk {
        .url = "/index.html";
        .interval = 2s;
        .timeout = 2s;
        .window = 10;  #最近10次檢查
        .threshold = 7;  #有7次成功則為健康主機(jī)
}
backend srv1 {
        .host = "192.168.0.9";
        .port = "80";
        .probe = http_chk;
}
backend srv2 {
        .host = "192.168.0.10";
        .port = "80";
        .probe = http_chk;
}
sub vcl_init {
        new websrvs = directors.random();
        websrvs.add_backend(srv1, 1);
        websrvs.add_backend(srv2, 2);
}
sub vcl_recv {
        set req.backend_hint = websrvs.backend();
}
varnish> backend.list #查看后端主機(jī)健康狀態(tài)信息     
Backend name                   Refs   Admin      Probe
srv1(192.168.0.9,,80)          3      probe      Healthy 10/10
srv2(192.168.0.10,,80)         3      probe      Healthy 10/10
varnish> backend.set_health srv1 sick|healthy|auto  #手動(dòng)標(biāo)記主機(jī)狀態(tài) down|up|probe

設(shè)置后端的主機(jī)屬性:

backend BE_NAME {
    ...
    .connect_timeout = 0.5s;  #連接超時(shí)時(shí)間
    .first_byte_timeout = 20s;  #第一個(gè)字節(jié)20s不響應(yīng)則為超時(shí)
    .between_bytes_timeout = 5s;  #第一個(gè)字節(jié)和第二個(gè)字節(jié)間隔超時(shí)時(shí)間
    .max_connections = 50;  #最大連接數(shù)
}

varnish的運(yùn)行時(shí)參數(shù)

最大并發(fā)連接數(shù) = thread_pools * thread_pool_max

  • thread_pools:工作線程數(shù)芍锦,最好小于或等于CPU核心數(shù)量
  • thread_pool_max:每線程池的最大線程數(shù)
  • thread_pool_min:最大空閑線程數(shù)
  • thread_pool_timeout:空閑超過(guò)多長(zhǎng)時(shí)間被清除
  • thread_pool_add_delay:生成線程之前等待的時(shí)間
  • thread_pool_destroy_delay:清除超出最大空閑線程數(shù)的線程之前等待的時(shí)間

日志管理

virnish的日志默認(rèn)存儲(chǔ)在80M的內(nèi)存空間中竹勉,如果日志記錄超出了則覆蓋前邊的日志,服務(wù)器重啟后丟失娄琉;需要更改配置使其永久保存到磁盤

[root@varnish ~]# varnishstat -1 -f MAIN  #指定查看MAIN段的信息
[root@varnish ~]# varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss  #顯示指定參數(shù)的當(dāng)前統(tǒng)計(jì)數(shù)據(jù)
MAIN.cache_hit              47         0.00 Cache hits
MAIN.cache_miss             89         0.01 Cache misses
[root@varnish ~]# varnishtop -1 -i ReqHeader  #顯示指定的排序信息
   165.00 ReqHeader Accept: */*
   165.00 ReqHeader Host: 192.168.0.8
   165.00 ReqHeader User-Agent: curl/7.29.0
   165.00 ReqHeader X-Forwarded-For: 192.168.0.7

將日志永久保存到:/var/log/varnish/varnish.log

[root@varnish ~]# systemctl start varnishlog.service

以Apache/NCSA日志格式顯示

[root@varnish ~]# varnishncsa
192.168.0.7 - - [14/Jul/2018:12:34:23 +0800] "GET http://192.168.0.8/javascripts/test1.html HTTP/1.1" 200 11 "-" "curl/7.29.0"

參考文檔:https://blog.csdn.net/jingsanliunian/article/details/78452602
http://www.reibang.com/p/e948549f34ae

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末次乓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子孽水,更是在濱河造成了極大的恐慌票腰,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件女气,死亡現(xiàn)場(chǎng)離奇詭異杏慰,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門缘滥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)轰胁,“玉大人,你說(shuō)我怎么就攤上這事朝扼≡叻В” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵擎颖,是天一觀的道長(zhǎng)榛斯。 經(jīng)常有香客問(wèn)我,道長(zhǎng)肠仪,這世上最難降的妖魔是什么肖抱? 我笑而不...
    開(kāi)封第一講書人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮异旧,結(jié)果婚禮上意述,老公的妹妹穿的比我還像新娘。我一直安慰自己吮蛹,他們只是感情好荤崇,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著潮针,像睡著了一般术荤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上每篷,一...
    開(kāi)封第一講書人閱讀 52,158評(píng)論 1 308
  • 那天瓣戚,我揣著相機(jī)與錄音,去河邊找鬼焦读。 笑死子库,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的矗晃。 我是一名探鬼主播仑嗅,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼张症!你這毒婦竟也來(lái)了仓技?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤俗他,失蹤者是張志新(化名)和其女友劉穎脖捻,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體兆衅,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡地沮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年颜价,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诉濒。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖夕春,靈堂內(nèi)的尸體忽然破棺而出未荒,到底是詐尸還是另有隱情,我是刑警寧澤及志,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布片排,位于F島的核電站,受9級(jí)特大地震影響速侈,放射性物質(zhì)發(fā)生泄漏率寡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一倚搬、第九天 我趴在偏房一處隱蔽的房頂上張望冶共。 院中可真熱鬧,春花似錦每界、人聲如沸捅僵。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)庙楚。三九已至,卻和暖如春趴樱,著一層夾襖步出監(jiān)牢的瞬間馒闷,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工叁征, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留纳账,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓航揉,卻偏偏與公主長(zhǎng)得像塞祈,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子帅涂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 緩存的基礎(chǔ)知識(shí) 1议薪、程序本身具有局部性 時(shí)間局部性過(guò)去訪問(wèn)到的數(shù)據(jù),也有可能被兩次訪問(wèn) 空間局部性一個(gè)數(shù)據(jù)被訪問(wèn)到...
    魏鎮(zhèn)坪閱讀 2,035評(píng)論 1 3
  • 1.介紹 運(yùn)維日常: 2.Web Page Cache: varnish2.0,3.0處理過(guò)程 varnish4....
    尛尛大尹閱讀 3,363評(píng)論 0 0
  • 一媳友、varnish軟件 1斯议、概述 (1)Varnish是一款高性能、開(kāi)源的反向代理服務(wù)器和緩存服務(wù)器醇锚。Varnis...
    任總閱讀 833評(píng)論 0 0
  • 本文編譯自:users-guide 本節(jié)講述如何使用 VCL 編寫處理 HTTP 流量的策略哼御。 Varnish 的...
    C86guli閱讀 3,187評(píng)論 0 1
  • 何得這一生 何其的運(yùn)氣 碰見(jiàn)了遇上了 你可知是緣分 全球60億人多 偏偏愛(ài)上你 你令我明白 還有你 我知道還有你 ...
    野貓_閱讀 242評(píng)論 0 1