參考:https://www.cnblogs.com/cutemsyu/p/6051876.html
1、varnish程序環(huán)境
軟件包:yum install varnish
/etc/varnish/varnish.params: 配置varnish服務(wù)進(jìn)程的工作特性,例如監(jiān)聽(tīng)的地址和端口,緩存機(jī)制;
/etc/varnish/default.vcl:配置各Child/Cache線程的緩存;
主程序:/usr/sbin/varnishd
/usr/share/doc/varnish-4.0.4/builtin.vcl ---系統(tǒng)內(nèi)置的一些VCL
Systemd Unit File:/usr/lib/systemd/system/varnish.service
程序架構(gòu):
Manager進(jìn)程
Cacher進(jìn)程,包含多種類型的線程:
accept, worker, expiry, ...
也就是一個(gè)主的Manager進(jìn)程和一個(gè)子Cacher進(jìn)程,Cacher進(jìn)程分成很多個(gè)線程來(lái)處理用戶的請(qǐng)求
shared memory log:
統(tǒng)計(jì)數(shù)據(jù):計(jì)數(shù)器;
日志區(qū)域:日志記錄;
varnishlog, varnishncsa, varnishstat...
配置接口:VCL
Varnish Configuration Language,
vcl complier --> c complier --> shared object
2、varnish的緩存存儲(chǔ)機(jī)制( Storage Types)
malloc[,size]內(nèi)存存儲(chǔ),[,size]用于定義空間大?。恢貑⒑笏芯彺骓?xiàng)失效;
file[,path[,size[,granularity]]]磁盤文件存儲(chǔ),黑盒;重啟后所有緩存項(xiàng)失效;
persistent,path,size文件存儲(chǔ),黑盒;重啟后所有緩存項(xiàng)有效;實(shí)驗(yàn)階段,目前還沒(méi)有使用;
3、VCL
Varnish Configuration Language
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

4、變量類型

內(nèi)建變量:
req.*:request,表示由客戶端發(fā)來(lái)的請(qǐng)求報(bào)文相關(guān);
req.http.*
req.http.User-Agent, req.http.Referer, ...
bereq.*:由varnish發(fā)往BE主機(jī)的httpd請(qǐng)求相關(guān);
bereq.http.*
beresp.*:由BE主機(jī)響應(yīng)給varnish的響應(yīng)報(bào)文相關(guān);
beresp.http.*
resp.*:由varnish響應(yīng)給client相關(guān);
obj.*:存儲(chǔ)在緩存空間中的緩存對(duì)象的屬性;只讀;
常用變量:
bereq.*, req.*:
bereq.http.HEADERS
bereq.request:請(qǐng)求方法;
bereq.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.*, resp.*:
beresp.http.HEADERS
beresp.status:響應(yīng)的狀態(tài)碼;
reresp.proto:協(xié)議版本;
beresp.backend.name:BE主機(jī)的主機(jī)名;
beresp.ttl:BE主機(jī)響應(yīng)的內(nèi)容的余下的可緩存時(shí)長(zhǎng);
obj.*
obj.hits:此對(duì)象從緩存中命中的次數(shù);
obj.ttl:對(duì)象的ttl值,也就是有效期
server.*
server.ip:varnish主機(jī)的IP;
server.hostname:varnish主機(jī)的Hostname;
client.*
client.ip:發(fā)請(qǐng)求至varnish主機(jī)的客戶端IP;
5、/etc/varnish/varnish.params的配置
vim /etc/varnish/varnish.params
# 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=192.168.1.5 ---監(jiān)聽(tīng)的地址,默認(rèn)是本機(jī)的所有地址
VARNISH_LISTEN_PORT=6081 ---監(jiān)聽(tīng)的端口
# Admin interface listen address and port ---一個(gè)和varnishadm管理工具通訊的管理接口
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1---地址為本機(jī),說(shuō)明只能在本機(jī)上使用varnishadm命令管理緩存配置,這樣比較安全
VARNISH_ADMIN_LISTEN_PORT=6082 ---監(jiān)聽(tīng)的端口
varnish除了監(jiān)聽(tīng)在6081端口之外,還監(jiān)聽(tīng)在6082端口,varnishadm管理工具可以通過(guò)這個(gè)端口連接到varnish服務(wù)器,來(lái)管理varnish緩存的配置
# Shared secret file for admin interface ---管理接口的共享秘鑰文件
VARNISH_SECRET_FILE=/etc/varnish/secret
# Backend storage specification, see Storage Types in the varnishd(5)
# man page for details.
RNISH_STORAGE="malloc,256M" ---內(nèi)存存儲(chǔ)
RANSH_STORAGE="file,/data/cache/varnish.bin,2G" ---磁盤文件存儲(chǔ),重啟后所有緩存項(xiàng)失效
# User and group for the varnishd worker processes
VARNISH_USER=varnish
VARNISH_GROUP=varnish
6、 搭建一個(gè)緩存服務(wù),并測(cè)試緩存是否命中

1、在后端搭建好httpd服務(wù)
2、在varnish的設(shè)置
vim /etc/varnish/varnish.params
VARNISH_LISTEN_PORT=80 ---將監(jiān)聽(tīng)的端口改為80,這樣在網(wǎng)站上訪問(wèn)的時(shí)候就不用輸入端口號(hào)了
systemctl start varnish
vim /etc/varnish/default.vcl
backend default {
.host = "192.168.74.133";
.port = "80";
}
sub vcl_deliver { ---表示在投遞給客戶端的時(shí)候,給客戶端的響應(yīng)報(bào)文頭部中給出是否命中
if (obj.hits>0) {
set resp.http.x-cache = "HIT via" + server.ip;
}else {
set resp.http.x-cache = "MISS from" + server.ip;
}
}
varnish_reload_vcl ---重新載入default.vcl配置文件
測(cè)試
在火狐瀏覽器上測(cè)試
http://172.18.21.107/test1.html ---第一次訪問(wèn)時(shí)響應(yīng)報(bào)文的頭部顯示沒(méi)有命中,第二次訪問(wèn)的時(shí)候顯示命中了
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 ---可以利用這個(gè)管理工具來(lái)管理varnish的各種配置
7、設(shè)置對(duì)某資源的請(qǐng)求不緩存
vim /etc/varnish/default.vcl
sub vcl_recv { ---表示如果請(qǐng)求的uri中是以下面兩個(gè)字符串開頭的就不緩存
if (req.url ~ "(?i)^/(login|admin)") { ---(?i)表示忽略大小寫
return(pass);
}
}
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
vcl.load test1 default.vcl ---將test1這個(gè)配置載入配置文件中
vcl.use test1 ---用這個(gè)配置
vcl.list ---查看配置
vcl.show test1 ---查看配置文件是否載入配置
測(cè)試
http://172.18.21.107/admin/index.html ---發(fā)現(xiàn)不會(huì)緩存
8、對(duì)于特定類型的資源,例如公開的圖片等,取消其私有標(biāo)識(shí),并強(qiáng)行設(shè)定其可以由varnish緩存
vim /etc/varnish/default.vcl
sub vcl_backend_response {
if (beresp.http.cache-control !~ "s-maxage") { ---如果后端服務(wù)器響應(yīng)給緩存服務(wù)器的響應(yīng)報(bào)文中不包含s-maxage
if (bereq.url ~ "(?i)\.(jpg|jpeg|png|gif|css|js)$") { ---如果緩存服務(wù)器請(qǐng)求后端web服務(wù)器的url中包括以這些點(diǎn)結(jié)尾的文件
unset beresp.http.set-cookie; ---不設(shè)定響應(yīng)的cookie
set beresp.ttl = 3600s; ---設(shè)定緩存時(shí)長(zhǎng)為3600s
}
}
}
vcl.load test2 default.vcl
vcl.use test2
vcl.discard test1 ---刪除某個(gè)配置
backend.list ---查看后端主機(jī)
測(cè)試
http://172.18.21.107/simplelock.jpg ---發(fā)現(xiàn)緩存
9、后端服務(wù)器可以看到真正的客戶端地址
vim /etc/varnish/default.vcl
sub vcl_recv {
if (req.restarts == 0 ) { ---如果客戶端從新發(fā)請(qǐng)求的次數(shù)為0,也就是客戶端沒(méi)有重新發(fā)起請(qǐng)求
if (req.http.X-Forwarded-For) { ---如果請(qǐng)求的報(bào)文中含有首部X-Forwarded-For
set req.http.X-Forwarded-For = req.http.X-Fordwarded-For + "," + client. ---就設(shè)定首部的值是client
ip;
}else{
set req.http.X-Fordwarded-For = client.ip; ---如果請(qǐng)求的報(bào)文中沒(méi)有首部X-Forwarded-For就直接設(shè)定客戶端地址
}
}
}
vcl.load test3 default.vcl
vcl.use test3
在后端的web服務(wù)器上的設(shè)置
vim /etc/httpd/conf/httpd.conf
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %{X-Forwarded-For}i" combined
service httpd reload
測(cè)試
curl 172.18.21.107
tail -f /var/log/httpd/access_log ---在后端日志上監(jiān)控可以看到客戶端地址
10、緩存對(duì)象的修剪
1、purge方法
vim /etc/varnish/default.vcl
if (req.method == "PURGE") { ---加到sub vcl_recv語(yǔ)句塊里
return(purge);
}
sub vcl_purge { ---此項(xiàng)可以不加,因?yàn)樵谀J(rèn)的VCL里已經(jīng)定義,cat /usr/share/doc/varnish-4.0.4/builtin.vcl可以看到
return (synth(200,"Purged"));
} ---此項(xiàng)的作用的是上面定義的返回purge后進(jìn)行的操作,就返回一個(gè)合成的響應(yīng)碼200,"Purged"
vcl.load test5 default.vcl ---加載配置到配置文件中
vcl.use test5 ---使用這個(gè)配置
在客戶端curl -X PURGE 172.18.21.107/simplelock.jpg ---X選項(xiàng)用于指明客戶端請(qǐng)求的方法是purge
[root@centos6 network-scripts]#curl -X PURGE 172.18.21.107/simplelock.jpg -I
HTTP/1.1 200 Purged ---可以看到這個(gè)合成的響應(yīng)碼
Date: Thu, 02 Nov 2017 11:21:34 GMT
Server: Varnish
X-Varnish: 163953
Content-Type: text/html; charset=utf-8
Retry-After: 5
Content-Length: 241
Connection: keep-alive
測(cè)試
http://172.18.21.107/simplelock.jpg ---purge之后就沒(méi)有緩存了
添加此類請(qǐng)求的訪問(wèn)控制法則
也就是acl控制列表,運(yùn)行哪些客戶端purge
示例
vim /etc/varnish/default.vcl
vcl 4.0;
acl purges { ---在vcl 4.0下面定義一個(gè)acl
"127.0.0.0"/8;
"172.18.0.0"/16;
}
if (req.method == "PURGE") { ---加到sub vcl_recv語(yǔ)句塊里
if (!client.ip ~ purges) { ---如果客戶端的地址不滿足上面acl中定義的地址
return(synth(405,"purging not allowed for " + client.ip)); ---就返回一個(gè)合成的狀態(tài)碼
}
return(purge);
}
vcl.load test7 default.vcl ---這些命令都是在另外一個(gè)窗口通過(guò)varnishadm管理工具實(shí)現(xiàn)的
use test7
測(cè)試curl -X PURGE 172.18.21.107/readblock.jpg ----只能本機(jī)和這個(gè)網(wǎng)段的進(jìn)行修剪
2、Banning
示例
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
ban req.url ~ (?i).(jpg|jpeg)$ ---用命令行的方式ban掉一類緩存
總結(jié):用purge修剪單個(gè)的緩存,用ban修剪一類緩存
11 、如何設(shè)定使用多個(gè)后端主機(jī)
vim /etc/varnish/default.vcl
backend default {
.host = "192.168.74.133";
.port = "80";
}
backend appsrv {
.host = "192.168.74.129";
.port = "80";
}
sub vcl_recv {
if (req.url ~ "(?i)\.php$") {
set req.backend_hint = appsrv;
}else{
set req.backend_hint = default;
}
}
vcl.load test8 default.vcl
vcl.use test8
backend.list ---可以看到有兩個(gè)后端主機(jī)
200
Backend name Refs Admin Probe
default(192.168.74.133,,80) 8 probe Healthy (no probe)
appsrv(192.168.74.129,,80) 1 probe Healthy (no probe)
測(cè)試
http://172.18.21.107/index.php
12、實(shí)現(xiàn)負(fù)載均衡
vim /etc/varnish/default.vcl
vcl 4.0;
import directors; ---要實(shí)現(xiàn)負(fù)載均衡要先導(dǎo)入這個(gè)模塊
backend srv1 {
.host = "192.168.74.133";
.port = "80";
}
backend srv2 {
.host = "192.168.74.129";
.port = "80";
}
sub vcl_init { ---初始化后端服務(wù)器組
new srvs = directors.round_robin(); --定義一個(gè)服務(wù)器組為srvs,并設(shè)置調(diào)度算法為輪詢,不支持權(quán)重,varnish有兩種調(diào)度算法輪詢和隨機(jī)random
srvs.add_backend(srv1);
srvs.add_backend(srv2); ---添加兩個(gè)后端服務(wù)器到這個(gè)組中
}
sub vcl_recv {
set req.backend_hint = srvs.backend(); ---請(qǐng)求的后端主機(jī)是定義的服務(wù)器組
if (req.url ~ "(?i)^/(login|admin)") { ---為了看出輪詢效果,定義一個(gè)不緩存的
return(pass);
}
}
vcl.load test9 default.vcl
vcl.use test9
測(cè)試
http://172.18.21.107/admin/index.html ---可以發(fā)現(xiàn)輪詢
13、基于cookie的session stick
sub vcl_init {
new h = directors.hash(); ---定義一個(gè)服務(wù)器組為h,調(diào)度算法為哈希
h.add_backend(srv1, 1);
h.add_backend(srv2, ,2); ---添加兩個(gè)服務(wù)器到組中,后面的1和2為權(quán)重,輪詢算法不支持權(quán)重
}
sub vcl_recv {
set req.backend_hint = h.backend(req.http.cookie); ----req.http.cookie表示請(qǐng)求報(bào)文中含有cookie的就調(diào)度到指定的后端服務(wù)器
}
14、定義健康狀態(tài)檢測(cè)
vim /etc/varnish/default.vcl
probe check { --定義一個(gè)檢查方法為check
.url = "/index.html"; ---檢查的uri
.window = 5; ---定義一個(gè)窗口,基于最近的多少次檢查來(lái)判斷其健康狀態(tài);
.threshold = 4; ---定義一個(gè)門檻,也就是上面定義的檢查次數(shù)中有4次成功的才認(rèn)為后端服務(wù)器是健康的
.interval = 2s; ---監(jiān)控間隔
.timeout = 1s; ---超時(shí)時(shí)長(zhǎng)
}
backend srv1 {
.host = "192.168.74.133";
.port = "80";
.probe = check;
}
backend srv2 {
.host = "192.168.74.129";
.port = "80";
.probe = check; ---在兩個(gè)后端服務(wù)器組中調(diào)用這個(gè)檢測(cè)方法
}
vcl.load test10 default.vcl
vcl.use test10
backend.list ---這是沒(méi)有設(shè)定健康狀態(tài)檢查之前的狀態(tài)
200
Backend name Refs Admin Probe
default(192.168.74.133,,80) 2 probe Healthy (no probe)
srv1(192.168.74.133,,80) 1 probe Healthy (no probe)
srv2(192.168.74.129,,80) 1 probe Healthy (no probe)
backend.list ---設(shè)定之后我們發(fā)現(xiàn)Healthy 5/5
200
Backend name Refs Admin Probe
default(192.168.74.133,,80) 2 probe Healthy (no probe)
srv1(192.168.74.133,,80) 2 probe Healthy 5/5
srv2(192.168.74.129,,80) 2 probe Healthy 5/5
手動(dòng)設(shè)定BE主機(jī)的狀態(tài):
sick:管理down;
healthy:管理up;
auto:probe auto;
示例
backend.set_health srv1 sick ---設(shè)置為down狀態(tài),可以用于灰度發(fā)布時(shí)使用,一批一批上線
200
backend.list
200
Backend name Refs Admin Probe
default(192.168.74.133,,80) 2 probe Healthy (no probe)
srv1(192.168.74.133,,80) 2 sick Healthy 5/5
srv2(192.168.74.129,,80) 2 probe Healthy 5/5
backend.set_health srv1 healthy ---設(shè)置為健康狀態(tài),即使這臺(tái)主機(jī)真的壞了,也會(huì)往這臺(tái)主機(jī)調(diào)度,最好不要這樣設(shè)置
200
backend.list
200
Backend name Refs Admin Probe
default(192.168.74.133,,80) 2 probe Healthy (no probe)
srv1(192.168.74.133,,80) 2 healthy Healthy 5/5
srv2(192.168.74.129,,80) 2 probe Healthy 5/5
backend.set_health srv1 auto ---設(shè)定為自動(dòng)狀態(tài),也就是根據(jù)健康狀態(tài)檢測(cè)情況決定
200
backend.list
200
Backend name Refs Admin Probe
default(192.168.74.133,,80) 2 probe Healthy (no probe)
srv1(192.168.74.133,,80) 2 probe Healthy 5/5
srv2(192.168.74.129,,80) 2 probe Healthy 5/5
設(shè)置后端主機(jī)的健康檢測(cè)的其他方法:
.connect_timeout = 0.5s; 指的是tcp連接建立的超時(shí)時(shí)長(zhǎng)
.first_byte_timeout = 20s; 指的是tcp連接建立之后開始傳輸數(shù)據(jù)的第一個(gè)字節(jié)的超時(shí)時(shí)長(zhǎng)
.between_bytes_timeout = 5s;傳輸一個(gè)字節(jié)之后再傳輸一個(gè)字節(jié),兩個(gè)字節(jié)之間的傳輸超時(shí)時(shí)間超過(guò)5秒定義為這臺(tái)主機(jī)時(shí)不健康的
.max_connections = 50; 當(dāng)前服務(wù)器的最大并發(fā)連接數(shù)等于50的時(shí)候定義為不健康的,這個(gè)生成中可能會(huì)用到
15、線程相關(guān)的參數(shù)設(shè)置
使用線程池機(jī)制管理線程;在線程池內(nèi)部,其每一個(gè)請(qǐng)求由一個(gè)線程來(lái)處理; 其worker線程的最大數(shù)決定了varnish的并發(fā)響應(yīng)能力;
thread_pools:線程池的數(shù)量. 最好小于或等于CPU核心數(shù)量;
thread_pool_max:每線程池的最大線程數(shù);
thread_pool_min:每個(gè)線程池的最小線程數(shù),額外意義為“最大空閑線程數(shù)”;
最大并發(fā)連接數(shù) = thread_pools * thread_pool_max
thread_pool_timeout:線程空閑時(shí)間,超過(guò)閾值則摧毀線程
thread_pool_add_delay:創(chuàng)建一個(gè)新線程的延遲時(shí)間,默認(rèn)值為0s
thread_pool_destroy_delay:摧毀一個(gè)線程的延遲時(shí)間,默認(rèn)值為2s;
如何修改varnish處于運(yùn)行狀態(tài)時(shí)的這些參數(shù)
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
param.show -l ---可以查看所有參數(shù)
param.set thread_pool 4 ---設(shè)置線程池?cái)?shù)量為4個(gè)
param.show thread_pools ---查看一下
param.set thread_pool_max 3000 ---設(shè)置每個(gè)池子中的最大線程
param.set thread_pool_max 3000
此時(shí)最大并發(fā)為12000
要想永久修改執(zhí)行如下設(shè)置
vim /etc/varnish/varnish.params
DAEMON_OPTS="-p thread_pool_min=100 -p thread_pool_max=3000 -p thread_pool_timeout=300 -p thread_pools=4 -r thread_pools,thread_pool_max,thread_pool_min"---用-r選項(xiàng)指明這些參數(shù)是只讀的,不能進(jìn)行修改
systemctl restart varnish
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
param.show thread.pools
param.set thread_pools 2 ---發(fā)現(xiàn)不能設(shè)置,已經(jīng)被寫保護(hù)了
107
parameter "thread_pools" is protected.
16、varnish日志
varnishlog ---可以顯示新生成的日志
varnishtop ---動(dòng)態(tài)的顯示日志信息
varnishncsa --以combine的格式顯示日志信息,這種格式是http日志的格式
varnishstat ---顯示統(tǒng)計(jì)日志
varnishstat -l --顯示所有的字段名稱列表
[root@centos7 varnish]#varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss ---可以顯示命中的次數(shù)和未命中的次數(shù),從而計(jì)算命中率,-f表示字段field,-1是只顯示一次,不然會(huì)像top命令一樣
MAIN.cache_hit 6 0.01 Cache hits
MAIN.cache_miss 3 0.00 Cache misses
varnishstat -1 -f MAIN ---可以顯示某個(gè)字段
[root@centos7 varnish]#varnishtop -1 ---一次性的顯示過(guò)去的參數(shù)
[root@centos7 varnish]#varnishtop -i RespHeader ---動(dòng)態(tài)的顯示某個(gè)指定的標(biāo)簽,-I支持正則表達(dá)式
list length 16 centos7.magedu.com
1.17 RespHeader Accept-Ranges: bytes
1.12 RespHeader Age: 0
1.12 RespHeader Via: 1.1 varnish-v4
1.12 RespHeader Connection: keep-alive
1.12 RespHeader x-cache: MISS from172.18.21.107
0.67 RespHeader X-Varnish: 9
[root@centos7 varnish]#varnishtop -x RespHeader, RespStatus ---表示除了RespHeader、RespStatus 的內(nèi)容都顯示出來(lái),-X支持正則表達(dá)式
[root@centos7 varnish]#varnishtop -I Resp.* ---正則表達(dá)式匹配的是后面的內(nèi)容,小寫的時(shí)候匹配的是前面的標(biāo)簽
list length 3 centos7.magedu.com
0.56 Timestamp Resp: 1509634477.875729 0.001115 0.000280
0.50 Timestamp Resp: 1509634477.516917 0.002058 0.000363
0.50 Timestamp Resp: 1509634477.706995 0.001768 0.000230
如何永久的記錄日志
[root@centos7 varnish]#systemctl start varnishncsa.service
[root@centos7 varnish]#cd /var/log/varnish/
[root@centos7 varnish]#ls
varnishncsa.log
[root@centos7 varnish]#tail varnishncsa.log
[root@centos7 varnish]#tail varnishncsa.log -f
172.18.254.200 - - [02/Nov/2017:23:02:09 +0800] "GET http://172.18.21.107/ HTTP/1.1" 200 32 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"
要根據(jù)緩存服務(wù)器的負(fù)載情況決定是否啟動(dòng)日志功能