当前位置: 首页 > 工具软件 > varnish-agent > 使用案例 >

总结:varnish缓存总结

李华茂
2023-12-01

概念

  • 程序的运行具有局部性特征:
    • 时间局部性:一个数据被访问过之后,可能很快会被再次访问到;
    • 空间局部性:一个数据被访问时,其周边的数据也有可能被访问到

局部性;

  • 时效性:

    • 缓存空间耗尽:LRU,最近最少使用;

    • 过期:缓存清理

      缓存命中率:hit/(hit+miss)(0,1)
      页面命中率:基于页面数量进行衡量
      字节命中率:基于页面的体积进行衡量
      
  • 缓存与否:

    • 私有数据:private,private cache;
    • 公共数据:public, public or private cache;
  • 缓存有效性判断机制:

    • 过期时间:Expires
      HTTP/1.0
      Expires:过期
      HTTP/1.1
      Cache-Control: maxage=
      Cache-Control: s-maxage=
    • 条件式请求:
      Last-Modified/If-Modified-Since:基于文件的修改时间戳来判别;
      Etag/If-None-Match:基于文件的校验码来判别;
  • 缓存层级:

    • 私有缓存:用户代理附带的本地缓存机制;
    • 公共缓存:反向代理服务器的缓存功能;
  • 请求报文用于通知缓存服务如何使用缓存响应请求:
    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 <"> ],可缓存,但响应给客户端之前需要revalidation,即必须发出条件式请求进行缓存有效性验正;
    | “no-store” ,不允许存储响应内容于缓存中;
    | “no-transform”
    | “must-revalidate”
    | “proxy-revalidate”
    | “max-age” “=” delta-seconds
    | “s-maxage” “=” delta-seconds
    | cache-extension

安装varnish

Manager进程
	Cacher进程,包含多种类型的线程:
			accept, worker, expiry, ... 
	shared memory log:
			统计数据:计数器;
			日志区域:日志记录;
				varnishlog, varnishncsa, varnishstat... 
			
配置接口:VCL
	Varnish Configuration Language, 
		vcl complier --> c complier --> shared object 

varnish的缓存存储机制( Storage Types):
		-s [name=]type[,options]
		
		· malloc[,size]
			内存存储,[,size]用于定义空间大小;重启后所有缓存项失效;
		· file[,path[,size[,granularity]]]
			磁盘文件存储,黑盒;重启后所有缓存项失效;
		· persistent,path,size
			文件存储,黑盒;重启后所有缓存项有效;实验;
工作中一般使用磁盘储存(PCIE接口SSD)缓存
			
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:运行于前台;
[root@CentOS7 ~]# yum install varnish -y
[root@CentOS7 ~]# rpm -ql varnish
/etc/varnish/default.vcl      配置各Child/Cache线程的缓存策略
/etc/varnish/varnish.params   配置varnish服务进程的工作特性
/usr/bin/varnishlog           日志格式
/usr/bin/varnishncsa          日志格式(任选其一即可)
/usr/sbin/varnishd            主程序
/usr/bin/varnishadm             CLI interface
/usr/bin/varnishhist            Shared Memory Log交互工具
/usr/bin/varnishlog
/usr/bin/varnishncsa
/usr/bin/varnishstat
/usr/bin/varnishtop		
/usr/bin/varnishtest                          测试工具程序:
/usr/sbin/varnish_reload_vcl                  VCL配置文件重载程序:
/usr/lib/systemd/system/varnish.service       varnish服务
/usr/lib/systemd/system/varnishlog.service    日志持久的服务
/usr/lib/systemd/system/varnishncsa.service	


配置

[root@varnish ~]# vim /etc/varnish/varnish.params
VARNISH_LISTEN_PORT=80                   web端口为80
VARNISH_STORAGE="file,/data/varnish/cache,1G"   缓存位置及大小
[root@varnish ~]# mkdir -p /data/varnish/cache
[root@varnish ~]# chown -R varnish.varnish /data/varnish/cache/
[root@varnish ~]# ss -ntl

实验:配置后端服务器响应
配置文件相关:
			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 
[root@varnish ~]# vim /etc/varnish/default.vcl
backend default {
    .host = "192.168.8.27";                                                                          
    .port = "80";
}

[root@varnish ~]# varnish_reload_vcl    加载
实验:实现命中率提示
vim /etc/varnish/default.vcl
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;
				}
[root@varnish ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
Type 'help' for command list.
Type 'quit' to close CLI session.
··········
vcl.load test default.vcl       装载,加载并编译;       
200        
VCL compiled.
vcl.list                        列出所有
200        
active          0 boot          激活状态
available       0 test          可用

vcl.use test                    激活
200        
VCL 'test' now active
quit                            退出
500        

[root@CentOS7 ~]# curl -I 192.168.8.17    访问缓存服务器
X-Cache: Miss Via 192.168.8.17          第一次miss

[root@CentOS7 ~]# curl -I 192.168.8.17
X-Cache: Hit Via 192.168.8.17           第二种命中


实验:当访问admin或login时不查缓存
[root@web ~]# mkdir -p /var/www/html/{admin,login}
[root@web ~]# echo /var/www/html/admin/index.html >/var/www/html/admin/index.html
[root@web ~]# echo /var/www/html/login/index.html >/var/www/html/login/index.html
[root@client ~]# curl -I 192.168.8.17/admin/index.html
X-Cache: Hit Via 192.168.8.17      命中

[root@varnish ~]# vim /etc/varnish/default.vcl
sub vcl_recv {
        if (req.url ~ "(?i)^/(login|admin)"){
                return(pass);                                                                        
        }

[root@varnish ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082

vcl.load pass default.vcl

vcl.list

vcl.use pass

[root@client ~]# curl -I 192.168.8.17/login/index.html
X-Cache: Miss Via 192.168.8.17
[root@client ~]# curl -I 192.168.8.17/admin/index.html
X-Cache: Miss Via 192.168.8.17     配置后都没有命中


实验:使用curl不能访问
[root@varnish ~]# vim /etc/varnish/default.vcl
sub vcl_recv {
        if (req.http.User-Agent ~ "(?i)curl"){
                return(synth(403));                                                                    
        }
[root@varnish ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
vcl.load curl default.vcl
vcl.use curl


[root@client ~]# curl -I 192.168.8.17     curl禁止访问
HTTP/1.1 403 Forbidden

[root@client ~]# curl -I -A IE 192.168.8.17    IE可以访问
HTTP/1.1 200 OK 

实验:实现图片去除cookie
对于特定类型的资源,例如公开的图片等,取消其私有标识,并强行设定其可以由varnish缓存的时长
[root@web ~]# cp /usr/shafind /usr/share -iname "*.jpg" 
[root@web ~]# cp /usr/share/pixmaps/faces/yellow-rose.jpg /var/www/html/
[root@varnish ~]# vim /etc/varnish/default.vcl
sub vcl_backend_response {
        if (beresp.http.Cache-Control !~ "(?i)S-maxage") {
                if (bereq.url ~ "(?i)\.(jpg|jpeg|png|gif|css|js)"){
                        unset beresp.http.Set-Cookie;                                                
                        set beresp.ttl=3600s;
                }
        }

[root@varnish ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
vcl.use curl         激活其他

vcl.discard cookie    删除

vcl.load cookie default.vcl    加载编译

vcl.use cookie            激活


实验:后端服务器可以记录客户端IP
[root@varnish ~]# varnishadm -im /etc/varnish/default.vcl 

sub 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;
                        }
        }
}
[root@varnish ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082

vcl.load ip default.vcl

vcl.use ip


[root@web ~]# vim /etc/httpd/conf/httpd.conf     修改日志格式
    LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined    
[root@web ~]# systemctl restart httpd

[root@client ~]# curl -I -A IE 192.168.8.17/
[root@web ~]# cat /var/log/httpd/access_log
 192.168.8.7 - - [11/Aug/2020:13:59:49 +0800] "GET / HTTP/1.1" 200 7 "-" "IE" 
客户端IP显示              

NGINX修改
$http_x_forwarded_for

实验:临时删除缓存(curl发送purge)
[root@varnish ~]# vim /etc/varnish/default.vcl
sub vcl_purge {
        return (synth(200,"purged"));
}
sub vcl_recv {
        if (req.method == "PURGE"){                                                                                                                                                                             
[root@varnish ~]# systemctl start varnish

[root@CentOS7 ~]# curl -I 192.168.8.7      命中
X-Cache: Hit Via 192.168.8.7
[root@CentOS7 ~]# curl -X PURGE 192.168.8.7     发purge指令删除
[root@CentOS7 ~]# curl -I 192.168.8.7      miss
X-Cache: Miss Via 192.168.8.7
            
若别人知道发指令可以删除缓存,太危险,可以指定访问网段
[root@varnish ~]# vim /etc/varnish/default.vcl 
acl purgers {
        "127.0.0.0"/8;
        "192.168.8.0"/24;
}
sub vcl_purge {
        return (synth(200,"purged"));
}
sub vcl_recv {
        if (req.method == "PURGE"){
                if (!client.ip ~ purgers){                 不是该地址
                        return (synth(405, "Purging not allow for " + client.ip));                                                                                                                              
                }
                return (purge);
        }

[root@varnish ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
vcl.load test2 default.vcl

vcl.use test2
       
实验:临时删除缓存(ban)
[root@CentOS7 ~]# curl -I 192.168.8.7     hit
X-Cache: Hit Via 192.168.8.7

[root@varnish ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
ban req.url ~ /                           删除所有缓存

[root@CentOS7 ~]# curl -I 192.168.8.7     miss
X-Cache: Miss Via 192.168.8.7

[root@varnish ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
ban req.url ~ /  
ban req.url ~ ^/data         清理data目录下缓存
ban req.url ~ .js$           清理js结尾的缓存  
sub vcl_recv {
        if (req.method == "BAN") {
                ban("req.http.host == " + req.http.host + "&& req.url == " + req.url);                                                                                                                          
                return (synth(200,"Ban added"));
        }

[root@varnish ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
ban req.http.host == 192.168.8.7 && req.url == /      删除所有
ban req.http.host == 192.168.8.7 && req.url == /test/index.html   删除一个 

实验:实现后端多台服务器

实现cookie、图片、静态资源分开存放

[root@varnish ~]# vim /etc/varnish/default.vcl 
vcl 4.0;
import directors;                      #增加
# Default backend definition. Set this to point to your content server.
	backend imgsrv1 {
		.host = "192.168.10.11";
		.port = "80";
	}
	
	backend imgsrv2 {
		.host = "192.168.10.12";
		.port = "80";
	}	
	
	backend appsrv1 {
		.host = "192.168.10.21";
		.port = "80";
	}
	
	backend appsrv2 {
		.host = "192.168.10.22";
		.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);
		}
	}
[root@CentOS7 ~]# curl  192.168.8.7   
sorrysever
[root@CentOS7 ~]# curl -X PURGE 192.168.8.7     删除缓存,轮询访问后端服务器

[root@CentOS7 ~]# curl  192.168.8.7
192.168.8.107web1	
实验:后端服务器健康状态检查
.probe:定义健康状态检测方法;
	.url:检测时要请求的URL,默认为”/"; 
	.request:发出的具体请求;
		.request = 
			"GET /.healthtest.html HTTP/1.1"
			"Host: www.magedu.com"
			"Connection: close"
	.window:基于最近的多少次检查来判断其健康状态; 
	.threshold:最近.window中定义的这么次检查中至有.threshhold定义的次数是成功的;
	.interval:检测频度; 
	.timeout:超时时长;
	.expected_response:期望的响应码,默认为200;
vcl 4.0;
import directors;
# Default backend definition. Set this to point to your content server.
probe check {
        .url = "/index.html";
        .window = 5;
        .threshold = 4;
        .interval = 2s;
        .timeout = 1s;
}
backend default {
    .host = "192.168.8.37";
    .port = "80";
    .probe = check;
}
backend appsrv {
    .host = "192.168.8.27";
    .port = "80";
    .probe = check;
}

sub vcl_init {
    new www = directors.round_robin();
    www.add_backend(default);
    www.add_backend(appsrv);
}

[root@varnish ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
backend.list                查看(Healthy健康)
200        
Backend name                   Refs   Admin      Probe
default(192.168.8.37,,80)      7      probe      Healthy 5/5
appsrv(192.168.8.27,,80)       6      probe      Healthy 5/5
backend.list                查看(sick 出问题)
200        
Backend name                   Refs   Admin      Probe
default(192.168.8.37,,80)      7      probe      Healthy 5/5
appsrv(192.168.8.27,,80)       6      probe      Sick 0/5

backend.set_health appsrv healthy

配置:查看主机状态

  • 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 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.
      		
    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. 
      	timeout_req: Max time to receive clients request headers, measured from first non-white-space character to double CRNL.
      	cli_timeout:Timeout for the childs replies to CLI requests from the mgt_param.
      	
    设置方式:
      			vcl.param 
      			param.set
      		
    永久有效的方法:
      			varnish.params
      				DEAMON_OPTS="-p PARAM1=VALUE -p PARAM2=VALUE"
    
[root@varnish ~]# vim /etc/varnish/varnish.params 
DAEMON_OPTS="-p thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300"

varnishstat

[root@varnish ~]# varnishstat       列出前面的动态显示
[root@varnish ~]# varnishstat -1    显示一次所有
[root@varnish ~]# varnishstat -l    显示列表
[root@varnish ~]# varnishstat -1 -f LCK.mempool.locks    显示该列表一次
LCK.mempool.locks        75225         5.85 Lock Operations
[root@varnish ~]# varnishstat -f LCK.mempool.locks    动态显示该列表
[root@varnish ~]# varnishstat -f MAIN



[root@varnish ~]# varnishstat -f MAIN.cache_hit     命中
[root@varnish ~]# varnishstat -f MAIN.client_req    请求
[root@varnish ~]# varnishstat -f MAIN.threads       线程

命中率=命中/请求

varnishtop

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>
 类似资料: