varnish:
vcl语言进行管理
模块:
vcl_recv:用来接收客户端的请求
vcl_hash:如果请求是静态数据 则进入到varnish本身的缓存中
vcl_pass:当请求为动态数据 则去后端获取
注:varnish不缓存动态数据
vcl_pipe:当请求为非正常请求时,则直接拒绝
vcl_hit:在varnish缓存中找到对应的数据(命中)
vcl_miss:在varnish缓存中没有找到对应的数据(未命中)
vcl_fetch:将请求交给后端
vcl_deliver:将请求响应给客户端
因为要是使用判断的条件。所以会使用到一些固定的预设变量
预设变量:
req:客户端发送给varnish请求使用的变量(rep request请求)
req.url:客户端对varnish请求的url(路径)
req.http:客户端对varnish的请求头部信息
bereq:varnish给后端服务器发送的请求(bereq:backend request)
bereq.url:varnish对后端服务器的请求的url
bereq.http:varnish对后端服务器的请求的头部信息
resp:varnish对客户端的响应(resp:response响应)
resp.http:varnish响应客户端的头部信息
resp.status:返回状态码
beresp:服务器节点给varnish的响应(beresp:backend response)
beresp.uncacheable:响应数据是否不缓存
beresp.ttl:响应数据的缓存时间
obj:缓存在varnish中的数据
obj.ttl:varnish本地缓存的时间
obj.hits:varnish缓存的命中次数
hash_data():对客户端请求的内容进行hash计算
hash_data(req.url) 计算请求的路径
hash_data(req.url.host) 计算请求的域名
hash_data(server.ip) 计算请求的ip
vcl语法
运算符:
= 赋值运算符
== 比较运算符
~ 正则匹配
! 非
!= 不等于
!~ 不匹配
&& | | 与非
数据类型:
字符串 “abc”
布尔值 true false
时间 s秒 m分钟 d天
条件判断:
if else
单主机实例:
环境:
client | 192.168.10.2 |
---|---|
varnish | 192.168.10.3 |
web | 192.168.10.10 |
操作:
web:
安装httpd服务并修改页面内容
varnish:
[root@localhost varnish-4.1.11]# vim /usr/local/varnish/default.vcl
13 vcl 4.0;
16 probe health {
17 .url = "/"; #从/开始
18 .timeout = 3s; #超时时间
19 .interval = 1s; #间隔时间
20 .window = 5; #能同时维持5个窗口运行
21 .threshold = 3; #至少3个成功
22 }
23 backend web { #后端主机
24 .host = "192.168.10.10";
25 .port = "80";
26 .probe = health; #使用健康检查
27 }
28 sub vcl_recv { #用来接收客户端请求的模块
29 set req.backend_hint = web; #当请求命中后端web才接收请求
30 if(req.http.X-Forwarded-For){ #如果在客户端的请求头当中看到这个字段 则就证明经过了代理
31 set req.http.X-Forwarded-For=req.http.X-Forwarded-For + "," + client.ip;
32 } #则需要重新建立请求头 把这个字段后面加上代理的ip和客户端的ip 为了服务端能够获取到client的ip
33 else{
34 set req.http.X-Forwarded-For=req.http.X-Forwarded-For; #如果没有 不改变
35 }
36 if(req.method != "GET" &&
37 req.method != "POST" &&
38 req.method != "DELETE" &&
39 req.method != "HEAD" &&
40 req.method != "PUT" #如果请求是不正常的请求方式
41 ){
42 return(pipe); 则进入到pipe模块中
43 }
44 if(req.url ~ "\.(html|htm|png|jpg$)"){ #如果客户端的请求url中是以.html结尾 则是静态数据
45 return(hash); #则进入到hash模块中
46 }
47 if(req.url ~"\.php$"){ #如果请求是以.php结尾 则是动态数据
48 return(pass); #则进入到pass模块中
49 }
50 return(hash); #其余全部进入到hash模块中
51 }
52 sub vcl_hash{ #静态数据模块
53 hash_data(req.url); #对客户端的请求路径进行hash
54 if(req.http.host){ #如果请求头当中包含域名
55 hash_data(req.http.host); #则hash域名
56 }
57 else{
58 hash_data(server.ip); #其余haship
59 }
60 }
61 sub vcl_pass{ #动态请求数据块
62 return(fetch); #直接将请求交给后端
63 }
64 sub vcl_pipe{ #不正常请求的模块
65 return(pipe); #直接结束
66 }
67 sub vcl_miss{ #缓存未命中
68 return(fetch); #直接将请求交给后端
69 }
70 sub vcl_hit{ #缓存命中
71 return(deliver); #直接响应
72 }
73 sub vcl_backend_response{ #后端数据模块
74 if(bereq.url ~ "\.php$"){ #如果varnish对后端请求的是动态数据 则不缓存
75 set beresp.uncacheable = true;
76 }
77 if(bereq.url ~ "\.html$"){ #如果varnish对后端请求的是静态数据 则缓存300s
78 set beresp.ttl = 300s;
79 }
80 }
81 sub vcl_deliver{ #结束模块
82 if(obj.hits > 0){ #如果命中次数大于0
83 set resp.http.X-cache = "hit~~~~~"; #则在varnish对客户端的响应头部建立hit~~
84 }
85 else{
86 set resp.http.X-cahe = "miss~~~~~"; #其余 则在varnish对客户端的响应头部建立miss~~
87 }
88 }
[root@localhost varnish-4.1.11]# varnishd -C -f /usr/local/varnish/default.vcl
#启动
[root@localhost varnish-4.1.11]# varnishd -f /usr/local/varnish/default.vcl #执行这条命令时如果它提示端口被占用则可通过killall -9 加占用端口的服务名 进行杀死即可
[root@localhost varnish-4.1.11]# netstat -anput | grep varnishd
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 73810/varnishd
tcp 0 0 127.0.0.1:44729 0.0.0.0:* LISTEN 73810/varnishd
tcp6 0 0 :::80 :::* LISTEN 73810/varnishd
tcp6 0 0 ::1:42815 :::* LISTEN 73810/varnishd
客户端验证:
[root@localhost ~]# curl -I 192.168.10.3
HTTP/1.1 200 OK
Date: Mon, 22 Jun 2020 03:07:31 GMT
Server: Apache/2.4.6 (CentOS)
Last-Modified: Mon, 22 Jun 2020 00:37:46 GMT
ETag: "7-5a8a17399266f"
Content-Length: 7
Content-Type: text/html; charset=UTF-8
X-Varnish: 2
Age: 0
Via: 1.1 varnish-v4
X-cache: miss~~~~~
Accept-Ranges: bytes
Connection: keep-alive
[root@localhost ~]# curl -I 192.168.10.3
HTTP/1.1 200 OK
Date: Mon, 22 Jun 2020 03:07:31 GMT
Server: Apache/2.4.6 (CentOS)
Last-Modified: Mon, 22 Jun 2020 00:37:46 GMT
ETag: "7-5a8a17399266f"
Content-Length: 7
Content-Type: text/html; charset=UTF-8
X-Varnish: 5 3
Age: 14
Via: 1.1 varnish-v4
X-cache: hit~~~~~
Accept-Ranges: bytes
Connection: keep-alive
多主机实例
环境:
client | 192.168.10.2 |
---|---|
varnish | 192.168.10.3 |
web1 | 192.168.10.10 httpd 111111 |
web2 | 192.168.10.20 httpd 22222 |
注:实验环境直接关闭防火墙即可
操作:
web:
分别安装httpd服务并修改页面内容
varnish:
[root@localhost ~]# vim /usr/local/varnish/default.vcl
16 probe health {
17 .url = "/";
18 .timeout = 3s;
19 .interval = 1s;
20 .window = 5;
21 .threshold = 3;
22 }
23 backend web1 {
24 .host = "192.168.10.10";
25 .port = "80";
26 .probe = health;
27 .max_connections = 100; #最大连接数
28 }
29
30 backend web2 {
31 .host = "192.168.10.20";
32 .port = "80";
33 .probe = health;
34 .max_connections = 100;
35 }
36 acl allow { #访问控制列表 allow是名称
37 "127.0.0.1"; #本地回环
38 "localhost"; #域名主机
39 "192.168.10.3"; #ip
40 }
41 import directors; #导入集群模块
42 sub vcl_init{ #导入轮询模块
43 new back = directors.round_robin(); #使用动态轮询的方式
44 back.add_backend(web1); #使用上面的主机
45 back.add_backend(web2);
46 }
47 sub vcl_recv {
48 set req.backend_hint = back.backend(); #自动屏蔽掉后端不正常的主机
49 if(req.method == "PURGE"){ #当请求方式为purge
50 if(client.ip !~ allow){ #如果请求的ip不匹配allow列表
51 return(synth(405,"not allowed")); #将返回状态码405
52 }
53 else{
54 return(purge); #其余则进入到清除缓存的模块
55 }
56 }
57 if(req.http.host ~ "^qqq"){ #如果客户端的请求域名是以qqq开头
58 set req.backend_hint = web1; #则将请求交给web1
59 }
60 if(req.http.host ~ "^www"){ #如果客户端的请求域名是以www开头
61 set req.backend_hint = web2; #则将请求交给web2
62 }
63 if(req.url ~ "\.(php|asp|aspx|jsp|do)($|\?)"){ #如果请求的是动态数据
64 return(pass); #则把请求交给pass模块
65 }
66 if(req.url ~"\.(css|html|htm|jpeg|png|mp4)$"){ #如果请求是静态数据
67 return(hash); #则把请求交给hash模块
68 }
69 if(req.method != "GET" &&
70 req.method != "POST" &&
71 req.method != "DELETE" &&
72 req.method != "PUT" &&
73 req.method != "HEAD"
74 ){
75 return(pipe); #如果请求方式不是正常的请求方式 则拒接连接
76 }
77 if(req.method != "GET" && req.method != "HEAD"){ #当请求方式不是get或者head时
78 return(pass); #则进入到动态数据模块 因为其余的请求方式和数据库都是有联系的
79 }
80 if(req.http.Authorzation){ 如果请求是认证
81 return(pass); #则进入到pass模块中
82 }
83 if(req.http.Accept-Encoding){ #如果在客户端的请求头中有这个字段
84 if(req.url ~ "\.(png|gif|bz2|zip)$"){ #客户端如果请求的是压缩文件
85 unset req.http.Accept-Encoding; #则不用建立这个请求头 防止web再次压缩
86 }
87 elseif(req.http.Accept-Encoding ~ "gzip"){ #如果请求头中匹配到gzip
88 set req.http.Accept-Encoding = "gzip"; #则建立这个请求头
89 }
90 elseif(req.http.Accept-Encoding ~ "deflate"){
91 set req.http.Accept-Encoding = "deflate";
92 }
93 else{
94 unset req.http.Accept-Encoding; #其余则不用建立
95 }
96 }
97 }
98 sub vcl_pipe{ #拒绝连接模块 直接结束
99 return(pipe);
100 }
101 sub vcl_pass{ #动态数据模块 进入到后端
102 return(fetch);
103 }
104 sub vcl_hash{ #静态数据模块
105 hash_data(req.url); #hash请求的路径
106 if(req.http.host){
107 hash_data(req.http.host); #hash域名
108 }
109 else{
110 hash_data(server.ip); #其余hash ip
111 if(req.http.Accept-Encoding ~ "deflate"){ #当请求头部中有这个字段 则hash deflate
112 hash_data("deflate");
113 }
114 }
115 if(req.http.Accept-Encoding ~ "gzip"){ #如果客户端请求头部中包含编码类型 web是以压缩文件进行传输的 是由客户端本身来进行解压 那么为了varnish能够把压缩的文件进行缓存 所以填写了这个模块
116 hash_data("gzip");
117 } #注 accept-Encoding字段
118 }
119
120 sub vcl_backend_response{ #后端能够找到对应的数据
121 if(bereq.url ~ "\.(php|asp|do)($|\?)"){ #当是动态数据时
122 set beresp.uncacheable = true; #不缓存 直接响应给客户端
123 return(deliver);
124 }
125 if(bereq.url ~ "\.(css|html|htm|png)$"){ #静态数据
126 set beresp.ttl = 15m; #缓存15分钟时间
127 }
128 if(bereq.url ~ "\.(gz|bz2|zip|mp3)$"){ #压缩文件
129 set beresp.ttl = 300s; #缓存300s
130 }
131 return(deliver);
132 }
133 sub vcl_backend_error{ #后端找不到对应的数据
134 if(beresp.status == 503){ #当状态码为503
135 set beresp.status = 200; #把状态码换成200
136 synthetic("hahahaha"); #返回页面 hahahaha
137 return(deliver);
138 }
139 }
140 sub vcl_purge{ #清除缓存模块
141 return(synth(200,"success~~~~")); #状态码变成200 成功
142 }
143 sub vcl_deliver{ #结束模块
144 if(obj.hits > 0){ #如果命中次数大于0
145 set resp.http.X-cache = "hit~~~~~"; #则在varnish对客户端的响应头部建立hit~~
146 }
147 else{
148 set resp.http.X-cache = "miss~~~~"; #其余则在varnish对客户端的响应头部建立miss~~
149 }
150 }
[root@localhost ~]# killall -9 varnishd
[root@localhost ~]# varnishd -f /usr/local/varnish/default.vcl
客户端访问:
[root@localhost ~]# curl -I 192.168.10.3
X-cache: miss~~~~
[root@localhost ~]# curl -I 192.168.10.3
X-cache: hit~~~~~
客户端清除缓存:
[root@localhost ~]# curl -I http://192.168.10.3 -X PURGE
HTTP/1.1 405 not allowed
Date: Tue, 23 Jun 2020 04:24:26 GMT
Server: Varnish
X-Varnish: 5
Content-Type: text/html; charset=utf-8
Retry-After: 5
Content-Length: 251
Connection: keep-alive
varnish清除:
[root@localhost ~]# curl -I http://192.168.10.3 -X PURGE
HTTP/1.1 200 success~~~~
Date: Tue, 23 Jun 2020 04:27:22 GMT
Server: Varnish
X-Varnish: 32772
Content-Type: text/html; charset=utf-8
Retry-After: 5
Content-Length: 255
Accept-Ranges: bytes
Connection: keep-alive
错误页面是否能访问成功 把varnish的缓存清除 后端的web关掉
客户端访问的
[root@localhost ~]# curl -I 192.168.10.3
HTTP/1.1 200 OK
Date: Tue, 23 Jun 2020 04:28:39 GMT
Server: Varnish
X-Varnish: 7
Age: 0
Via: 1.1 varnish-v4
X-cache: miss~~~~
Accept-Ranges: bytes
Connection: keep-alive
[root@localhost ~]# curl 192.168.10.3
hahahaha[root@localhost ~]#
访问qqq www这两个页面
后端服务开启
反向代理清除缓存 varnish重启
客户端:
[root@localhost ~]# vim /etc/hosts
192.168.10.3 www.abc.com
192.168.10.3 qqq.abc.com
[root@localhost ~]# curl www.abc.com
22222
[root@localhost ~]# curl qqq.abc.com
11111
varnish启动参数:
-a:指定varnish服务的监听端口与ip
例 -a 192.168.1.100:80
-f:指定配置文件
例 -f /usr/local/varnish/default.vcl
-n:指定varnish工作目录
例 -n /usr/local/varnish
-P:指定varnish进程PID号存放的文件
例 -P /usr/local/varnish/varnish.pid
-s:指定varnish缓存数据的文件
例 -s /usr/local/varnish/cache.data,1G
-T:管理varnish主机的IP与端口
例 -T 192.168.8.12:3500
-S:管理varnish主机使用的密钥文件
例 -S /etc/vc
-p:指定varnish运行时的参数
例 -p thread_pools=2:指定varnish开启的线程池的个数,与CPU个数或核心数一致
-p thread_pool_min=50:指定每个线程池中最少开启线程数量
-p thread_pool_max=5000:指定每个线程池中最多开启线程数量
-p thread_pool_timeout=30:当线程池中线程的数量超过最小值,且30s内没有客户端的请求,则对线程数量进行释放的最小值
-p lru_interval=30:没有指定缓时间的数据如果一直处于未命中状态,则缓存时间为该值,单位是s
程序–进程(获取程序所需的资源)–线程
[root@localhost ~]# varnish
varnishadm varnishhist varnishncsa varnishtest
varnishd varnishlog varnishstat varnishtop
varnishadm管理varnish
使用随机数生成密钥:
[root@localhost ~]# dd if=/dev/random of=/etc/vc count=1
0+1 records in
0+1 records out
115 bytes (115 B) copied, 0.000196612 s, 585 kB/s
[root@localhost ~]# cat /etc/vc
#重启varnish
[root@localhost ~]# killall -9 varnishd
[root@localhost ~]# varnishd -a 192.168.2.10:80 -f /usr/local/varnish/default.vcl -n /usr/local/varnish/ -P /usr/local/varnish/varnish.pid -s file,/usr/local/varnish/cache.data,1G -T 192.168.2.10:3500 -S /etc/vc -p thread_pools=2 -p thread_pool_min=50 -p thread_pool_max=1000 -p thread_pool_timeout=30 -p lru_interval=30
[root@localhost ~]# netstat -anput | grep varnishd
tcp 0 0 192.168.2.10:3500 0.0.0.0:* LISTEN 19517/varnishd
tcp 0 0 192.168.2.10:80 0.0.0.0:* LISTEN 19517/varnishd
交互式界面:
[root@localhost ~]# varnishadm -T 192.168.2.10:3500 -S /etc/vc
varnish> status
200
Child in state running
varnish> start
300
Child in state running
stop
200
varnish> start
200
varnish> backend.list
200
Backend name Admin Probe
boot.web1 probe Healthy 5/5
boot.web2 probe Healthy 5/5
quit退出
命令行:
清除缓存
[root@localhost ~]# varnishadm ban req.url "~" / #varnish启动
varnishadm [-t timeout ] [-S 密钥文件] [-T address:port] [-n name] [command]
#
-t 等待操作完成的时间
-S 认证的安全文件
-T 管理的接口和地址
-n 连接接口的名称
command 执行的命令
[root@localhost ~]# varnishadm -S /etc/vc -T 192.168.2.10:3500 stop
[root@localhost ~]# varnishadm -S /etc/vc -T 192.168.2.10:3500 start
[root@localhost ~]# varnishadm -S /etc/vc -T 192.168.2.10:3500 backend.list
Backend name Admin Probe
boot.web1 probe Healthy 5/5
boot.web2 probe Healthy 5/5
varnishstat #查看状态和参数
[root@localhost ~]# cd /usr/local/varnish/
[root@localhost varnish]# ls
bin default.vcl lib share varnish.pid _.vsm
cache.data include sbin var vcl_boot.1592884068.760178804
#_.vsm 是通过制定的配置文件启动后生成的文件
[root@localhost varnish]# cd /usr/local/varnish/var/varnish/localhost.localdomain/
[root@localhost localhost.localdomain]# ls
_.secret vcl_boot.1592794538.439760923 vcl_boot.1592882130.538364649
vcl_boot.1592623750.409803391 vcl_boot.1592794742.336751223 vcl_boot.1592882197.950655222
vcl_boot.1592623912.852447987 vcl_boot.1592794773.063064337 vcl_boot.1592882357.811198235
vcl_boot.1592626478.964962482 vcl_boot.1592881557.420217991 _.vsm
[root@localhost localhost.localdomain]# cp /usr/local/varnish/_.vsm ./
cp: overwrite ‘./_.vsm’? y
#varnishstat这个命令只能查看到对应目录的_.vsm这个文件 所以需要把通过制定的配置文件生成的vsm文件复制到对应目录下 这样才能查看到当前这个配置文件的参数和状态
[root@localhost localhost.localdomain]# varnishstat
varnishlog 查看日志
varnishncsa 用来查看简单的日志
[root@localhost ~]# varnishlog -n /usr/local/varnish/ -w /usr/local/varnish/varnish.log
-n 代表工作目录
-w 代表日志生成的文件
#需要有台运行
客户端上访问:
[root@localhost ~]# curl 192.168.2.10
2222
[root@localhost ~]# curl 192.168.2.10
2222
varnish上另开终端:
[root@localhost varnish]# cd /usr/local/varnish/
[root@localhost varnish]# ls
bin default.vcl lib share varnish.log vcl_boot.1592884068.760178804
cache.data include sbin var varnish.pid _.vsm
[root@localhost varnish]# cat varnish.log
varnishncsa
[root@localhost ~]# rm -rf /usr/local/varnish/varnish.log
[root@localhost ~]# varnishncsa -n /usr/local/varnish/ -w /usr/local/varnish/varnish.log
后台运行
客户端上访问:
[root@localhost ~]# curl 192.168.2.10
2222
[root@localhost ~]# curl 192.168.2.10
2222
varnish上另开终端:
[root@localhost varnish]# cd /usr/local/varnish/
[root@localhost varnish]# ls
bin default.vcl lib share varnish.log vcl_boot.1592884068.760178804
cache.data include sbin var varnish.pid _.vsm
[root@localhost varnish]# cat varnish.log
[root@localhost varnish]# cat varnish.log
192.168.2.100 - - [23/Jun/2020:12:14:19 +0800] "GET http://192.168.2.10/ HTTP/1.1" 200 5 "-" "curl/7.29.0"