Web Page Cache :
squid --> varnish
程序的运行具有局部性特征:
时间局部性:一个数据被访问过之后,可能很快会被再次访问人
空间局部性:一个数据被访问时,其周边的数据也有可能被访问到
cache:命中
热区:局部性
时效性:
缓存空间耗尽:LRU
过期:缓存清理
缓存命中率:hit/(hit+mlss)
(0.1)
页面命中率:基于页面数量进行衡量
字节命中率:基于页面的体积进行衡量
缓存与否:
私有数据:prlvate,prlvate cache;
公共数据:publlc, publlc or prlvate cache;
Cache-related Headers Fields
The most important caching header fields are:
Expires:过期时间;
Expires:Thu, 22 Oct 2026 06:34:30 GMT
Cache-control :max-age=
Etag
if-None-Match
Last-Modified
if-Modified-Since
Vary
Age
缓存有效性判断机制
过期时间: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
缓存层级:
私有缓存:用户代理附带的本地缓存机制;
公共缓存:反向代理服务器的缓存功能;
User-Agent <--> private cache <--> public cache <--> public cache 2 <--> Original Server
请求报文用于通知缓存服务如何使用缓存响应请求:
cache-request-directive =
"no-cache"
| "no-store"
| "max-age" "=" delta-seconds
| "max-stale"「"=" delta-seconds ]
| "min-fresh""=" delta-seconds
| "no-transform"
| "only-if-cached"
| cache-extension
响应报文用于通知缓存服务器如何存储上级服务器响应的内容:
cache-response-directive =
"public"
| "private" 「"=" <"> 1#field-name <"> ]
| "no-cache" ["="<"> 1#field-name<">],可缓存,但响应给客户端之前需要revalidatior
| "no-store",不允许存储响应内容于缓存中
| "no-transform"
| "must-revalidate"
| "proxy-revalidate"
| "max-age" "=" delta-seconds
| "s-maxage""=" delta-seconds
| cache-extension
开源解决方案:
squid :
varnish :
varnish官方站点: http://www.varnish-cache.org/
Community
Enterprise
This is Varnish cache, a high-performance HTTP accelerator.
程序架构:
Manager进程
Cacher进程,包含多种类型的线程:
accept, worker, expiry,...
shared memory log :
统计数据:计数器
日志区域:日志记录
varnishlog, varnishncsa, varhishstat.
配置接口:VCL
Varnish Confilguration Language,
vcl complier --> c complier --> shared object
varnish的程序环境:
/etc/varnish/varnish.params:配置varnish服务进程的工作特性,例如监听的地址和端口,缓存机制;
/etc/varnish/default.vcl:配置备Child/Cache线程的缓存策略;
主程序:
/usr/sbin/varnishd
CLI interface :
/usr/bin/varnishadm
Shared Memory Log交互工具:
/usr/bin/vainishhist
/usr/bin/varnishlog
/usr/bin/varnishncsa
/usr/bin/varnishstat
/usr/binv/arnishtop
测试工具程序:
/usr/bin/varnishtest
VCL配置文件重载程序:
/usr/sbin/varnish_reload_vcl
Systemd Unit File :
/usr/lib/systemd/system/varnish.service
varnish服务
/usr/lib/systemd/system/varnishlog.senvice
/usr/lib/systemd/system/varnishncsa.senvice
日志 持久的服务
varnish的缓存存储机制(Storage Types):
-s [name=]type[,options]
·malioc[.size]
内存存储,[,size]用于定义空间大小;重启后所有缓存项失效;
·file[,path[,size[,granularity]]]
磁盘文件存储,黑盒:重启后所有缓存项失效
·persistent,path,size
文件存储,黑盒;重启后所有缓存项有效;实验;
varnish程序的选项:
程序选项:/etc/varnish/varnish.params文件
-a address[:port][address[:port][...],默认为6081端口;
-T address[:port],默认为6082端口;
-s [name=]type[options],定义缓存存储机制;
-u user
-g group
-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
-S /etc/varnish/secret -T [ADDRESS:]PORT
help [<command>]
ping [<timestamp>]
auth <response>
quit
banner
status
start
stop
vcl.load <configname> <filename>
vcl.inline <configname> <quoted_VCLstring>
vcl.use sconfigname>
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_heaith <backend_expression> <state>
ban <field> <operator> <arg> [&& <field> <oper> <arg>]....
ban.list
配置文件相关:
vcl.list
vcl.load:装载,加载并编译;
vcl.use:激活;
vcl.discard:删除;
vcl.show [-v]<configname>:查看指定的配置文件的详细信息;
运行时参数:
param.show -l: 显示列表:
param.show <PARAM>
param.set <PARAM> <VALUE>
缓存存储:
storage.list
后端服务器:
backend.list
VCL :
"域“专有类型的配置语言;
state engine:状态引擎;
VCL有多个状态引擎,状态之间存在相关性,但状态引擎彼此间互相隔离;每个状态引擎可使用retumn(x)指明关联至哪个下一级引擎;每个状态引擎对应于v!文件中的一个配置段,即为subroutine
vcl_hash --> return(hit)--> vcl_hit
vcl_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 (rea.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);
}
Client Side :
vcl_recv, vcl_pass, vcl_hit, vcl_miss, vcl_pipe, vcl_purge, vcl_synth, vcl_deliver
vci_recv :
hash: vcl_hash
pass: vcl_pass
plpe: vcl pipe
synth: vcl_synth
purge: vcl_hash --> vcl_purge
vcl_hash :
lookup :
hit: vcl_hit
miss: vcl_miss
pass, hit_for_pass: vcl_pass
purge: vcl_purge
Backend Side :
vcl_backend_fetch,vcl_backend_response,vcl_backend_error
两个特殊的引擎:
vcl_init:在处理任何请求之前要执行的vcI代码:主要用于初始化VMODS;
vcl_fini:所有的请求都已经结束,在vcl配置被丢弃时调用;主要用于清理VMODS;
vcl的语法格式:
(1)VCL files start with vcl 4.0
(2)//,# and /* foo */ for comments;
(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); 用于实现状态引擎转换
(6)Domain-specific;
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;
三类主要语法:
sub subroutine {
.....
}
if CONDITION {
....
} else {
.....
}
return(), hash_data()
VCL Built-in Functlons and Keywords
函数:
regsub(str, regex, sub)
regsuball(str, regex, sub)
ban(boolean expression)
hash _data(input)
synthetic(str)
Keywords:
call subroutine , return(action),new ,set ,unset
操作符
==,!=,~, >, >=, <,<=
逻辑操作符: &&, | |, !
变量赋值: =
举例:obj.hits是内建变量,用于保存某缓存项的从缓存中命中的次数;
if (obj.hits>0) {
set resp.http.X-Cache ="HIT via" + server.ip;
} eise {
set resp.http.X-Cache ="MISS via" + server.ip;
}
变量类型:
内建变量:
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
server.hostname
client.*
client.ip
用户自定义:
set
unset
示例1:强制对某类资源的请求不检查缓存:
vcl_recv {
if (req.url ~ "(?i)^/(login | admin)") {
return(pass);
}
}
示例2:对于特定类型的资源,例如公开的图片等,取消其私有标识,并强行设定其可以由varnish缓存的时长:定义在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;
}
}
示例3:定义在vcl_recv中;
if (req.restarts == 0) {
if (req.http.X-Fowarded-For) {
set req.http.X-Forwarded-For = req.http.X-Forwarded-For + "," + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
}
缓存对象的修剪:purge, ban
(1)能执行purge操作
sub vcl_purge {
return (synth(200,"Purged"));
}
(2)何时执行purge操作
sub vcl_recv {
if (req.method =="PURGE") {
return(purge);
}
...
}
添加此类请求的访问控制法则:
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);
}
...
}
Banning :
(1)varnishadm :
ban <field> <operator> <arg>
示例:
ban req.url ~^/javascripts
(2)在配置文件中定义,使用ban()函数;
示例:
if (req.method =="BAN") {
ban("req.http.host == " + req.http.host + " && req.url == " + req.url);
# Throw a synthetic page so the request won't go to the backend.
return(synth(200,"Ban added"));
}
如何设定使用多个后端主机:
backend default {
.host = "192.168.0.104";
.port = "80”;
}
backend appsrv {
.host= "192.168.0.105";
.port="80";
}
sub vcl_recv {
if (req.url ~ "(?i)\.php$") {
set req.backend_hint=appsmy;
} else {
set req.backend_hint = default;
}
....
}
Director :
varnish module ;
使用前需要导入
import directors
示例:
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();
}
示例:
backend imgsrv1 {
.host = "192.168.0.110";
.port = "80";
}
backend imgsrv2 {
.host = "192.168.0.111";
.port = "80";
}
backend appsrv1 {
.host = "192.168.0.120";
.port = "80";
}
backend imgsrv1 {
.host = "192.168.0.121";
.port = "80";
}
sub vcl_init {
new imgsrvs = directors.random();
imgsrvs.add_backend(imgsrv1,10);
imgsrvs.add backend(imgsrv2,20);
new staticsrvs = directors.round robin();
appsrvs.add backend(appsrv1);
appsrvs.add_backend(appsrv2);
new appsrvs = directors.hash();
appsrvs.add backend(appsrv1,1);
appsrvs.add_backend(appsrv2,1);
}
sub vcl_recv {
if (req.url ~"(?i)\.(css | js)$" {
set req.backend_hint=staticsrvs.backend();
}
if (req.url ~"(?i)\.(jpg |jpeg |png |gif)$" {
set req.backend_hint=imgsrvs.backend();
} else {
set req.backend_hint = appsrvs.backend(req.http.cookie);
}
}
基于cookie的session sticky :
sub vcl_init {
new h = directors.hash();
h.add_backend(one,1); // backend 'one' with weight '1'
h.add backend(two,1); // backend 'two' with weight '1'
}
sub vcl_recv {
// pick a backend based on the cookie header of the client
set req.backend_hint = h.backend(req.http.cookie);
}
BE Health Check :
backend BE_NAME {
.host =
.port =
.probe = {
.url=
.timeout=
.interval=
.window=
.threshold=
}
}
.probe:定义健康状态检测方法:
.url:检测时要请求的URL,默认为"/";
.request:发出的具体请求:
.request =
"GET /.healthtest.html HTTP/1.1"
"Host: www.___.com"
"Connection: close"
.window:基于最近的多少次检查来判断其健康状态;
.threshold:最近.window中定义的这么次检查中至有.threshold定义的次数是成功的;
.interval:检测频度;
.timeout:超时时长:
.expected_response: 期望的响应码,默认为200;
健康状态检测的配置方式:
(1)probe PB_NAME {}
backend NAME ={
.probe =PB_NAME;
...
}
(2)backend NAME {
.probe = {
...
}
}
示例:
probe check {
.url = "/.healthcheck.html";
.window =5;
.threshold = 4;
.interval = 2s;
timeout = 1s;
}
backend default {
.host= "192.168.0.200";
.port = "80":
.probe = check;
}
backend appsrv {
.host= "192.168.0.201";
.port = "80":
.probe = check;
}
设置后端的主机属性:
backend BE_NAME {
....
.connect_timeout = 0.5s;
.first_byte_timeout = 20s;
.between_byte_timeout = 5s;
.max_connections = 50;
}
varnish的运行时参数:
线程模型:
cache-worker
cache-main
ban lurker
acceptor :
epoll/kqueue :
线程相关的参数:
在线程池内部,其每一个请求由一个线程来处理:其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 ofthread_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.
Timer相关的参数:
send_timeout : Send timeout for client connections. if the HTTP response hasn't been transmitted in this many seconds the session is closed.
timeout_idle : Idle timeout for client connections.
设置方式:
vcl.param
param.set
永久有效的方法:
varnish.params
DEAMON_OPTS="-P PARAM1=VALUE -P PARAM2=VALUE"
varnish日志区域:
shared memory log
计数器
日志信息
1、varnishstat -Varnish cache statistics
-1
-1 -f FILED_NAME
-1:可用于-f选项指定的字段名称列表;
MAIN.cache_hit
MAIN.cache_miss
# varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss
# varnishstat -1 -f MAIN -f MEMPOOL
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;