参考:https://www.cnblogs.com/cutemsyu/p/6051876.html
1、varnish程序环境
软件包:yum install varnish
/etc/varnish/varnish.params: 配置varnish服务进程的工作特性,例如监听的地址和端口,缓存机制;
/etc/varnish/default.vcl:配置各Child/Cache线程的缓存;
主程序:/usr/sbin/varnishd
/usr/share/doc/varnish-4.0.4/builtin.vcl ---系统内置的一些VCL
Systemd Unit File:/usr/lib/systemd/system/varnish.service
程序架构:
Manager进程
Cacher进程,包含多种类型的线程:
accept, worker, expiry, ...
也就是一个主的Manager进程和一个子Cacher进程,Cacher进程分成很多个线程来处理用户的请求
shared memory log:
统计数据:计数器;
日志区域:日志记录;
varnishlog, varnishncsa, varnishstat...
配置接口:VCL
Varnish Configuration Language,
vcl complier --> c complier --> shared object
2、varnish的缓存存储机制( Storage Types)
malloc[,size]内存存储,[,size]用于定义空间大小;重启后所有缓存项失效;
file[,path[,size[,granularity]]]磁盘文件存储,黑盒;重启后所有缓存项失效;
persistent,path,size文件存储,黑盒;重启后所有缓存项有效;实验阶段,目前还没有使用;
3、VCL
Varnish Configuration Language
VCL有多个状态引擎,状态之间存在相关性,但状态引擎彼此间互相隔离;每个状态引擎可使用return(x)指明关联至哪个下一级引擎;每个状态引擎对应于vcl文件中的一个配置段,即为subroutine
4、变量类型
内建变量:
req.*:request,表示由客户端发来的请求报文相关;
req.http.*
req.http.User-Agent, req.http.Referer, ...
bereq.*:由varnish发往BE主机的httpd请求相关;
bereq.http.*
beresp.*:由BE主机响应给varnish的响应报文相关;
beresp.http.*
resp.*:由varnish响应给client相关;
obj.*:存储在缓存空间中的缓存对象的属性;只读;
常用变量:
bereq.*, req.*:
bereq.http.HEADERS
bereq.request:请求方法;
bereq.url:请求的url;
bereq.proto:请求的协议版本;
bereq.backend:指明要调用的后端主机;
req.http.Cookie:客户端的请求报文中Cookie首部的值;
req.http.User-Agent ~ "chrome"
beresp.*, resp.*:
beresp.http.HEADERS
beresp.status:响应的状态码;
reresp.proto:协议版本;
beresp.backend.name:BE主机的主机名;
beresp.ttl:BE主机响应的内容的余下的可缓存时长;
obj.*
obj.hits:此对象从缓存中命中的次数;
obj.ttl:对象的ttl值,也就是有效期
server.*
server.ip:varnish主机的IP;
server.hostname:varnish主机的Hostname;
client.*
client.ip:发请求至varnish主机的客户端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 ---监听的地址,默认是本机的所有地址
VARNISH_LISTEN_PORT=6081 ---监听的端口
# Admin interface listen address and port ---一个和varnishadm管理工具通讯的管理接口
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1---地址为本机,说明只能在本机上使用varnishadm命令管理缓存配置,这样比较安全
VARNISH_ADMIN_LISTEN_PORT=6082 ---监听的端口
varnish除了监听在6081端口之外,还监听在6082端口,varnishadm管理工具可以通过这个端口连接到varnish服务器,来管理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" ---内存存储
RANSH_STORAGE="file,/data/cache/varnish.bin,2G" ---磁盘文件存储,重启后所有缓存项失效
# User and group for the varnishd worker processes
VARNISH_USER=varnish
VARNISH_GROUP=varnish
6、 搭建一个缓存服务,并测试缓存是否命中
1、在后端搭建好httpd服务
2、在varnish的设置
vim /etc/varnish/varnish.params
VARNISH_LISTEN_PORT=80 ---将监听的端口改为80,这样在网站上访问的时候就不用输入端口号了
systemctl start varnish
vim /etc/varnish/default.vcl
backend default {
.host = "192.168.74.133";
.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;
}
}
varnish_reload_vcl ---重新载入default.vcl配置文件
测试
在火狐浏览器上测试
http://172.18.21.107/test1.html ---第一次访问时响应报文的头部显示没有命中,第二次访问的时候显示命中了
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 ---可以利用这个管理工具来管理varnish的各种配置
7、设置对某资源的请求不缓存
vim /etc/varnish/default.vcl
sub vcl_recv { ---表示如果请求的uri中是以下面两个字符串开头的就不缓存
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这个配置载入配置文件中
vcl.use test1 ---用这个配置
vcl.list ---查看配置
vcl.show test1 ---查看配置文件是否载入配置
测试
http://172.18.21.107/admin/index.html ---发现不会缓存
8、对于特定类型的资源,例如公开的图片等,取消其私有标识,并强行设定其可以由varnish缓存
vim /etc/varnish/default.vcl
sub vcl_backend_response {
if (beresp.http.cache-control !~ "s-maxage") { ---如果后端服务器响应给缓存服务器的响应报文中不包含s-maxage
if (bereq.url ~ "(?i)\.(jpg|jpeg|png|gif|css|js)$") { ---如果缓存服务器请求后端web服务器的url中包括以这些点结尾的文件
unset beresp.http.set-cookie; ---不设定响应的cookie
set beresp.ttl = 3600s; ---设定缓存时长为3600s
}
}
}
vcl.load test2 default.vcl
vcl.use test2
vcl.discard test1 ---删除某个配置
backend.list ---查看后端主机
测试
http://172.18.21.107/simplelock.jpg ---发现缓存
9、后端服务器可以看到真正的客户端地址
vim /etc/varnish/default.vcl
sub vcl_recv {
if (req.restarts == 0 ) { ---如果客户端从新发请求的次数为0,也就是客户端没有重新发起请求
if (req.http.X-Forwarded-For) { ---如果请求的报文中含有首部X-Forwarded-For
set req.http.X-Forwarded-For = req.http.X-Fordwarded-For + "," + client. ---就设定首部的值是client
ip;
}else{
set req.http.X-Fordwarded-For = client.ip; ---如果请求的报文中没有首部X-Forwarded-For就直接设定客户端地址
}
}
}
vcl.load test3 default.vcl
vcl.use test3
在后端的web服务器上的设置
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
测试
curl 172.18.21.107
tail -f /var/log/httpd/access_log ---在后端日志上监控可以看到客户端地址
10、缓存对象的修剪
1、purge方法
vim /etc/varnish/default.vcl
if (req.method == "PURGE") { ---加到sub vcl_recv语句块里
return(purge);
}
sub vcl_purge { ---此项可以不加,因为在默认的VCL里已经定义,cat /usr/share/doc/varnish-4.0.4/builtin.vcl可以看到
return (synth(200,"Purged"));
} ---此项的作用的是上面定义的返回purge后进行的操作,就返回一个合成的响应码200,"Purged"
vcl.load test5 default.vcl ---加载配置到配置文件中
vcl.use test5 ---使用这个配置
在客户端curl -X PURGE 172.18.21.107/simplelock.jpg ---X选项用于指明客户端请求的方法是purge
[root@centos6 network-scripts]#curl -X PURGE 172.18.21.107/simplelock.jpg -I
HTTP/1.1 200 Purged ---可以看到这个合成的响应码
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
测试
http://172.18.21.107/simplelock.jpg ---purge之后就没有缓存了
添加此类请求的访问控制法则
也就是acl控制列表,运行哪些客户端purge
示例
vim /etc/varnish/default.vcl
vcl 4.0;
acl purges { ---在vcl 4.0下面定义一个acl
"127.0.0.0"/8;
"172.18.0.0"/16;
}
if (req.method == "PURGE") { ---加到sub vcl_recv语句块里
if (!client.ip ~ purges) { ---如果客户端的地址不满足上面acl中定义的地址
return(synth(405,"purging not allowed for " + client.ip)); ---就返回一个合成的状态码
}
return(purge);
}
vcl.load test7 default.vcl ---这些命令都是在另外一个窗口通过varnishadm管理工具实现的
use test7
测试curl -X PURGE 172.18.21.107/readblock.jpg ----只能本机和这个网段的进行修剪
2、Banning
示例
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
ban req.url ~ (?i).(jpg|jpeg)$ ---用命令行的方式ban掉一类缓存
总结:用purge修剪单个的缓存,用ban修剪一类缓存
11 、如何设定使用多个后端主机
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 ---可以看到有两个后端主机
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)
测试
http://172.18.21.107/index.php
12、实现负载均衡
vim /etc/varnish/default.vcl
vcl 4.0;
import directors; ---要实现负载均衡要先导入这个模块
backend srv1 {
.host = "192.168.74.133";
.port = "80";
}
backend srv2 {
.host = "192.168.74.129";
.port = "80";
}
sub vcl_init { ---初始化后端服务器组
new srvs = directors.round_robin(); --定义一个服务器组为srvs,并设置调度算法为轮询,不支持权重,varnish有两种调度算法轮询和随机random
srvs.add_backend(srv1);
srvs.add_backend(srv2); ---添加两个后端服务器到这个组中
}
sub vcl_recv {
set req.backend_hint = srvs.backend(); ---请求的后端主机是定义的服务器组
if (req.url ~ "(?i)^/(login|admin)") { ---为了看出轮询效果,定义一个不缓存的
return(pass);
}
}
vcl.load test9 default.vcl
vcl.use test9
测试
http://172.18.21.107/admin/index.html ---可以发现轮询
13、基于cookie的session stick
sub vcl_init {
new h = directors.hash(); ---定义一个服务器组为h,调度算法为哈希
h.add_backend(srv1, 1);
h.add_backend(srv2, ,2); ---添加两个服务器到组中,后面的1和2为权重,轮询算法不支持权重
}
sub vcl_recv {
set req.backend_hint = h.backend(req.http.cookie); ----req.http.cookie表示请求报文中含有cookie的就调度到指定的后端服务器
}
14、定义健康状态检测
vim /etc/varnish/default.vcl
probe check { --定义一个检查方法为check
.url = "/index.html"; ---检查的uri
.window = 5; ---定义一个窗口,基于最近的多少次检查来判断其健康状态;
.threshold = 4; ---定义一个门槛,也就是上面定义的检查次数中有4次成功的才认为后端服务器是健康的
.interval = 2s; ---监控间隔
.timeout = 1s; ---超时时长
}
backend srv1 {
.host = "192.168.74.133";
.port = "80";
.probe = check;
}
backend srv2 {
.host = "192.168.74.129";
.port = "80";
.probe = check; ---在两个后端服务器组中调用这个检测方法
}
vcl.load test10 default.vcl
vcl.use test10
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) 1 probe Healthy (no probe)
srv2(192.168.74.129,,80) 1 probe Healthy (no probe)
backend.list ---设定之后我们发现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
手动设定BE主机的状态:
sick:管理down;
healthy:管理up;
auto:probe auto;
示例
backend.set_health srv1 sick ---设置为down状态,可以用于灰度发布时使用,一批一批上线
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 ---设置为健康状态,即使这台主机真的坏了,也会往这台主机调度,最好不要这样设置
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 ---设定为自动状态,也就是根据健康状态检测情况决定
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
设置后端主机的健康检测的其他方法:
.connect_timeout = 0.5s; 指的是tcp连接建立的超时时长
.first_byte_timeout = 20s; 指的是tcp连接建立之后开始传输数据的第一个字节的超时时长
.between_bytes_timeout = 5s;传输一个字节之后再传输一个字节,两个字节之间的传输超时时间超过5秒定义为这台主机时不健康的
.max_connections = 50; 当前服务器的最大并发连接数等于50的时候定义为不健康的,这个生成中可能会用到
15、线程相关的参数设置
使用线程池机制管理线程;在线程池内部,其每一个请求由一个线程来处理; 其worker线程的最大数决定了varnish的并发响应能力;
thread_pools:线程池的数量. 最好小于或等于CPU核心数量;
thread_pool_max:每线程池的最大线程数;
thread_pool_min:每个线程池的最小线程数,额外意义为“最大空闲线程数”;
最大并发连接数 = thread_pools * thread_pool_max
thread_pool_timeout:线程空闲时间,超过阈值则摧毁线程
thread_pool_add_delay:创建一个新线程的延迟时间,默认值为0s
thread_pool_destroy_delay:摧毁一个线程的延迟时间,默认值为2s;
如何修改varnish处于运行状态时的这些参数
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
param.show -l ---可以查看所有参数
param.set thread_pool 4 ---设置线程池数量为4个
param.show thread_pools ---查看一下
param.set thread_pool_max 3000 ---设置每个池子中的最大线程
param.set thread_pool_max 3000
此时最大并发为12000
要想永久修改执行如下设置
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选项指明这些参数是只读的,不能进行修改
systemctl restart varnish
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
param.show thread.pools
param.set thread_pools 2 ---发现不能设置,已经被写保护了
107
parameter "thread_pools" is protected.
16、varnish日志
varnishlog ---可以显示新生成的日志
varnishtop ---动态的显示日志信息
varnishncsa --以combine的格式显示日志信息,这种格式是http日志的格式
varnishstat ---显示统计日志
varnishstat -l --显示所有的字段名称列表
[root@centos7 varnish]#varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss ---可以显示命中的次数和未命中的次数,从而计算命中率,-f表示字段field,-1是只显示一次,不然会像top命令一样
MAIN.cache_hit 6 0.01 Cache hits
MAIN.cache_miss 3 0.00 Cache misses
varnishstat -1 -f MAIN ---可以显示某个字段
[root@centos7 varnish]#varnishtop -1 ---一次性的显示过去的参数
[root@centos7 varnish]#varnishtop -i RespHeader ---动态的显示某个指定的标签,-I支持正则表达式
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 的内容都显示出来,-X支持正则表达式
[root@centos7 varnish]#varnishtop -I Resp.* ---正则表达式匹配的是后面的内容,小写的时候匹配的是前面的标签
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"
要根据缓存服务器的负载情况决定是否启动日志功能