一. Web Page Cache 相关概念
1. 程序的运行具有局部性原理:
#缓存可以提供http的速度,也是基于这两个原理
时间局部性: 即一个资源被访问到后,短时间内有可能被再次访问到,
同时资源也遵循28定律,有20%的资源为高频访问资源.
空间局部性: 即空间中相近的资源将更快被访问到
2. cache命中率:
缓存命中率:hit/(hit+miss)
页面命中率:基于页面数量进行衡量
字节命中率:基于页面的体积进行衡量
缓存存在热区,即局部性;
时效性:
缓存空间耗尽:LRU
过期:缓存清理
3. 资源缓存与否:(分类)
私有数据:private,private cache;
此类数据仅提供私人缓存即浏览器缓存
公共数据:public, public or private cache;
此类数据可以作为公共缓存或私人缓存
4. Cache-related Headers Fields #缓存相关的http首部
The most important caching header fields are:
Expires:绝对过期时间;
Expires:Thu, 22 Oct 2026 06:34:30 GMT
Cache-Control : 缓存控制,即定义是否缓存
Etag: 版本标签,用于弥补时间戳无法精确定义资源是否改变
Last-Modified: 最后修改时间(服务端发往客户端,存在于响应报文)
If-Modified-Since: 最后修改时间(客户端发往服务端, 存在于请求报文)
If-None-Match:匹配Etag, 若匹配即未修改,返回304状态吗
Vary:告诉下游代理是使用缓存响应还是从原始服务器请求
Age:从原始服务器到代理缓存形成的估算时间(以秒计,非负)
5.缓存有效性判断机制:
过期时间:Expires
HTTP/1.0
Expires 绝对过期时间
HTTP/1.1
Cache-Control: maxage= 相对过期时间
Cache-Control: s-maxage= 公共资源相对过期时间
条件式请求:
Last-Modified/If-Modified-Since
Etag/If-None-Match
示例:
Expires:Thu, 13 Aug 2026 02:05:12 GMT
Cache-Control:max-age=315360000
ETag:"1ec5-502264e2ae4c0"
Last-Modified:Wed, 03 Sep 2014 10:00:27 GMT
6. 请求报文中的cache-control对应值:
cache-request-directive =
"no-cache"
#缓存下来后,但响应时要求每次都需要向原始服务器做校验
"no-store" :
#不缓存
"max-age" "=" delta-seconds
# 相对最大有效时长,即只接受age值小于此值的未过期对象
"max-stale" [ "=" delta-seconds ]
#接受过期对象,但是过期时间必须小于此值
"min-fresh" "=" delta-seconds
#接受其新鲜生命期大于其当前 Age 跟 min-fresh 值之和的缓存对象
"no-transform"
#未改变
"only-if-cached"
#只有缓存中有相应资源时,客户端才能收到响应
cache-extension
7. 响应报文中的cache-control对应值:
cache-response-directive =
"public" #公共资源
| "private" [ "=" <"> 1#field-name <"> ]
#指定为私有资源
| "no-cache" [ "=" <"> 1#field-name <"> ]
#略
| "no-store"
#略
| "no-transform"
#略
| "must-revalidate"
#类似 no-cache, 但是强制性更大
| "proxy-revalidate"
#类似must-revalidate,但只作用于代理端
| "max-age" "=" delta-seconds
| "s-maxage" "=" delta-seconds
| cache-extension
======================================================================================
二.varnish
1.开源解决方案:
squid:
varnish:
2. varnish官方站点: http://www.varnish-cache.org/
This is Varnish Cache, a high-performance HTTP accelerator.
版本: Community
Enterprise —带有web GUI 功能
#目前最新为5.0, 3–4.0使用居多,并且vcl 语法互不兼容
3. 程序架构及组成:
Manager进程: 即父进程
Cacher进程(真正提供响应请求处理的),包含多种类型的线程:
accept, worker, expiry, …
shared memory log:
统计数据:计数器;
日志区域:日志记录;
varnishlog, varnishncsa, varnishstat…
varnishadm : varnish cli 交互式专用管理工具
配置接口:VCL
Varnish Configuration Language,
vcl complier –> c complier –> shared object
#VCL规则需要由vcl complier 编译器 调用c 编译器编译后,成为一个共享对象
才能供varnish加载使用
————————————————————————–
4. varnish的程序环境:
/etc/varnish/varnish.params: 配置varnish服务进程的工作特性,例如监听的地址
和端口,缓存机制;
注意:
早期的配置为/etc/sysconfig/varnishd/下的文件
/etc/varnish/default.vcl:配置各Child/Cache线程的工作属性;
配置文件的工作机制:
以变量形式定义varnish 自身的工作特性,各变
在/etc/varnish/varnish.params中定义;
同时,在启动时,由/usr/lib/systemd/system/varnish.service
负责调用varnish.params文件
备注:
1. 修改varnish工作个性配置,即/etc/varnish/varnish.params,
不需要重新编译vcl,与之无关,重启varnish.server 即可
2. 修改vcl模板配置时,常为修改/etc/varnish/default.vcl
并且,修改完成后,需要用特定命令varnish_reload_vcl
或者varnishadm进行重载
主程序:
/usr/sbin/varnishd
CLI interface:
/usr/bin/varnishadm
Shared Memory Log交互工具:
/usr/bin/varnishhist
#历史记录
/usr/bin/varnishlog
#最为详细的log记录,基于报文首部来分来
/usr/bin/varnishncsa
#基于httpd combind类似的格式
/usr/bin/varnishstat
#即时各状态的信息
/usr/bin/varnishtop
#基于请求数量由大到小的顺序排序的日志
测试工具程序:
/usr/bin/varnishtest
VCL配置文件重载程序:
/usr/sbin/varnish_reload_vcl
Systemd Unit File:
/usr/lib/systemd/system/varnish.service
#varnish服务:
/usr/lib/systemd/system/varnishlog.service
/usr/lib/systemd/system/varnishncsa.service
#日志持久,滚动的服务;
默认VCL配置文件: /etc/varnish/default.vcl
# 默认此文件为空,可自行添加自定义项目
#默认已经启用内建vcl配置, 使用varnishadm –vcl.show -v boot可查看
内建VCL配置文件: /usr/share/doc/varnish-##/builtin.vcl
#可将其复制到/etc/varnish下编译使用
5.varnish的缓存存储机制( Storage Types):
· malloc[,size]
内存存储,[,size]用于定义空间大小;重启后所有缓存项失效;
· file[,path[,size[,granularity]]]
文件存储,黑盒;重启后所有缓存项失效;
#对外抽象为单一的一个日志文件,且仅varnish 能识别(黑盒)
· persistent,path,size
文件存储,黑盒;重启后所有缓存项有效;实验;
6. varnish程序的选项:
#用于手动以命令形式修改varnish 的工作参数,效果与手动修改配置文件一样
(程序选项:/etc/varnish/varnish.params文件)
-a address[:port][,address[:port][…],默认为6081端口;
#缓存服务监听接口
#使用时,需要改为80端口;
-T address[:port],默认为6082端口;
#管理监听接口
-s [name=]type[,options],定义缓存存储机制;
默认为file:
VARNISH_STORAGE="file,/var/lib/varnish/varnish_storage.bin,1G"
可修给为malloc,内存工作机制:
VARNISH_STORAGE="malloc,512M"
-u user #默认运行用户为varnish
-g group #默认组为varnish
-f config:VCL配置文件;
-F:运行于前台;
…
运行时参数:/etc/varnish/varnish.params文件, DEAMON_OPTS
DAEMON_OPTS="-p thread_pool_min=5 -p thread_pool_max=500 -p
thread_pool_timeout=300"
-p param=value:设定运行参数及其值; 可重复使用多次;
-r param[,param…]: 设定指定的参数为只读状态,即不允许运行时修改
重载vcl配置文件:
~ ]# varnish_reload_vcl
============================================================
三. varnishadm
1. 常用选项:
-S /etc/varnish/secret -T [ADDRESS:]PORT
#使用varnishadm 时候,需要使用与服务器启动时所用的同一个密钥文件进行认
证,即/etc/varnish/secret,并-T 指定服务器以及端口,默认为8082端口
#当执行任何命令时,若执行成功,则会返回200代码
help [<command>] #获取命令帮助
ping [<timestamp>] #检测服务器工作状态,正常则返回pang
auth <response> #
quit
banner #重新加载varnishadm标题
status #获取状态信息
start #varnishd服务启动
stop #服务停止
vcl.load <configname> <filename> #VCL模板命令
vcl.inline <configname> <quoted_VCLstring>
vcl.use <configname>
vcl.discard <configname>
vcl.list
vcl.show [-v] <configname>
param.show [-l] [<param>] #运行参数相关命令
param.set <param> <value>
panic.show
panic.clear
storage.list #缓存存储情况
backend.list [<backend_expression>] #后端服务器列表
backend.set_health <backend_expression> <state> #后端服务器健康情况
ban <field> <operator> <arg> [&& <field> <oper> <arg>]…
#用于定义如何手动清理缓存
ban.list
2.配置文件相关:
vcl.list #列出已经成功编译的vcl版本
available : 可以使用版本
active: 正在启用的版本
vcl.load:装载,加载并编译;
eg:
vcl.reload testconf1 /etc/varnish/default.vcl
#加载/etc/varnish/default.vcl,并编译后取名为testconf1
vcl.use:激活;#使用指定版本,注意需要先load才能使用
eg:
vcl.use testconf1
vcl.discard:删除未被使用的acl版本,即available状态的
vcl.show [-v] <configname>:查看指定的配置文件的详细信息;
#用于查看已经生效的配置
eg:
vcl.show -v boot
#此配置信息为默认配置
3. 运行时参数:
param.show -l:显示列表;其中包含可以修改的全部参数
param.show <PARAM> #显示指定项的参数
eg:
param.show thread_pool_max
param.set <PARAM> <VALUE>
eg:
param.set thread_pool.max 1024
4. 缓存存储:
storage.list
5. 后端服务器:
backend.list
===========================================================
四. VCL:
1. vcl :”域“专有类型的配置语言;与varnish内部的 state enging状态引擎相关;
2. 状态引擎
VCL状态引擎切换机制: 内部有多个状态引擎,状态之间存在相关性,但彼此间互相隔离;每
个状态引擎可使用
return(x)指明关联至哪个下一级引擎;
eg: vcl_hash –> return(hit) –> vcl_hit
两个特殊的引擎:
vcl_init:在处理任何请求之前要执行的vcl代码:主要用于初始化VMODs;
vcl_fini:所有的请求都已经结束,在vcl配置被丢弃时调用;主要用于清理VMODs;
3. 请求处理流程:
#详细处理流程,可以参照/usr/share/doc/varnish-###/builtin.vcl中的定义
(1) state engine /组件 说明:
客户端请求接收: vcl_recv
url哈希: vcl_hash
缓存命中: vcl_hit
缓存未命中: vcl_miss
报文后端传送: vcl_pass
后端主机报文获取: vcl_fetch
缓存项修剪: vcl_purge
session(cookie)/authorization 认证报文后端传送: vcl_pipe
客户端响应:vcl_deliver
繁忙等待队列: vcl_waiting
后端返回报文接收: vcl_backend_response
后端服务器错误: vcl_backend_error
后端返回报文可缓存性判断: cacheable
purge响应报文构建: vcl_synth
(2) 接收请求:vcl_recv;判断其是否可缓存;
(a) 可缓存:vcl_hash
(i) 命中:vcl_hit
(ii)未命中:vcl_miss –> vcl_fetch
(b) 不可缓存:直接–>vcl_fetch
(c) http方法不可识别: –> vcl_pipe(管道输送给后端服务器)
(d) purge方法: 修剪缓存对应项–>vcl_synth ()
(e) 服务器繁忙期间 : –> vcl_waiting 请求进入等待队列
(f) 请求报文首部含有用户session/authorization–> vcl_pass–>vcl_fetch
传输给后端服务器
(g) 非get/head 方法—> vcl_pass, 传送给后端服务器
(3) #varnish 4.0 内部处理流程图,
注意: 4.0以前的处理流程会有所不同,部分请求,不会都通往vcl_hash
部分处理路径:
(1) vcl_hash -(hit)-> vcl_hit –> vcl_deliver
(2) vcl_hash -(miss)-> vcl_miss –> vcl_backend_fetch –> vcl_backend_response –>
vcl_deliver
(3) vcl_hash -(purge)-> vcl_purge –> vcl_synth
(4) vcl_hash -(pipe)-> vcl_pipe
===========================================================
五. VCL语法详解
1.vcl的语法格式:
(1) VCL files start with vcl 4.0;
#varnish 4.0 acl配置文件必须以"vcl 4.0"
(2) //, # and /* foo */ for comments;
#单行注释,以及多行注释, C语言风格;
(3) Subroutines are declared with the sub keyword; 例如sub vcl_recv { …};
#用于定义状态引擎的工作机制
(4) No loops, state-limited variables(受限于引擎的内建变量);
#不支持循环,但支持条件判断
(5) Terminating statements with a keyword for next action as argument of the
return() function, i.e.: return(action);
#每个状态引擎定义sub 最后,使用return 返回值来指定下一个前往的引擎
(6) Domain-specific;
#每个状态引擎的配置,只对一个状态引擎有效
2. The VCL Finite State Machine ##状态引擎工作特性
(1) Each request is processed separately;
#各请求独立处理
(2) Each request is independent from others at any given time;
#每个请求在任何时候都与其他请求独立
(3) States are related, but isolated;
#每个状态都互相独立
(4) return(action); exits one state and instructs Varnish to proceed to the next
state;
(5) Built-in VCL code is always present and appended below your own VCL;
#内建的cvl
3. 三类主要语法:
1. sub subroutine {
…
}
#用于定义状态引擎工作配置
eg:
sub vcl_purge {
return (synth(200, "Purged"));
}
—————————————
2. if CONDITION {
…
} else {
…
}
`#用于定义不同报文的处理动作
eg:
if (req.method == "PRI") {
/* We do not support SPDY or HTTP/2.0 */
return (synth(405));
}
——————————————
3. return() # 定义返回值
4. hash_data() #哈希指定url
eg:
sub vcl_hash {
hash_data(req.url);
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
return (lookup);
}
4.VCL Built-in Functions and Keywords #内建函数
函数:
regsub(str, regex, sub)
#替换str中regex第一次匹配到的内容替换为sub
regsuball(str, regex, sub)
#替换str中regex匹配到的全部内容为替换sub
ban(boolean expression)
#基于布尔型表达式匹配的缓存清理
hash_data(input)
#哈希指定数据
synthetic(str)
Keywords:
call subroutine, #调用子例程
return(action),
new, #
set, #设定变量值
unset #撤销变量值
操作符:
==, !=, ~, >, >=, <, <=
逻辑操作符:&&, ||, !
变量赋值:=
补充:
(?i) : 为正则表达式开头项,代表不检查大小写
举例:obj.hits
sub vcl_deliver {
if (obj.hits>0) {
set resp.http.X-Cache = "HIT via " + server.ip;
} else {
set resp.http.X-Cache = "MISS via " + server.ip;
}
}
内建函数使用限定区域示意图:
5. 变量类型:
内建变量:
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.*:存储在缓存空间中的缓存对象的属性;只读;
(obj.hits: 缓存命中计数器)
常用变量:
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
server.hostname
client.*
client.ip
用户自定义:
set
unset
—————————————————————————
示例1:强制对某类资源的请求不检查缓存:
vcl_recv {
if (req.url ~ "(?i)^/(login|admin)") {
return(pass);
}
}
—————————————————————————
示例2:对于特定类型的资源,例如公开的图片等,取消其私有标识,并强行设定其可以由
varnish缓存的时长;
sbu vcl_backend_response {
if (beresp.http.cache-control !~ "s-maxage") {
if (bereq.url ~ "(?i)\.(jpg|jpeg|png|gif|css|js)$") {
unset beresp.http.Set-Cookie;
set beresp.ttl = 3600s;
}
}
}
——————————————————————————–
6. 缓存对象的修剪:purge, ban
(1) 能执行purge操作
sub vcl_purge {
return (synth(200,"Purged"));
}
(2) 何时执行purge操作
sub vcl_recv {
if (req.method == "PURGE") {
return(purge);
}
…
}
7. 添加此类请求的访问控制法则:
acl purgers {
"127.0.0.0"/8;
"10.1.0.0"/16;
}
sub vcl_recv {
if (req.method == "PURGE") {
if (!client.ip ~ purgers) {
return(synth(405,"Purging not allowed for " + client.ip));
}
return(purge);
}
…
}
———————————————————————————–
8. 如何设定使用多个后端主机:
backend default {
.host = "172.16.100.6";
.port = "80";
}
backend appsrv {
.host = "172.16.100.7";
.port = "80";
}
sub vcl_recv {
if (req.url ~ "(?i)\.php$") {
set req.backend_hint = appsrv;
} else {
set req.backend_hint = default;
}
…
}
9. Director:后端服务器调度器
注意: 使用前需要导入:
import directors;
调度算法: 1.robin
2. random
示例:
import directors; # load the directors
backend server1 {
.host =
.port =
}
backend server2 {
.host =
.port =
}
sub vcl_init {
new GROUP_NAME = directors.round_robin();
GROUP_NAME.add_backend(server1);
GROUP_NAME.add_backend(server2);
}
sub vcl_recv {
# send all traffic to the bar director:
set req.backend_hint = GROUP_NAME.backend();
}
10. BE Health Check:
backend BE_NAME {
.host =
.port =
.probe = {
.url=
.timeout=
.interval=
.window=
.threshhold=
}
}
.probe:定义健康状态检测方法;
.url:检测时请求的URL,默认为”/";
.request:发出的具体请求;
.request =
"GET /.healthtest.html HTTP/1.1"
"Host: www.magedu.com"
"Connection: close"
.window:基于最近的多少次检查来判断其健康状态;
.threshhold:最近.window中定义的这么次检查中至有.threshhold定义的次数
是成功的;
.interval:检测频度;
.timeout:超时时长;
.expected_response:期望的响应码,默认为200;
健康状态检测的配置方式:
(1) 调用.probe 方式
probe PB_NAME = { }
#先定义probe检测方式
backend NAME = {
.probe = PB_NAME;
#调用刚定义的检测方式
…
}
#通过调用.probe方式来检测指定后端主机健康状态,可避免代码冗余
(2) 直接在对应后端主机配置中插入probe 配置
backend NAME {
.probe = {
…#直接在此处插入健康状态检测配置
}
}
示例:
probe check {
.url = "/.healthcheck.html ";
.window = 5;
.threshold = 4;
.interval = 2s;
.timeout = 1s;
}
backend default {
.host = "10.1.0.68";
.port = "80";
.probe = check;
}
backend appsrv {
.host = "10.1.0.69";
.port = "80";
.probe = check;
}
=======================================================
六. varnish的运行时参数:
1. 线程模型:
cache-worker
cache-main
ban lurker
acceptor:
epoll/kqueue:
…
2. 线程相关的参数:
在线程池内部,其每一个请求由一个线程来处理; 其worker线程的最大数决定了
varnish的并发响应能力;
thread_pools:Number of worker thread pools. 最好小于或等于CPU核心数量;
thread_pool_max:The maximum number of worker threads in each pool.
thread_pool_min:The minimum number of worker threads in each pool.
额外意义为“最大空闲线程数”;
最大并发连接数=thread_pools * thread_pool_max
thread_pool_timeout:Thread idle threshold. Threads in excess of
thread_pool_min, which have been idle for at least this long, will be
destroyed.
thread_pool_add_delay:Wait at least this long after creating a thread.
thread_pool_destroy_delay:Wait this long after destroying a thread.
设置方式:
vcl.param
永久有效的方法:
varnish.params
DEAMON_OPTS="-p PARAM1=VALUE -p PARAM2=VALUE"
3. varnish日志区域:
shared memory log
计数器
日志信息
1、varnishstat – Varnish Cache statistics
#可显示当前状态下的各种信息的实时信息,并会持续刷新
#也是一个各状态信息的即时统计计数器
-1 :只看某时刻的一个信息,非即时状态
-1 -f FILED_NAME #显示指定某字段的瞬时信息
-l:可用于-f选项指定的字段名称列表;
eg: varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss
2、varnishtop – Varnish log entry ranking
#根据数量最大,由高到低的方式排序来显示各参数
-1 Instead of a continously updated display, print the statistics once
and exit.
-i taglist,可以同时使用多个-i选项,也可以一个选项跟上多个标签;
-I <[taglist:]regex> #以正则表达式匹配方式显示匹配项目
-x taglist:排除列表 #不显示指定的项目
-X <[taglist:]regex>
3、varnishlog – Display Varnish logs
#以罗列各参数的形式显示日志信息
4、 varnishncsa – Display Varnish logs in Apache / NCSA combined log format
#以类似httpd中combined方式,显示日志信息
4. 内建函数:
hash_data():指明哈希计算的数据;减少差异,以提升命中率;
regsub(str,regex,sub):把str中被regex第一次匹配到字符串替换为sub;主要用于
URL Rewrite
regsuball(str,regex,sub):把str中被regex每一次匹配到字符串均替换为sub;
return():
ban(expression)
ban_url(regex):Bans所有的其URL可以被此处的regex匹配到的缓存对象;
synth(status,"STRING"):purge操作;
总结:
varnish: state engine, vcl
varnish 4.0:
vcl_init
vcl_recv
vcl_hash
vcl_hit
vcl_pass
vcl_miss
vcl_pipe
vcl_waiting
vcl_purge
vcl_deliver
vcl_synth
vcl_fini
vcl_backend_fetch
vcl_backend_response
vcl_backend_error
sub VCL_STATE_ENGINE
backend BE_NAME {}
probe PB_NAME {}
acl ACL_NAME {}
原创文章,作者:ldt195175108,如若转载,请注明出处:http://www.178linux.com/59971