日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Varnish缓存代理简介与配置

發(fā)布時(shí)間:2025/3/8 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Varnish缓存代理简介与配置 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、varnish原理:

1)Varnish簡(jiǎn)介:

varnish緩存是web應(yīng)用加速器,同時(shí)也作為http反向緩存代理。你可以安裝varnish在任何http的前端,同時(shí)配置它緩存內(nèi)容。與傳統(tǒng)的 squid 相比,varnish 具有性能更高、速度更快、管理更加方便等諸多優(yōu)點(diǎn)。有一部分企業(yè)已經(jīng)在生產(chǎn)環(huán)境中使用其作為舊版本的squid的替代方案,以在相同的服務(wù)器成本下提供更好的緩存效果,Varnish更是作為CDN緩存服務(wù)器的可選服務(wù)之一。

根據(jù)官網(wǎng)的介紹,Varnish的主要特性如下:https://www.varnish-cache.org/

1.緩存位置:可以使用內(nèi)存也可以使用磁盤。如果要使用磁盤的話推薦SSD做RAID1

2.日志存儲(chǔ):日志也存儲(chǔ)在內(nèi)存中。存儲(chǔ)策略:固定大小,循環(huán)使用

3.支持虛擬內(nèi)存的使用。

4.有精確的時(shí)間管理機(jī)制,即緩存的時(shí)間屬性控制。

5.狀態(tài)引擎架構(gòu):在不同的引擎上完成對(duì)不同的緩存和代理數(shù)據(jù)進(jìn)行處理。可以通過(guò)特定的配置語(yǔ)言設(shè)計(jì)不同的控制語(yǔ)句,以決定數(shù)據(jù)在不同位置以不同方式緩存,在特定的地方對(duì)經(jīng)過(guò)的報(bào)文進(jìn)行特定規(guī)則的處理。

6.緩存管理:以二叉堆格式管理緩存數(shù)據(jù),做到數(shù)據(jù)的及時(shí)清理。

2)Varnish與Squid的對(duì)比

相同點(diǎn):

都是一個(gè)反向代理服務(wù)器;

都是開(kāi)源軟件;

Varnish的優(yōu)勢(shì):

1、Varnish的穩(wěn)定性很高,兩者在完成相同負(fù)荷的工作時(shí),Squid服務(wù)器發(fā)生故障的幾率要高于Varnish,因?yàn)槭褂肧quid要經(jīng)常重啟;

2、Varnish訪問(wèn)速度更快,因?yàn)椴捎昧恕癡isual Page Cache”技術(shù),所有緩存數(shù)據(jù)都直接從內(nèi)存讀取,而squid是從硬盤讀取,因而Varnish在訪問(wèn)速度方面會(huì)更快;

3、Varnish可以支持更多的并發(fā)連接,因?yàn)閂arnish的TCP連接釋放要比Squid快,因而在高并發(fā)連接情況下可以支持更多TCP連接;

4、Varnish可以通過(guò)管理端口,使用正則表達(dá)式批量的清除部分緩存,而Squid是做不到的;

squid屬于是單進(jìn)程使用單核CPU,但Varnish是通過(guò)fork形式打開(kāi)多進(jìn)程來(lái)做處理,所以可以合理的使用所有核來(lái)處理相應(yīng)的請(qǐng)求;

Varnish的劣勢(shì):

1、varnish進(jìn)程一旦Crash或者重啟,緩存數(shù)據(jù)都會(huì)從內(nèi)存中完全釋放,此時(shí)所有請(qǐng)求都會(huì)發(fā)送到后端服務(wù)器,在高并發(fā)情況下,會(huì)給后端服務(wù)器造成很大壓力;

2、在varnish使用中如果單個(gè)url的請(qǐng)求通過(guò)HA/F5等負(fù)載均衡,則每次請(qǐng)求落在不同的varnish服務(wù)器中,造成請(qǐng)求都會(huì)被穿透到后端;而且同樣的請(qǐng)求在多臺(tái)服務(wù)器上緩存,也會(huì)造成varnish的緩存的資源浪費(fèi),造成性能下降;

Varnish劣勢(shì)的解決方案:

針對(duì)劣勢(shì)一:在訪問(wèn)量很大的情況下推薦使用varnish的內(nèi)存緩存方式啟動(dòng),而且后面需要跟多臺(tái)squid/nginx服務(wù)器。主要為了防止前面的varnish服 務(wù)、服務(wù)器被重啟的情況下,大量請(qǐng)求穿透varnish,這樣squid/nginx可以就擔(dān)當(dāng)?shù)诙覥ACHE,而且也彌補(bǔ)了varnish緩存在內(nèi)存中重啟都會(huì)釋放的問(wèn)題;

針對(duì)劣勢(shì)二:可以在負(fù)載均衡上做url哈希,讓單個(gè)url請(qǐng)求固定請(qǐng)求到一臺(tái)varnish服務(wù)器上;

3)使用varnish作為web代理緩存的原理?:

varnish是一個(gè)http反向代理的緩存。它從客戶端接收請(qǐng)求然后嘗試從緩存中獲取數(shù)據(jù)來(lái)響應(yīng)客戶端的請(qǐng)求,如果varnish不能從緩存中獲得數(shù)據(jù)來(lái)響應(yīng)客戶端,它將轉(zhuǎn)發(fā)請(qǐng)求到后端(backend?servers),獲取響應(yīng)同時(shí)存儲(chǔ),最后交付給客戶端。?

如果varnish已經(jīng)緩存了某個(gè)響應(yīng),它比你傳統(tǒng)的后端服務(wù)器的響應(yīng)要快很多,所以你需要盡可能是更多的請(qǐng)求直接從varnish的緩存中獲取響應(yīng)。?

varnish決定是緩存內(nèi)容或者是從后端服務(wù)器獲取響應(yīng)。后端服務(wù)器能通過(guò)http響應(yīng)頭中的Cache-Control來(lái)同步varnish緩存內(nèi)容。在某些條件下varnish將不緩存內(nèi)容,最常見(jiàn)的是使用cookie。當(dāng)一個(gè)被標(biāo)記有cookie的客戶端web請(qǐng)求,varnish默認(rèn)是不緩存。這些眾多的varnish功能特點(diǎn)都是可以通過(guò)寫(xiě)vcl來(lái)改變的。

5)簡(jiǎn)單架構(gòu):

Varnish 分為 management 進(jìn)程和child 進(jìn)程;

Management進(jìn)程:對(duì)子進(jìn)程進(jìn)行管理,同時(shí)對(duì)VCL配置進(jìn)行編譯,并應(yīng)用到不同的狀態(tài)引擎。

Child進(jìn)程:生成線程池,負(fù)責(zé)對(duì)用戶請(qǐng)求進(jìn)行處理,并通過(guò)hash查找返回用戶結(jié)果。

6)varnish主要配置部分:

varnish配置主要分為:后端配置,ACL配置,probes配置,directors配置,核心子程序配置幾大塊。其中后端配置是必要的,在多臺(tái)服務(wù)器中還會(huì)用到directors配置,核心子程序配置。

后端配置:即給varnish添加反代服務(wù)器節(jié)點(diǎn),最少配置一個(gè)。

ACL配置:即給varnish添加訪問(wèn)控制列表,可以指定這些列表訪問(wèn)或禁止訪問(wèn)。

probes配置:即給varnish添加探測(cè)后端服務(wù)器是否正常的規(guī)則,方便切換或禁止對(duì)應(yīng)后端服務(wù)器。

directors配置:即給varnish添加負(fù)載均衡模式管理多個(gè)后端服務(wù)器。

核心子程序配置:即給varnish添加后端服務(wù)器切換,請(qǐng)求緩存,訪問(wèn)控制,錯(cuò)誤處理等規(guī)則。

7)VCL中內(nèi)置預(yù)設(shè)變量:變量(也叫object):


req:The request object,請(qǐng)求到達(dá)時(shí)可用的變量(客戶端發(fā)送的請(qǐng)求對(duì)象)

bereq:The backend request object,向后端主機(jī)請(qǐng)求時(shí)可用的變量

beresp:The backend response object,從后端主機(jī)獲取內(nèi)容時(shí)可用的變量(后端響應(yīng)請(qǐng)求對(duì)象)

resp:The HTTP response object,對(duì)客戶端響應(yīng)時(shí)可用的變量(返回給客戶端的響應(yīng)對(duì)象)

obj:存儲(chǔ)在內(nèi)存中時(shí)對(duì)象屬性相關(guān)的可用的變量(高速緩存對(duì)象,緩存后端響應(yīng)請(qǐng)求內(nèi)容)

?

預(yù)設(shè)變量是系統(tǒng)固定的,請(qǐng)求進(jìn)入對(duì)應(yīng)的vcl子程序后便生成,這些變量可以方便子程序提取,當(dāng)然也可以自定義一些全局變量。

當(dāng)前時(shí)間:

now?:作用:返回當(dāng)前時(shí)間戳。

?

客戶端:(客戶端基本信息)

client.ip:返回客戶端IP地址。

注:原client.port已經(jīng)棄用,如果要取客戶端請(qǐng)求端口號(hào)使用 std.port(client.ip),需要import std;才可以使用std

client.identity:用于裝載客戶端標(biāo)識(shí)碼。

?

服務(wù)器:(服務(wù)器基本信息)

注:原server.port已經(jīng)棄用,如果要取服務(wù)器端口號(hào)使用 std.port(server.ip),需要import std;才可以使用std

server.hostname:服務(wù)器主機(jī)名。

server.identity:服務(wù)器身份標(biāo)識(shí)。

server.ip:返回服務(wù)器端IP地址。

?

req :(客戶端發(fā)送的請(qǐng)求對(duì)象)

req:整個(gè)HTTP請(qǐng)求數(shù)據(jù)結(jié)構(gòu)

req.backend_hint:指定請(qǐng)求后端節(jié)點(diǎn),設(shè)置后 bereq.backend 才能獲取后端節(jié)點(diǎn)配置數(shù)據(jù)

req.can_gzip:客戶端是否接受GZIP傳輸編碼。

req.hash_always_miss:是否強(qiáng)制不命中高速緩存,如果設(shè)置為true,則高速緩存不會(huì)命中,一直會(huì)從后端獲取新數(shù)據(jù)。

req.hash_ignore_busy:忽略緩存中忙碌的對(duì)象,多臺(tái)緩存時(shí)可以避免死鎖。

req.http:對(duì)應(yīng)請(qǐng)求HTTP的header。

req.method:請(qǐng)求類型(如 GET , POST)。

req.proto:客戶端使用的HTTP協(xié)議版本。

req.restarts:重新啟動(dòng)次數(shù)。默認(rèn)最大值是4

req.ttl:緩存有剩余時(shí)間。

req.url:請(qǐng)求的URL。

req.xid:唯一ID。

?

bereq:(發(fā)送到后端的請(qǐng)求對(duì)象,基于req對(duì)象)

bereq:整個(gè)后端請(qǐng)求后數(shù)據(jù)結(jié)構(gòu)。

bereq.backend:所請(qǐng)求后端節(jié)點(diǎn)配置。

bereq.between_bytes_timeout:從后端每接收一個(gè)字節(jié)之間的等待時(shí)間(秒)。

bereq.connect_timeout:連接后端等待時(shí)間(秒),最大等待時(shí)間。

bereq.first_byte_timeout:等待后端第一個(gè)字節(jié)時(shí)間(秒),最大等待時(shí)間。

bereq.http:對(duì)應(yīng)發(fā)送到后端HTTP的header信息。

bereq.method:發(fā)送到后端的請(qǐng)求類型(如:GET , POST)。

bereq.proto:發(fā)送到后端的請(qǐng)求的HTTP版本。

bereq.retries:相同請(qǐng)求重試計(jì)數(shù)。

bereq.uncacheable:無(wú)緩存這個(gè)請(qǐng)求。

bereq.url:發(fā)送到后端請(qǐng)求的URL。

bereq.xid:請(qǐng)求唯一ID。

?

beresp:(后端響應(yīng)請(qǐng)求對(duì)象)

beresp:整個(gè)后端響應(yīng)HTTP數(shù)據(jù)結(jié)構(gòu)。

beresp.backend.ip:后端響應(yīng)的IP。

beresp.backend.name:響應(yīng)后端配置節(jié)點(diǎn)的name。

beresp.do_gunzip:默認(rèn)為 false 。緩存前解壓該對(duì)象

beresp.do_gzip:默認(rèn)為 false 。緩存前壓縮該對(duì)象

beresp.grace:設(shè)置當(dāng)前對(duì)象緩存過(guò)期后可額外寬限時(shí)間,用于特殊請(qǐng)求加大緩存時(shí)間,當(dāng)并發(fā)量巨大時(shí),不易設(shè)置過(guò)大否則會(huì)堵塞緩存,一般可設(shè)置 1m 左右,當(dāng)beresp.ttl=0s時(shí)該值無(wú)效。

beresp.http:對(duì)應(yīng)的HTTP請(qǐng)求header

beresp.keep:對(duì)象緩存后帶保持時(shí)間

beresp.proto:響應(yīng)的HTTP版本
beresp.reason:由服務(wù)器返回的HTTP狀態(tài)信息

beresp.status:由服務(wù)器返回的狀態(tài)碼

beresp.storage_hint:指定保存的特定存儲(chǔ)器

beresp.ttl:該對(duì)象緩存的剩余時(shí)間,指定統(tǒng)一緩存剩余時(shí)間。

beresp.uncacheable:繼承bereq.uncacheable,是否不緩存

?

OBJ :(高速緩存對(duì)象,緩存后端響應(yīng)請(qǐng)求內(nèi)容)

obj.grace:該對(duì)象額外寬限時(shí)間

obj.hits:緩存命中次數(shù),計(jì)數(shù)器從1開(kāi)始,當(dāng)對(duì)象緩存該值為1,一般可以用于判斷是否有緩存,當(dāng)前該值大于0時(shí)則為有緩存。

obj.http:對(duì)應(yīng)HTTP的header

obj.proto:HTTP版本

obj.reason:服務(wù)器返回的HTTP狀態(tài)信息

obj.status:服務(wù)器返回的狀態(tài)碼

obj.ttl:該對(duì)象緩存剩余時(shí)間(秒)

obj.uncacheable:不緩存對(duì)象

?

resp :(返回給客戶端的響應(yīng)對(duì)象)

resp:整個(gè)響應(yīng)HTTP數(shù)據(jù)結(jié)構(gòu)。

resp.http:對(duì)應(yīng)HTTP的header。

resp.proto:編輯響應(yīng)的HTTP協(xié)議版本。

resp.reason:將要返回的HTTP狀態(tài)信息。

resq.status:將要返回的HTTP狀態(tài)碼。

?

存儲(chǔ) :

storage.<name>.free_space:存儲(chǔ)可用空間(字節(jié)數(shù))。

storage.<name>.used_space:存儲(chǔ)已經(jīng)使用空間(字節(jié)數(shù))。

storage.<name>.happy:存儲(chǔ)健康狀態(tài)。

?

8、特定功能性語(yǔ)句

ban(expression):清除指定對(duì)象緩存

call(subroutine):調(diào)用子程序,如:call(name);

hash_data(input):生成hash鍵,用于制定hash鍵值生成結(jié)構(gòu),只能在vcl_hash子程序中使用。調(diào)用 hash_data(input) 后,即這個(gè)hash為當(dāng)前頁(yè)面的緩存hash鍵值,無(wú)需其它獲取或操作,如:

sub?vcl_hash{

???????hash_data(client.ip);

???????return(lookup);

}

注意:return(lookup); 是默認(rèn)返回值,所以可以不寫(xiě)。

new():創(chuàng)建一個(gè)vcl對(duì)象,只能在vcl_init子程序中使用。

return():結(jié)束當(dāng)前子程序,并指定繼續(xù)下一步動(dòng)作,如:return (ok); 每個(gè)子程序可指定的動(dòng)作均有不同。

rollback():恢復(fù)HTTP頭到原來(lái)狀態(tài),已經(jīng)棄用,使用 std.rollback() 代替。

synthetic(STRING):合成器,用于自定義一個(gè)響應(yīng)內(nèi)容,比如當(dāng)請(qǐng)求出錯(cuò)時(shí),可以返回自定義 404 內(nèi)容,而不只是默認(rèn)頭信息,只能在 vcl_synth 與 vcl_backend_error 子程序中使用,如:

sub?vcl_synth?{

????//自定義內(nèi)容

????synthetic?({"

<!DOCTYPE?HTML?PUBLIC?"-//W3C//DTD?HTML?4.01?Transitional//EN">

<html?lang="zh-cn">

???<head>

???<meta?http-equiv="Content-Type"?content="text/html;?charset=utf-8"/>

??????<title>error</title>

???</head>

???<body>

??????<h1>Error</h1>

??????<h3>這只是一個(gè)測(cè)試自定義響應(yīng)異常內(nèi)容</h3>

???</body>

</html>

????"});

????//只交付自定義內(nèi)容

????return(deliver);

?

regsub(str, regex, sub):使用正則替換第一次出現(xiàn)的字符串,第一個(gè)參數(shù)為待處理字符串,第二個(gè)參數(shù)為正則表達(dá)式,第三個(gè)為替換為字符串。

regsuball(str, regex, sub):使用正則替換所有匹配字符串。參數(shù)與regsuball相同。

具體變量詳見(jiàn):

https://www.varnish-cache.org/docs/4.0/reference/vcl.html#reference-vcl

?

(9)return 語(yǔ)句:

return 語(yǔ)句是終止子程序并返回動(dòng)作,所有動(dòng)作都根據(jù)不同的vcl子程序限定來(lái)選用。

https://www.varnish-cache.org/docs/4.0/users-guide/vcl-built-in-subs.html

語(yǔ)法:return(action);

常用的動(dòng)作:

abandon? 放棄處理,并生成一個(gè)錯(cuò)誤。

deliver? 交付處理

fetch? 從后端取出響應(yīng)對(duì)象

hash? 哈希緩存處理

lookup?查找緩存對(duì)象

ok?繼續(xù)執(zhí)行

pass? 進(jìn)入pass非緩存模式

pipe?進(jìn)入pipe非緩存模式

purge?清除緩存對(duì)象,構(gòu)建響應(yīng)

restart?重新開(kāi)始

retry?重試后端處理

synth(status code,reason)?合成返回客戶端狀態(tài)信息

?

10)varnish中內(nèi)置子程序有:

注:varnish內(nèi)置子程序均有自己限定的返回動(dòng)作??return (動(dòng)作);? 不同的動(dòng)作將調(diào)用對(duì)應(yīng)下一個(gè)子程序。

vcl_recv子程序:

開(kāi)始處理請(qǐng)求,通過(guò)?return (動(dòng)作);?選擇varnish處理模式,默認(rèn)進(jìn)入hash緩存模式(即return(hash);),緩存時(shí)間為配置項(xiàng)default_ttl(默認(rèn)為 120秒)過(guò)期保持時(shí)間default_grace(默認(rèn)為10秒)。該子程序一般用于模式選擇,請(qǐng)求對(duì)象緩存及信息修改,后端節(jié)點(diǎn)修改,終止請(qǐng)求等操作。

可操作對(duì)象:(部分或全部值)

讀:client,server,req,storage

寫(xiě):client,req

返回值:

synth(status code,reason);? 定義響應(yīng)內(nèi)容。

pass? 進(jìn)入pass模式,并進(jìn)入vcl_pass子程序。

pipe? 進(jìn)入pipe模式,并進(jìn)入vcl_pipe子程序。

hash? 進(jìn)入hash緩存模式,并進(jìn)入vcl_hash子程序,默認(rèn)返回值。

purge? 清除緩存等數(shù)據(jù),子程序先從vcl_hash再到vcl_purge。

?

vcl_pipe子程序:

pipe模式處理,該模式主要用于直接取后端響應(yīng)內(nèi)容返回客戶端,可定義響應(yīng)內(nèi)容返回客戶端。該子程序一般用于需要及時(shí)且不作處理的后端信息,取出后端響應(yīng)內(nèi)容后直接交付到客戶端不進(jìn)入vcl_deliver子程序處理。

可操作對(duì)象:(部分或全部值)

讀:client,server,bereq,req,storage

寫(xiě):client,bereq,req

返回值:

synth(status code,reason);? 定義響應(yīng)內(nèi)容。

pipe? 繼續(xù)pipe模式,進(jìn)入后端vcl_backend_fetch子程序,默認(rèn)返回值。

?

vcl_pass子程序:

pass模式處理,該模式類似hash緩存模式,僅不做緩存處理。

可操作對(duì)象:(部分或全部值)

讀:client,server,req,storage

寫(xiě):client,req

返回值:

synth(status code,reason);? 定義響應(yīng)內(nèi)容。

fetch? 繼續(xù)pass模式,進(jìn)入后端vcl_backend_fetch子程序,默認(rèn)返回值。

?

vcl_hit子程序:

hash緩存模式時(shí),存在hash緩存時(shí)調(diào)用,用于緩存處理,可放棄或修改緩存。

可操作對(duì)象:(部分或全部值)

讀:client,server,obj,req,storage

寫(xiě):client,req

返回值:

restart?重啟請(qǐng)求。

deliver?交付緩存內(nèi)容,進(jìn)入vcl_deliver子程序處理,默認(rèn)返回值。

synth(status code,reason);? 定義響應(yīng)內(nèi)容。

?

vcl_miss子程序:

hash緩存模式時(shí),不存在hash緩存時(shí)調(diào)用,用于判斷性的選擇進(jìn)入后端取響應(yīng)內(nèi)容,可以修改為pass模式。

可操作對(duì)象:(部分或全部值)

讀:client,server,req,storage

寫(xiě):client,req

返回值:

restart?重啟請(qǐng)求。

synth(status code,reason);? 定義響應(yīng)內(nèi)容。

pass?切換到pass模式,進(jìn)入vcl_pass子程序。

fetch? 正常取后端內(nèi)容再緩存,進(jìn)入vcl_backend_fetch子程序,默認(rèn)返回值。

?

vcl_hash子程序:

hash緩存模式,生成hash值作為緩存查找鍵名提取緩存內(nèi)容,主要用于緩存hash鍵值處理,可使用hash_data(string) 指定鍵值組成結(jié)構(gòu),可在同一個(gè)頁(yè)面通過(guò)IP或cookie生成不同的緩存鍵值。

可操作對(duì)象:(部分或全部值)

讀:client,server,req,storage

寫(xiě):client,req

返回值:

lookup?查找緩存對(duì)象,存在緩存進(jìn)入vcl_hit子程序,不存在緩存進(jìn)入vcl_miss子程序,當(dāng)使用了purge清理模式時(shí)會(huì)進(jìn)入vcl_purge子程序,默認(rèn)返回值。

?

vcl_purge子程序:

清理模式,當(dāng)查找到對(duì)應(yīng)的緩存時(shí)清除并調(diào)用,用于請(qǐng)求方法清除緩存,并報(bào)告。

可操作對(duì)象:(部分或全部值)

讀:client,server,req,storage

寫(xiě):client,req

返回值:

synth(status code,reason);? 定義響應(yīng)內(nèi)容。

restart?重啟請(qǐng)求。

?

vcl_deliver子程序:

客戶端交付子程序,在vcl_backend_response子程序后調(diào)用(非pipe模式),或vcl_hit子程序后調(diào)用,可用于追加響應(yīng)頭信息,cookie等內(nèi)容。

可操作對(duì)象:(部分或全部值)

讀:client,server,req,resp,obj,storage

寫(xiě):client,req,resp

返回值:

deliver?正常交付后端或緩存響應(yīng)內(nèi)容,默認(rèn)返回值。

restart?重啟請(qǐng)求。

?

vcl_backend_fetch子程序:

發(fā)送后端請(qǐng)求之前調(diào)用,可用于改變請(qǐng)求地址或其它信息,或放棄請(qǐng)求。

可操作對(duì)象:(部分或全部值)

讀:server,bereq,storage

寫(xiě):bereq

返回值:

fetch?正常發(fā)送請(qǐng)求到到后端取出響應(yīng)內(nèi)容,進(jìn)入vcl_backend_response子程序,默認(rèn)返回值。

abandon?放棄后端請(qǐng)求,并生成一個(gè)錯(cuò)誤,進(jìn)入vcl_backend_error子程序。

?

vcl_backend_response子程序:

后端響應(yīng)后調(diào)用,可用于修改緩存時(shí)間及緩存相關(guān)信息。

可操作對(duì)象:(部分或全部值)

讀:server,bereq,beresp,storage

寫(xiě):bereq,beresp

返回值:

deliver?正常交付后端響應(yīng)內(nèi)容,進(jìn)入vcl_deliver子程序,默認(rèn)返回值。

abandon?放棄后端請(qǐng)求,并生成一個(gè)錯(cuò)誤,進(jìn)入vcl_backend_error子程序。

retry?重試后端請(qǐng)求,重試計(jì)數(shù)器加1,當(dāng)超過(guò)配置中max_retries值時(shí)會(huì)報(bào)錯(cuò)并進(jìn)入vcl_backend_error子程序。

?

vcl_backend_error子程序:

后端處理失敗調(diào)用,異常頁(yè)面展示效果處理,可自定義錯(cuò)誤響應(yīng)內(nèi)容,或修改beresp.status與beresp.http.Location重定向等。

可操作對(duì)象:(部分或全部值)

讀:server,bereq,beresp,storage

寫(xiě):bereq,beresp

返回值:

deliver?只交付 sysnthetic(string) 自定義內(nèi)容,默認(rèn)返回后端異常標(biāo)準(zhǔn)錯(cuò)誤內(nèi)容。

retry?重試后端請(qǐng)求,重試計(jì)數(shù)器加1,當(dāng)超過(guò)配置中max_retries值時(shí)會(huì)報(bào)錯(cuò)并進(jìn)入vcl_backend_error子程序。

?

vcl_synth子程序:

自定義響應(yīng)內(nèi)容。可以通過(guò)synthetic()和返回值 synth 調(diào)用,這里可以自定義異常顯示內(nèi)容,也可以修改resp.status與resp.http.Location重定向。

可操作對(duì)象:(部分或全部值)

讀:client,server,req,resp,storage

寫(xiě):req,resp

返回值:

deliver?只交付 sysnthetic(string) 自定義內(nèi)容,默認(rèn)返回 sysnth 異常指定狀態(tài)碼與錯(cuò)誤內(nèi)容。

restart?重啟請(qǐng)求。

?

vcl_init子程序:

加載vcl時(shí)最先調(diào)用,用于初始化VMODs,該子程序不參與請(qǐng)求處理,僅在vcl加載時(shí)調(diào)用一次。

可操作對(duì)象:(部分或全部值)

讀:server

寫(xiě):無(wú)

返回值:

ok?正常返回,進(jìn)入vcl_recv子程序,默認(rèn)返回值。

?

vcl_fini子程序:

卸載當(dāng)前vcl配置時(shí)調(diào)用,用于清理VMODs,該子程序不參與請(qǐng)求處理,僅在vcl正常丟棄后調(diào)用。

可操作對(duì)象:(部分或全部值)

讀:server

寫(xiě):無(wú)

返回值:

ok?正常返回,本次vcl將釋放,默認(rèn)返回值。

varnish子程序調(diào)用流程圖,通過(guò)大部分子程序的return返回值進(jìn)入下一步行動(dòng):


11)優(yōu)雅模式(Garce mode)

Varnish中的請(qǐng)求合并

當(dāng)幾個(gè)客戶端請(qǐng)求同一個(gè)頁(yè)面的時(shí)候,varnish只發(fā)送一個(gè)請(qǐng)求到后端服務(wù)器,然后讓其他幾個(gè)請(qǐng)求掛起并等待返回結(jié)果;獲得結(jié)果后,其它請(qǐng)求再?gòu)?fù)制后端的結(jié)果發(fā)送給客戶端;

但如果同時(shí)有數(shù)以千計(jì)的請(qǐng)求,那么這個(gè)等待隊(duì)列將變得龐大,這將導(dǎo)致2類潛在問(wèn)題:

驚群?jiǎn)栴}(thundering herd problem),即突然釋放大量的線程去復(fù)制后端返回的結(jié)果,將導(dǎo)致負(fù)載急速上升;沒(méi)有用戶喜歡等待;

故為了解決這類問(wèn)題,可以配置varnish在緩存對(duì)象因超時(shí)失效后再保留一段時(shí)間,以給那些等待的請(qǐng)求返回過(guò)去的文件內(nèi)容(stale content),配置案例如下:

sub vcl_recv {

if (! req.backend.healthy) {

set req.grace = 5m;

} else {

set req.grace = 15s;

}

}

sub vcl_fetch {

set beresp.grace = 30m;

}

以上配置表示varnish將會(huì)將失效的緩存對(duì)象再多保留30分鐘,此值等于最大的req.grace值即可;

而根據(jù)后端主機(jī)的健康狀況,varnish可向前端請(qǐng)求分別提供5分鐘內(nèi)或15秒內(nèi)的過(guò)期內(nèi)容

二、安裝varnish

1、安裝依賴關(guān)系的軟件包(注:使用centos在線yum源)

[root@varnish ~]# yum -y install autoconf automake libedit-devel libtool ncurses-devel pcre-devel pkgconfig python-docutils python-sphinx

2、安裝varnish

Varnish的官方網(wǎng)址為http://varnish-cache.org,可以在這里下載最新版本的軟件。

下載地址:https://www.varnish-cache.org/content/varnish-cache-403

注意:Varnish網(wǎng)站有時(shí)會(huì)被墻。

Git 下載:git clone https://github.com/varnish/Varnish-Cache /var/tmp/

解壓,進(jìn)入解壓目錄編譯安裝:

[root@varnish ~]# tar zxf varnish-4.0.3.tar.gz

[root@varnish ~]# cd varnish-4.0.3/

[root@varnish varnish-4.0.3]# export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig

注:

./autogen.sh?

如果從Git庫(kù)下載的安裝包時(shí)才需要運(yùn)行,用于生成configure編譯文件。

配置:

[root@varnish varnish-4.0.3]# ./configure

注:不指定安裝路徑,默認(rèn)是安裝在/usr/local目錄下

編譯、安裝

[root@varnish varnish-4.0.3]# make && make install

復(fù)制 vcl 文件(在編譯安裝目錄下),如果安裝目錄里沒(méi)有 default.vcl 文件。

復(fù)制到安裝目錄的/usr/local/var/varnish/目錄下(當(dāng)然并無(wú)必需要求在哪個(gè)目錄,因?yàn)檎絾?dòng)時(shí)還得指定這個(gè)文件的目錄)

[root@varnish varnish-4.0.3]# cp etc/example.vcl ?/usr/local/var/varnish/default.vcl

三、varnish實(shí)例解析:

varnish 配置基本上是編輯 VCL(Varnish?Configuration?Language) 文件,varnish 有一套自定義 VCL 語(yǔ)法,啟動(dòng)時(shí),會(huì)將配置文件編譯為C語(yǔ)言,再執(zhí)行。

varnish 4.0開(kāi)始,每個(gè)VCL文件必須在開(kāi)始行聲明它的版本“vcl 4.0;”

塊(子程序)由大括號(hào)分隔,語(yǔ)句用分號(hào)結(jié)束。所有的關(guān)鍵字及預(yù)設(shè)子程序名都是全小寫(xiě)。

注釋:支持 // 或 #? 多行時(shí)還可以使用 /* .. */

1、后端服務(wù)器地址池配置及后端服務(wù)器健康檢查

varnish有"后端"或者"源"服務(wù)器的概念。backend server提供給varnish加速的內(nèi)容。實(shí)際上就是給varnish添加可供訪問(wèn)的web服務(wù)器,如果有多臺(tái)web服務(wù)器時(shí),可添加多個(gè)backend塊。

1)后端服務(wù)器定義:

命令:backend。這個(gè)定義為最基本的反向入口定義,用于varnish連接對(duì)應(yīng)的服務(wù)器,如果沒(méi)有定義或定義錯(cuò)誤則用戶無(wú)法訪問(wèn)正常頁(yè)面。

語(yǔ)法格式:

backend?name{

????.attribute?=?"value";

}

說(shuō)明:backend?是定義后端關(guān)鍵字,name?是當(dāng)前后端節(jié)點(diǎn)的別名,多個(gè)后端節(jié)點(diǎn)時(shí),name 名不能重復(fù),否則覆蓋。花括號(hào)里面定義當(dāng)前節(jié)點(diǎn)相關(guān)的屬性(鍵=值)。除默認(rèn)節(jié)點(diǎn)外其它節(jié)點(diǎn)定義后必需有調(diào)用,否則varnish無(wú)法啟動(dòng)。后端是否正常可以通過(guò)std.healthy(backend)判斷。

支持運(yùn)算符:

=?? (賦值運(yùn)算)

==? (相等比較)

~??? (匹配,可以使用正則表達(dá)式,或訪問(wèn)控制列表)

!~??? (不匹配,可以使用正則表達(dá)式,或訪問(wèn)控制列表)

!? (非)

&&?? (邏輯與)

||?? (邏輯或)

屬性列表:

.host="xxx.xxx.xxx.xxx";????? //要轉(zhuǎn)向主機(jī)(即后端主機(jī))的IP或域名,必填鍵/值對(duì)。
.port="8080";??????? //主機(jī)連接端口號(hào)或協(xié)議名(HTTP等),默認(rèn)80
.host_header='';??? //請(qǐng)示主機(jī)頭追加內(nèi)容
.connect_timeout=1s;???? //連接后端的超時(shí)時(shí)間
.first_byte_timeout=5s;??? //等待從后端返回的第一個(gè)字節(jié)時(shí)間
.between_bytes_timeout=2s;???? //每接收一個(gè)字節(jié)之間等待時(shí)間
.probe=probe_name;??????? //監(jiān)控后端主機(jī)的狀態(tài),指定外部監(jiān)控name或者內(nèi)部直接添加
.max_connections=200;??? //設(shè)置最大并發(fā)連接數(shù),超過(guò)這個(gè)數(shù)后連接就會(huì)失敗

例:(下面兩個(gè)例子結(jié)果是一樣的,但第二個(gè)例子中更適用于集群,可以方便批量修改)

backend?web{

????.host="192.168.31.83";

????.port="80";

????.probe={??????????//直接追加監(jiān)控塊.probe是一個(gè)的參數(shù)

????????.url="/";

????????.timeout=2s;

????}

}

probe?web_probe{???//監(jiān)控必需定義在前面,否則后端調(diào)用找不到監(jiān)控塊。

????.url="/";

????.timeout=2s;

}

?

backend?web{

????.host="192.168.31.83";

????.port="80";

????.probe=web_probe;???//調(diào)用外部共用監(jiān)控塊

}

?

2)監(jiān)視器定義:

命令:probe 。監(jiān)控可以循環(huán)訪問(wèn)指定的地址,通過(guò)響應(yīng)時(shí)間判定服務(wù)器是否空閑或正常。這類命令非常適用于集群中某些節(jié)點(diǎn)服務(wù)器崩潰或負(fù)載過(guò)重,而禁止訪問(wèn)這臺(tái)節(jié)點(diǎn)服務(wù)器。

語(yǔ)法格式:

probe?name{

????.attribute?=?"value";

}

說(shuō)明:probe?是定義監(jiān)控關(guān)鍵字,name?是當(dāng)前監(jiān)控點(diǎn)的別名,多個(gè)監(jiān)控節(jié)點(diǎn)時(shí),name 名不能重復(fù),否則覆蓋。花括號(hào)里面定義當(dāng)前節(jié)點(diǎn)相關(guān)的屬性(鍵=值)。

沒(méi)有必填屬性,因?yàn)槟J(rèn)值就可以正常執(zhí)行操作。

屬性列表:

.url="/";??? //指定監(jiān)控入口URL地址,默認(rèn)為"/"

.request="";?? //指定監(jiān)控請(qǐng)求入口地址,比 .url 優(yōu)先級(jí)高。
.expected_response="200";?? //請(qǐng)求響應(yīng)代碼,默認(rèn)是 200
.timeout=2s;?? //請(qǐng)求超時(shí)時(shí)間。
.interval=5s;???? //每次輪詢請(qǐng)求間隔時(shí)間,默認(rèn)為 5s 。
.initial=-1;???? //初始啟動(dòng)時(shí)以.window輪詢次數(shù)中幾次良好后續(xù)才能使用這個(gè)后端服務(wù)器節(jié)點(diǎn),默認(rèn)為 -1 ,則輪詢完 .window 所有次數(shù)良好判定為正常。
.window=8;?? //指定多少輪詢次數(shù),用于判定服務(wù)器正常,默認(rèn)是 8。
.threshold=3;?? //必須多少次輪詢正常才算該后端節(jié)點(diǎn)服務(wù)器正常,默認(rèn)是 3。

例:創(chuàng)建健康監(jiān)測(cè),定義健康檢查名稱為backend_healthcheck

probe?backend_healthcheck?{

????????.url?=?"/";

????????.timeout?=?1s;

????????.interval?=?5s;

????????.window?=?5;

????????.threshold?=?3;

????}

在上面的例子中varnish將每5s檢測(cè)后端,超時(shí)設(shè)為1s。每個(gè)檢測(cè)將會(huì)發(fā)送get /的請(qǐng)求。如果5個(gè)檢測(cè)中大于3個(gè)是成功,varnish就認(rèn)為后端是健康的,反之,后端就有問(wèn)題了。

?

3)集群負(fù)載均衡directors:

varnish可以定義多個(gè)后端,也可以將幾個(gè)后端放在一個(gè)后端集群里面已達(dá)到負(fù)載均衡的目的。

你也可以將幾個(gè)后端組成一組后端。這個(gè)組被叫做Directors。可以提高性能和彈性。

directors是varnish負(fù)載均衡模塊,使用前必需引入directors模塊,directors模塊主要包含:round_robin,random,hash,fallback負(fù)載均衡模式。

round_robin?: 循環(huán)依次逐個(gè)選擇后端服務(wù)器。

random?: 隨機(jī)選擇后端服務(wù)器,可設(shè)置每個(gè)后端權(quán)重增加隨機(jī)率。

hash?:? 通過(guò)散列隨機(jī)選擇對(duì)應(yīng)的后端服務(wù)器且保持選擇對(duì)應(yīng)關(guān)系,下次則直接找對(duì)應(yīng)的后端服務(wù)器。

Fallback:后備

注意:random,hash 有權(quán)重值設(shè)置,用于提高隨機(jī)率。每個(gè)后端最好都配置監(jiān)控器(后端服務(wù)器正常監(jiān)測(cè))以便directors自動(dòng)屏蔽不正常后端而不進(jìn)入均衡列隊(duì)中。

這些操作需要你載入VMOD(varnish module),然后在vcl_init中調(diào)用這個(gè)VMOD。

import?directors;???? ? ? ? ? ? ?#?load?the?directors

backend?web1?{

.host?=?"192.168.0.10";

.port = "80";

.probe = backend_healthcheck;

}

backend?web2?{

.host?=?"192.168.0.11";

.port = "80";

.probe = backend_healthcheck;

}

//初始化處理

sub?vcl_init?{ ? ? ? ? ? ?//調(diào)用vcl_init初始化子程序創(chuàng)建后端主機(jī)組,即directors

????new ?web_cluster?=?directors.round_robin(); //使用new關(guān)鍵字創(chuàng)建drector對(duì)象,使用round_robin算法

????web_cluster.add_backend(web1); ? //添加后端服務(wù)器節(jié)點(diǎn)

web_cluster.add_backend(web2);

}

//開(kāi)始處理請(qǐng)求

sub?vcl_recv?{ ? ? ? ? ? ? ? ? ? ? //調(diào)用vcl_recv子程序,用于接收和處理請(qǐng)求

????set ?req.backend_hint?=?web_cluster.backend(); ? ? //選取后端

}

說(shuō)明:

set命令是設(shè)置變量

unset命令是刪除變量

web_cluster.add_backend( backend , real );? 添加后端服務(wù)器節(jié)點(diǎn),backend 為后端配置別名,real 為權(quán)重值,隨機(jī)率計(jì)算公式:100 * (當(dāng)前權(quán)重 / 總權(quán)重)。

req.backend_hint是varnish的預(yù)定義變量,作用是指定請(qǐng)求后端節(jié)點(diǎn)

vcl對(duì)象需要使用new關(guān)鍵字創(chuàng)建,所有可創(chuàng)建對(duì)象都是內(nèi)定的,使用前必需import,所有new操作只能在vcl_init子程序中。

擴(kuò)展:varnish將不同的url發(fā)送到不同的后端server

import?directors;???? ? ? ? ? ? ?#?load?the?directors

backend?web1?{

.host?=?"192.168.0.10";

.port = "80";

.probe = backend_healthcheck;

}

backend?web2?{

.host?=?"192.168.0.11";

.port = "80";

.probe = backend_healthcheck;

}

backend img1 {

????????.host = "img1.lnmmp.com";

????????.port = "80";

????????.probe = backend_healthcheck;

}

backend img2 {

????????.host = "img2.lnmmp.com";

????????.port = "80";

????????.probe = backend_healthcheck;

}

//初始化處理

sub?vcl_init?{ ? ? ? ? ? ?//調(diào)用vcl_init初始化子程序創(chuàng)建后端主機(jī)組,即directors

????new ?web_cluster?=?directors.round_robin(); //使用new關(guān)鍵字創(chuàng)建drector對(duì)象,使用round_robin算法

????web_cluster.add_backend(web1); ? //添加后端服務(wù)器節(jié)點(diǎn)

web_cluster.add_backend(web2);

new img_cluster = directors.random();

img_cluster.add_backend(img1,2); ? //添加后端服務(wù)器節(jié)點(diǎn)并且設(shè)置權(quán)重值

img_cluster.add_backend(img2,5);

}

//根據(jù)不同的訪問(wèn)域名,分發(fā)至不同的后端主機(jī)組

sub?vcl_recv?{

if (req.http.host ~ "(?i)^(www.)?benet.com$") {

????????????????set ?req.http.host = "www.benet.com";

????????????????set ?req.backend_hint = web_cluster.backend(); ?//選取后端

????????} elsif (req.http.host ?~ ?"(?i)^p_w_picpaths.benet.com$") {

????????? ? set ?req.backend_hint = img_cluster.backend();

????????}

}

說(shuō)明:中的i就是忽略大小寫(xiě)的意思。(?i)表示開(kāi)啟忽略大小寫(xiě),而(?-i)表示關(guān)閉忽略大小寫(xiě)

?

4)訪問(wèn)控制列表(ACL):

創(chuàng)建一個(gè)地址列表,用于后面的判斷,可以是域名或IP集合。這個(gè)可以用于指定某些地址請(qǐng)求入口,防止惡意請(qǐng)求等。

語(yǔ)法格式:

acl ?purgers ?{

????"127.0.0.1";

"localhost";

“192.168.134.0/24”

????!"192.168.134.1";

}

說(shuō)明:acl?是訪問(wèn)列表關(guān)鍵字(必需小寫(xiě)),name?是該列表的別名用于調(diào)用,花括號(hào)內(nèi)部是地址集。

注意:如果列表中包含了無(wú)法解析的主機(jī)地址,它會(huì)匹配任何地址。

如果不想讓它匹配可以在前添加一個(gè) ! 符號(hào),如上面 !"192.168.134.1";?

使用ACL只需要用 匹配運(yùn)算符 ~ 或 !~? 如:

sub ?vcl_recv?{

????if? (req.method?==?"PURGE")?{ ? ?//PURGE請(qǐng)求的處理

??????? ?if ?(client.ip ?~ ?purgers)?{

???????????? ?return(purge);

??????? ?}?else?{

????????????return(synth(403,?"Access?denied."));

????????}

????}

}

?

5)緩存規(guī)則配置:

sub vcl_recv {

? // PURGE請(qǐng)求的處理

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

? ? if (!client.ip ~ purgers) {

? ? ? return (synth(405, "Not Allowed."));

? ? }

? ? return (purge);

? }

?

? set req.backend_hint = web.backend();

?

? //將php、asp等動(dòng)態(tài)內(nèi)容訪問(wèn)請(qǐng)求直接發(fā)給后端服務(wù)器,不緩存。

? if (req.url ~ "\.(php|asp|aspx|jsp|do|ashx|shtml)($|\?)") {

? ? return (pass);

? }

? //將非GET和HEAD訪問(wèn)請(qǐng)求直接發(fā)給后端服務(wù)器,不緩存。例如POST請(qǐng)求。

? if (req.method != "GET" && req.method != "HEAD") {

? ? ? ? return (pass);

? }

? //如果varnish看到header中有'Authorization'頭,它將pass請(qǐng)求。

? if (req.http.Authorization) {

? ? ? ? return (pass);

}

?

? //帶cookie首部的GET請(qǐng)求也緩存

? if (req.url ~ "\.(css|js|html|htm|bmp|png|gif|jpg|jpeg|ico|gz|tgz|bz2|tbz|zip|rar|mp3|mp4|ogg|swf|flv)($|\?)") {

? ? unset req.http.cookie;

? ? return (hash);

? }

說(shuō)明:默認(rèn)情況,varnish不緩存從后端響應(yīng)的http頭中帶有Set-Cookie的對(duì)象。如果客戶端發(fā)送的請(qǐng)求帶有Cookie header,varnish將忽略緩存,直接將請(qǐng)求傳遞到后端。

?

//為發(fā)往后端主機(jī)的請(qǐng)求添加X(jué)-Forward-For首部,首次訪問(wèn)增加 X-Forwarded-For 頭信息,方便后端程序獲取客戶端ip,而不是varnish地址

if (req.restarts == 0) {

? ? ? ? if (req.http.x-forwarded-for) {//如果設(shè)置過(guò)此header則要再次附加上用逗號(hào)隔開(kāi)

? ? ? ? ? ? set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;

? ? ? ? } else {//如果只有一層代理的話,就無(wú)需設(shè)置了

? ? ? ? ? ? set req.http.X-Forwarded-For = client.ip;

? ? ? ? }

}

說(shuō)明:X-Forwarded-For 是用來(lái)識(shí)別通過(guò)HTTP代理或負(fù)載均衡方式連接到Web服務(wù)器的客戶端最原始的IP地址的HTTP請(qǐng)求頭字段

子程序:

?

子程序是一種類似C的函數(shù),但是程序沒(méi)有調(diào)用參數(shù),子程序以 sub 關(guān)鍵字定義。在VCL里子程序是用于管理程序。

注意:所有VCL內(nèi)置的程序都是以 vcl_ 開(kāi)頭,并已經(jīng)預(yù)置好,在VCL文件中只要聲明對(duì)應(yīng)的內(nèi)置子程序,都會(huì)在對(duì)應(yīng)的流程中調(diào)用。

三、varnish完整配置實(shí)例

1、拓?fù)洵h(huán)境

Varnish:192.168.31.250

Web01:192.168.31.83

Web02:192.168.31.141

配置web01、web02做為后端服務(wù)器(過(guò)程略)

確保varnish服務(wù)器能正常訪問(wèn)web01、web02

Varnish緩存代理服務(wù)器配置:

2、vcl文件配置內(nèi)容:

[root@varnish ~]# cat ?/usr/local/var/varnish/default.vcl

#使用varnish版本4的格式.

vcl 4.0;

#加載后端負(fù)載均衡模塊

import directors;

#加載std模塊

import std;

#創(chuàng)建名為backend_healthcheck的健康檢查策略

probe backend_healthcheck {

? ? .url="/";

? ? .interval = 5s;

? ? .timeout = 1s;

? ? .window = 5;

? ? .threshold = 3;

}

#定義后端服務(wù)器

backend web_app_01 {

? ? .host = "192.168.31.83";

? ? .port = "80";

? ? .first_byte_timeout = 9s;

? ? .connect_timeout = 3s;

? ? .between_bytes_timeout = 1s;

? ? .probe = backend_healthcheck;

}

backend web_app_02 {

? ? .host = "192.168.31.141";

? ? .port = "80";

? ? .first_byte_timeout = 9s;

? ? .connect_timeout = 3s;

? ? .between_bytes_timeout = 1s;

? ? .probe = backend_healthcheck;

}

#定義允許清理緩存的IP

acl purgers {

? ? "127.0.0.1";

? ? "localhost";

? ? "192.168.31.0/24";

}

#vcl_init初始化子程序創(chuàng)建后端主機(jī)組

sub vcl_init {

? ? new web = directors.round_robin();

? ? web.add_backend(web_app_01);

? ? web.add_backend(web_app_02);

}

#請(qǐng)求入口用于接收和處理請(qǐng)求這里一般用作路由處理判斷是否讀取緩存和指定該請(qǐng)求使用哪個(gè)后端

sub vcl_recv {

? ? #將請(qǐng)求指定使用web后端集群?.在集群名后加上 .backend()

set req.backend_hint = web.backend();

# 匹配清理緩存的請(qǐng)求

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

? ? ? ? if (!client.ip ~ purgers) {

? ? ? ? ? ? return (synth(405, "Not Allowed."));

? ? ? ? }

? ? ? ? # 是的話就執(zhí)行清理

? ? ? ? return (purge);

? ? }

? ? # 如果不是正常請(qǐng)求 就直接穿透沒(méi)商量

? ? if (req.method != "GET" &&

? ? ? req.method != "HEAD" &&

? ? ? req.method != "PUT" &&

? ? ? req.method != "POST" &&

? ? ? req.method != "TRACE" &&

? ? ? req.method != "OPTIONS" &&

? ? ? req.method != "PATCH" &&

? ? ? req.method != "DELETE") {

? ? ? return (pipe);

? ? }

? ? # 如果不是GET和HEAD就跳到pass

? ? if (req.method != "GET" && req.method != "HEAD") {

? ? ? ? return (pass);

? ? }

? ? #如果匹配動(dòng)態(tài)內(nèi)容訪問(wèn)請(qǐng)求就跳到pass

? ? if (req.url ~ "\.(php|asp|aspx|jsp|do|ashx|shtml)($|\?)") {

? ? ? ? return (pass);

? ? }

? ? #具有身份驗(yàn)證的請(qǐng)求跳到pass

? ? if (req.http.Authorization) {

? ? ? ? return (pass);

? ? }

?

? ? if (req.http.Accept-Encoding) {

? ? ? ? if (req.url ~ "\.(bmp|png|gif|jpg|jpeg|ico|gz|tgz|bz2|tbz|zip|rar|mp3|mp4|ogg|swf|flv)$") {

? ? ? ? ? ? unset req.http.Accept-Encoding;

? ? ? ? } elseif (req.http.Accept-Encoding ~ "gzip") {

? ? ? ? ? ? set req.http.Accept-Encoding = "gzip";

? ? ? ? } elseif (req.http.Accept-Encoding ~ "deflate") {

? ? ? ? ? ? set req.http.Accept-Encoding = "deflate";

? ? ? ? } else {

? ? ? ? ? ? unset req.http.Accept-Encoding;

? ? ? ? }

? ? }

?

? ? if (req.url ~ "\.(css|js|html|htm|bmp|png|gif|jpg|jpeg|ico|gz|tgz|bz2|tbz|zip|rar|mp3|mp4|ogg|swf|flv)($|\?)") {

? ? ? ? unset req.http.cookie;

? ? ? ? return (hash);

}

# 把真實(shí)客戶端IP傳遞給后端服務(wù)器 后端服務(wù)器日志使用X-Forwarded-For來(lái)接收

? ? if (req.restarts == 0) {

? ? ? ? if (req.http.X-Forwarded-For) {

? ? ? ? ? ? set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;

? ? ? ? } else {

? ? ? ? ? ? set req.http.X-Forwarded-For = client.ip;

? ? ? ? }

? ? }

? ? return (hash);

}

# hash事件(緩存事件)

sub vcl_hash {

? ? hash_data(req.url);

? ? if (req.http.host) {

? ? ? ? hash_data(req.http.host);

? ? } else {

? ? ? ? hash_data(server.ip);

? ? }

? ? return (lookup);

}

# 緩存命中事件

sub vcl_hit {

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

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

? ? }

? ? return (deliver);

}

# 緩存不命中事件

sub vcl_miss {

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

? ? ? ? return (synth(404, "Purged."));

? ? }

? ? return (fetch);

}

# 返回給用戶的前一個(gè)事件 通常用于添加或刪除header頭

sub vcl_deliver {

? ? if (obj.hits > 0) {

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

? ? ? ? set resp.http.X-Cache-Hits = obj.hits;

? ? } else {

? ? ? ? set resp.http.X-Cache = "MISS";

}

#取消顯示php框架版本的header頭

unset resp.http.X-Powered-By;

#取消顯示web軟件版本、Via(來(lái)自varnish)等header頭 為了安全

? ? unset resp.http.Server;

? ? unset resp.http.X-Drupal-Cache;

? ? unset resp.http.Via;

? ? unset resp.http.Link;

unset resp.http.X-Varnish;

#顯示請(qǐng)求經(jīng)歷restarts事件的次數(shù)

set resp.http.xx_restarts_count = req.restarts;

#顯示該資源緩存的時(shí)間單位秒

set resp.http.xx_Age = resp.http.Age;

#顯示該資源命中的次數(shù)

set resp.http.hit_count = obj.hits;

#取消顯示Age 為了不和CDN沖突

unset resp.http.Age;

#返回給用戶

? ? return (deliver);

}

# pass事件

sub vcl_pass {

? ? return (fetch);

}

#處理對(duì)后端返回結(jié)果的事件(設(shè)置緩存、移除cookie信息、設(shè)置header頭等) 在fetch事件后自動(dòng)調(diào)用

sub vcl_backend_response {

? ? #開(kāi)啟grace模式 表示當(dāng)后端全掛掉后 即使緩存資源已過(guò)期(超過(guò)緩存時(shí)間) 也會(huì)把該資源返回給用戶 資源最大有效時(shí)間為5分鐘

set beresp.grace = 5m;

#后端返回如下錯(cuò)誤狀態(tài)碼 則不緩存

? ? if (beresp.status == 499 || beresp.status == 404 || beresp.status == 502) {

? ? set beresp.uncacheable = true;

}

#如請(qǐng)求php或jsp 則不緩存

? ? if (bereq.url ~ "\.(php|jsp)(\?|$)") {

? ? ? set beresp.uncacheable = true;

? ? } else { //自定義緩存文件的緩存時(shí)長(zhǎng),即TTL值

? ? ? ?if (bereq.url ~ "\.(css|js|html|htm|bmp|png|gif|jpg|jpeg|ico)($|\?)") {

? ? ? ? ?set beresp.ttl = 15m;

? ? ? ? ?unset beresp.http.Set-Cookie;

? ? ? ?} elseif (bereq.url ~ "\.(gz|tgz|bz2|tbz|zip|rar|mp3|mp4|ogg|swf|flv)($|\?)") {

? ? ? ? ? ?set beresp.ttl = 30m;

? ? ? ? ? ?unset beresp.http.Set-Cookie;

? ? ? ? ?} else {

? ? ? ? ? ? set beresp.ttl = 10m;

? ? ? ? ? ? unset beresp.http.Set-Cookie;

? ? ? ? ?}

? ? ? }

? ? #返回給用戶

? ? return (deliver);

}

sub vcl_purge {

? ? ? ? return (synth(200,"success"));

}

?

sub vcl_backend_error {

? ? if (beresp.status == 500 ||

? ? ? ? beresp.status == 501 ||

? ? ? ? beresp.status == 502 ||

? ? ? ? beresp.status == 503 ||

? ? ? ? beresp.status == 504) {

? ? ? ? return (retry);

? ? }

}

?

sub vcl_fini {

? ? return (ok);

}

?

3、啟動(dòng)varnish

當(dāng)啟動(dòng)varnish時(shí)有兩個(gè)重要的參數(shù)你必須設(shè)置: 一個(gè)是處理http請(qǐng)求的tcp監(jiān)聽(tīng)端口,另一個(gè)是處理真實(shí)請(qǐng)求的后端server

注:如果你使用操作系統(tǒng)自帶的包管理工具安裝的varnish,你將在下面的文件找到啟動(dòng)參數(shù):

Red?Hat,?Centos:?/etc/sysconfig/varnish


1):'-a' 參數(shù)定義了varnish監(jiān)聽(tīng)在哪個(gè)地址,并用該地址處理http請(qǐng)求,你可能想設(shè)置這個(gè)參數(shù)在眾所周知的http 80端口.

例子:

-a? :80

-a ?localhost:80

-a? 192.168.1.100:8080

-a? '[fe80::1]:80'

-a ?'0.0.0.0:8080,[::]:8081'

如果你的webserver和varnish運(yùn)行在同一臺(tái)機(jī)器,你必須換一個(gè)監(jiān)聽(tīng)地址.

2):'-f' ?VCL-file ?or ?'-b' ?backend

-f添加vcl文件,-b定義后端server

varnish需要知道從×××到這個(gè)需要緩存的http server.你可以用-b參數(shù)指定,或者幫把它放在vcl文件中,然后使用-f參數(shù)指定.

在啟動(dòng)的時(shí)候使用-b是一個(gè)快捷的方式.

-b?192.168.1.2:80

注意:如果你指定的是name,這個(gè)name必須能解析成一個(gè)IPv4或者IPv6的地址

如果你使用-f參數(shù),你啟動(dòng)的時(shí)候可以在-f指定vcl文件。

默認(rèn)的varnish使用100M的內(nèi)存來(lái)緩存對(duì)象,如果你想緩存更多,可以使用-s參數(shù).?

注:Varnish擁有大量的有用的命令行參數(shù),建議查看其幫助

[root@varnish ~]# /usr/local/sbin/varnishd -h

?

啟動(dòng)varnish

[root@varnish ~]# /usr/local/sbin/varnishd -f /usr/local/var/varnish/default.vcl -s malloc,200M -a 0.0.0.0:80

[root@varnish ~]# netstat -anpt | grep 80

tcp ? ? 0 ? 0 0.0.0.0:80 ? ? ?0.0.0.0:* ? ? ?LISTEN ? ? ?6173/varnishd

2)現(xiàn)在,varnish已經(jīng)啟動(dòng)和運(yùn)行,你可以通過(guò)varnish訪問(wèn)您的Web應(yīng)用程序。

打開(kāi)火狐瀏覽器

第一次訪問(wèn)


第二次訪問(wèn)


3)varnish4配置手動(dòng)清除緩存

varnish4通過(guò)vcl配置清楚緩存

通過(guò)vcl配置可以讓客戶端手動(dòng)請(qǐng)求清楚緩存,以保證局部數(shù)據(jù)及時(shí)更新,而不用重啟varnish服務(wù)器。

配置方法:

#允許清除緩存IP集

acl purgers {

? ? "127.0.0.1";

? ? "localhost";

? ? "192.168.31.0/24";

}

sub vcl_recv {

? ? ……

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

? ? ? ? if (!client.ip ~ purgers) {

? ? ? ? ? ? return (synth(405, "Not Allowed."));

? ? ? ? }

? ? ? ? return (purge); ? //清除緩存

}

……

}

sub vcl_purge {

? ? ? ? return (synth(200,"success"));

}

打開(kāi)火狐瀏覽器,隨便進(jìn)入一個(gè)緩存頁(yè)面,如下圖所示。


點(diǎn)擊編輯和重發(fā), 修改請(qǐng)求類型為?PURGE?再點(diǎn)擊?發(fā)送

查看返回狀態(tài),如果成功則成功清除緩存,可以按 F5 刷新頁(yè)面,查看新內(nèi)容。


轉(zhuǎn)載于:https://blog.51cto.com/namesam/1908525

總結(jié)

以上是生活随笔為你收集整理的Varnish缓存代理简介与配置的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。