web cache
程序具有局部性
时间局部性
空间局部性
key-value:
key:访问路径,URL,hash
value:web content
热点数据:
命中率:hit(hit+miss)
文档命中率,从文档个数进行衡量
字节命中率:从内容进行衡量
注意:缓存对象,生命周期,定期清理
缓存空间耗尽,LRU(最近最少使用)
可缓存,不可缓存(用户私有数据)
缓存处理的步骤:
接受请求-->解析请求(提取请求的url及各种首部)-->查询缓存-->新鲜度检测-->创建响应报文-->发送相应-->记录日志
新鲜度检测机制:
过期日期:
HTTP/1.0
Expires:Thu, 01 Jan 1970 00:00:00 GMT
HTTP/1.1:
Cache-Control:max-age=600
有效性再验证:revalidate
如果原始内容未改变,则仅仅响应(不附带body部分),响应码为304(not modified)
如果原始你饿哦让发生改变,则正常响应,响应码为200
如果原始内容小时,则相应404,此时换出浓重的cache object也应该被删除
条件式请求首部:
If-Modified-Since:基于其你去内容的时间戳做验证
If-Unmodified-Since
If_match
If-None-match
Etag:faiy89345
常见的缓存服务开源解决方案:
varnish,squid(类似nginx-->apache),nginx,apache
web cache:
squid,varnish
http://book.varnish-software.com/
DSL:vcl
管理进程:编译VCK并应用新配置,监控varish,初始化varnish,CLI接口
child/cache:
Acceptor:接收新的连接请求
workerthreads:处理用户请求
expiry:清理缓存中的过期对象
日志:share memory log,共享内存日志大小默认一般为90MB,分为两部分,亲一部分为计数器,后一部分请求相关的数据
VCL:varnishconfiguration language
缓存策略配置接口
基于“域”的简单编程语言
内存分配和回收:
malloc(),free()
varnish如何存储缓存对象
file:单个文件,不支持持久机制
malloc:内存
persistent:基于文件的持久存储
配置varnish的三种应用:
1. varnishd应用程序的命令行参数
监听的socket,使用的存储类型等等,额外的配置参数
-p: param=value
-r:param,param,…设定只读参数列表
/etc/varnish/varnish.params
2.-p选项指明的参数:
运行时参数
也可在程序运行中,通过其CLI进行配置
2. vcl配置缓存系统的缓存机制
通过vcl配置文件进行配置
先编译,后应用
依赖于c编译器
安装:
yum install varnish –y
epel源提供了安装包
/etc/logrotate.d/varnish
/etc/varnish
/etc/varnish/default.vcl
/etc/varnish/varnish.params
配置:
cat /usr/lib/systemd/system/varnish.service
man varnishd
cd /etc/varnish/
vim varnish.params
centos 7的epel源自带的时4.0.5版本
在varnish.params文件中定义的默认存储方式为内存存储
VARNISH_STORAGE="malloc,256M"
default.vcl:
修改
backend default {
.host = "192.168.137.135";
.port = "80";
}
host为后端服务器ip
port为后端服务器端口
开启varnish服务:
systemctl start varnish
关闭selinx和防火墙:
setenforce 0
service firewalld stop
service iptables stop
查看6081,6082端口监听:
netstat -tnlp | grep varnish
tcp 0 0 0.0.0.0:6081 0.0.0.0:* LISTEN 35302/varnishd
tcp 0 0 127.0.0.1:6082 0.0.0.0:* LISTEN 35293/varnishd
tcp6 0 0 :::6081 :::* LISTEN 35302/varnishd
后端服务器开启httpd服务添加html文件
for i in {1..10}; do echo "page ${i} on node35.com" > /var/www/html/test${i}.html; done
访问缓存服务器:
查看:
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
[root@node30 varnish]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
200
-----------------------------
Varnish Cache CLI 1.0
-----------------------------
Linux,3.10.0-693.el7.x86_64,x86_64,-smalloc,-smalloc,-hcritbit
varnish-4.0.5 revision 07eff4c29
Type 'help' for command list.
Type 'quit' to close CLI session.
help
200
help [<command>]
ping [<timestamp>]
auth <response>
quit
banner
status
start
stop
vcl.load <configname> <filename>
vcl.inline <configname> <quoted_VCLstring>
vcl.use <configname>
vcl.discard <configname>
vcl.list
param.show [-l] [<param>]
param.set <param> <value>
panic.show
panic.clear
storage.list
vcl.show [-v] <configname>
backend.list [<backend_expression>]
backend.set_health <backend_expression> <state>
ban <field> <operator> <arg> [&& <field> <oper> <arg>]...
ban.list
backend.list:列出后端服务器
varnish> backend.list
200
Backend name Refs Admin Probe
default(192.168.137.135,,80) 1 probe Healthy (no probe)
varnishlog命令:
varnishlog读取共享内存信息
输入varnishlog命令,没有显示信息,当有访问时会有输出信息
[root@node30 varnish]# varnishlog
* << Request >> 32779
- Begin req 32778 rxreq
- Timestamp Start: 1525315271.586835 0.000000 0.000000
- Timestamp Req: 1525315271.586835 0.000000 0.000000
- ReqStart 192.168.137.2 55600
- ReqMethod GET
- ReqURL /test1.html
- ReqProtocol HTTP/1.1
- ReqHeader Host: 192.168.137.130:6081
- ReqHeader Connection: keep-alive
- ReqHeader Cache-Control: max-age=0
- ReqHeader Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
- ReqHeader Upgrade-Insecure-Requests: 1
- ReqHeader User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0
- ReqHeader Accept-Encoding: gzip, deflate, sdch
- ReqHeader Accept-Language: zh-CN,zh;q=0.8
- ReqHeader If-None-Match: "15-56b43b317d678"
- ReqHeader If-Modified-Since: Thu, 03 May 2018 02:09:55 GMT
- ReqHeader X-Forwarded-For: 192.168.137.2
- VCL_call RECV
- VCL_return hash
- ReqUnset Accept-Encoding: gzip, deflate, sdch
- ReqHeader Accept-Encoding: gzip
- VCL_call HASH
- VCL_return lookup
- Hit 6
- VCL_call HIT
- VCL_return deliver
- RespProtocol HTTP/1.1
- RespStatus 200
- RespReason OK
- RespHeader Date: Thu, 03 May 2018 02:40:27 GMT
- RespHeader Server: Apache/2.4.6 (CentOS)
- RespHeader Last-Modified: Thu, 03 May 2018 02:09:55 GMT
- RespHeader ETag: "15-56b43b317d678"
- RespHeader Content-Length: 21
- RespHeader Content-Type: text/html; charset=UTF-8
- RespHeader X-Varnish: 32779 6
- RespHeader Age: 50
- RespHeader Via: 1.1 varnish-v4
- VCL_call DELIVER
- VCL_return deliver
- Timestamp Process: 1525315271.586994 0.000159 0.000159
- RespProtocol HTTP/1.1
- RespStatus 304
- RespReason Not Modified
- RespReason Not Modified
- RespUnset Content-Length: 21
- Debug "RES_MODE 0"
- RespHeader Connection: keep-alive
- Timestamp Resp: 1525315271.587269 0.000434 0.000275
- Debug "XXX REF 2"
- ReqAcct 518 0 518 283 0 283
- End
* << Session >> 32778
- Begin sess 0 HTTP/1
- SessOpen 192.168.137.2 55600 :6081 192.168.137.130 6081 1525315271.586679 14
- Link req 32779 rxreq
- SessClose RX_TIMEOUT 5.092
- End
varnishncsa命令:
[root@node30 varnish]# varnishncsa
192.168.137.2 - - [03/May/2018:10:45:14 +0800] "GET http://192.168.137.130:6081/test1.html HTTP/1.1" 304 0 "-"
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0"
输入varnishncsa,有访问时会有输出输出信息
varnishtop命令
varnishstat命令
命令行工具:
varnishadm-S /etc/varnish/secret -T IP:PORT
Log:varnishlog
varnishncsa
varnishstat
statistics
varnishstat
Top:
varnishtop
varnish(2)
vcl:
state engine:各引擎之间在一定程度上的相关性,前一个engine如果可以有多个下游engine,则上游engine需要 return指明要转移的下游engine
vcl_recv
vcl_hash
vcl_hit
vcl_miss
vcl_fetch
vcl_deliver
vcl_pipe
vcl_pass
vcl_error
编程语言语法:
(1)//,#,/*…*/用于注释,会被编译器忽略
(2)sub $name:用于定义子例程
sub_vcl_recv{
}
(3)不支持循环
(4)有众多内置的变量,变量的可调用位置与state engine有密切相关性
(5)支持终止语句,return(action),没有返回值
(6)“域”专用
(7)操作符:=,==,~,&&,||,!
条件语句判断语法:
if(condition){
}else{
}
变量赋值:setname=value
unset
req.http.HEADER:调用request报文中的http协议的指定的HEADER首部:
req.http.X-Forwarded-For
req.http.Authorization
req.http.cookie
req.request:请求方法
client.ip:客户端IP
官方文档:https://varnish-cache.org/docs/5.1/reference/vcl.html#varnish-configuration-language
参考博客:http://blog.51cto.com/hao360/1530236
state engine workflow(V3):
vcl_recv-->vcl_hash-->vcl_hit-->vcl_deliver
vcl_recv-->vcl_hash-->vcl_miss-->vcl_fetch-->vcl_delivere
vcl_recv-->vcl_pass-->vcl_fetch-->vcl_deliver
vcl_recv-->vcl_pipe
state engine worlflow(V4):
vcl_recv
vcl_pass
vcl_pipe
vcl_hash
vcl_hit
vcl_miss
vcl_backend_fetch
vcl_backend_response
vcl_nackend_error
vcl_purge
vcl_synth
备份default.vcl
cp default.vcl test.vcl
编辑使用test.vcl:
vim test.vcl
修改sub vcl_recv配置(从官网复制subvcl_recv配置,修改即可)
sub vcl_recv {
if (req.method == "PRI") {
/* We do not support SPDY or HTTP/2.0 */
return (synth(405));
}
if (req.method != "GET" &&
req.method != "HEAD" &&
req.method != "PUT" &&
req.method != "POST" &&
req.method != "TRACE" &&
req.method != "OPTIONS" &&
req.method != "DELETE") {
/* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
if (req.method != "GET" && req.method != "HEAD") {
/* We only deal with GET and HEAD by default */
return (pass);
}
if (req.http.Authorization || req.http.Cookie) {
/* Not cacheable by default */
return (pass);
}
return (hash);
}
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
vcl.load test1 test.vcl
200
VCL compiled.
vcl.list
200
active 0 boot
available 0 test1
多了一个test1(test1)
使test1生效
vcl.use test1
200
VCL 'test1' now active
这样不便于观察,为了便于观察,修改test.vcl的subvcl_deliver配置
加入
if (obj.hits>0) {
set resp.http.X-Cache = "HIT";
} else{
set resp.http.X-Cache = "MISS";
}
定义在vcl_deliver中,向相应客户端的报文添加一个自定义首部X-Cache
访问资源:
curl -I 192.168.137.130:6081/test6.html
第一次访问首部的X-Cache为MISS
X-Cache: MISS
第二次:X-Cache:HIT
varnish中的内置变量:
变量种类:
req
client
server
bereq
obj
beresp
storage
bereq
bereq.http.HEADERS:由varnish发往backend server的请求报文的指定首部
bereq.request:请求方法
bereq.url:
bereq.proto:
bereq.backend:指明要调用的后端主机
beresp:
beresp.proto:
beresp.status:后端服务器的响应状态码
beresp.ip
beresp.backend.name:
beresp.http:
beresp.HEADERS:从backend响应的报文首部
beresp.ttl:后端服务器响应的内容的余下的生存时长
obj:
obj.ttl:对象的ttl值
obj.hits:此对象从缓存中命中的次数
支持虚拟主机:
if (req.http.host == “www.magedu.com”) {
}
强制对某资源的请求不检查缓存:
在test.vcl的vcl_recv加入
if (req.url ~ "^/test7.html$") {
return(pass);
}
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
vcl.load test4 test.vcl
vcl.use test4
vcl.show test4
访问资源:
curl -I 192.168.137.130:6081/test6.html
访问test6.html,第二次显示已经命中,而访问test7.html一直显示未命中
/admin
/login
if (req.url ~ “(?i)^/login” || req.url ~ (?i)“^/admin”) {
return(pass)
}
其中(?i)表示忽略大小写
对特定类类型的资源取消私有的cookie标识
在test.vcl的subvcl_backend_response加入
if (beresp.http.cache-control !~ "s_maxage") {
if (bereq.url ~ "(?i)\.jpg$") {
set beresp.ttl = 300s;
unset beresp.http.Set-Cookie;
}
if (bereq.url ~ "(?i)\.css$") {
set beresp.ttl =600s;
unset beresp.http.Set-Cookie;
}
}
重新编译使用:
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
vcl.load test5 test.vcl
vcl.use test5
vcl.show test5
参考:https://varnish-cache.org/docs/4.1/reference/vcl.html
backendserver的定义:
backend name {
.attribute = “value”;
}
.host:BE主机的IP
.port:BE主机监听的PORT
probe:对BE做健康状态监测
. max_connections: 打开连接到此后端的最大数量
后端主机的健康状态监测方式:
probe name {
.attribute = "value";
}
.url:判定BE健康与否要请求的url
.expected_response:期望响应状态码,默认为200
加入后端:
backend websrv1 {
.host = "192.168.137.135";
.port = "80";
.probe = {
.url = "/test1.html";
}
}
backend websrv2 {
.host = "192.168.137.128";
.port = "80";
.probe = {
.url = "/test1.html";
}
}
在sub vcl_recv中加入:
if (req.url ~ "(?i)\.(jpg|png|gif)$") {
set req.backend_hint = websrv1;
}else {
set req.backend_hint = websrv2;
}
后端主机安装并开启httpd
systemctl start httpd
给后端两台主机加入页面:
for i in {1..10}; do echo "test${i} on web${i}" > /var/www/html/test${i}.html; done
缓存服务器重启varnish服务
service varnish restart
重新编译命名使用:
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
vcl.load test1 test.vcl
vcl.use test1
vcl.show test1
backend.list
varnish> backend.list
200
Backend name Refs Admin Probe
default(192.168.137.135,,80) 1 probe Healthy (no probe)
websrv1(192.168.137.135,,80) 1 probe Healthy 8/8
websrv2(192.168.137.128,,80) 1 probe Healthy 8/8
此时只有192.168.137.135主机上的/var/www/html/目录下游kobe0.jpg文件
访问缓存服务器:
此静态页面已经请求到192.168.137.135主机上的文件
请求的html文件响应的时192.168.137.128主机上的内容
实现了动静分离
示例2:
backend websrv2 {
.host = "192.168.137.128";
.port = "80";
.probe = {
.url = "/test1.html";
}
}
import directors;
sub vcl_init {
new mycluster = directors.round_robin();
mycluster.add_backend(websrv1);
mycluster.add_backend(websrv2);
}
sub vcl_recv {
# Happens before we check if we have this in cache already.
#
# Typically you clean up the request here, removing cookies you don't need,
# rewriting the request, etc.
#if (req.url ~ "(?i)\.(jpg|png|gif)$") {
# set req.backend_hint = websrv1;
#} else {
# set req.backend_hint = websrv2;
#}
if (req.url ~ "(?i)test1\.html$") {
return(pass);
}
set req.backend_hint = mycluster.backend();
}
不同的html文件会轮询
负载均衡算法:
fallback,random,round_robin,hash
掌握:varnishlog,varnishncsa,varnishtop,varnishstat