緩存系統(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)求玉锌。
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擁有倆套配置文件耍铜;一套配置文件用于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