WEB缓存系统之varnish状态引擎
前文我们聊了下varnish的VCL配置以及语法特点,怎样去编译加载varnish的vcl配置,以及命令行管理工具varnishadm怎么去连接varnish管理接口进行管理varnish,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/12626134.html;今天我们来说一下varnish的状态引擎;首先我们来回顾下iptables报文的走向,在iptables里报文的走向有三种,第一种是从别的主机发送过来的报文,首先它会到达网卡,然后进入prerouting链,然后经过路由决策后,如果是发往本机的,则就走input链,从而把报文送给本机上的应用程序;第二种是从prerouting链通过路由决策后,不是发往本机的报文而是发往其他主机,通过本机转发的,它会从prerouting链到forward链,然后从postrouting链把报文发送给其他主机;第三种是从本机发往其他主机的报文,它的报文走向是从output链到postrouting链,然后从网卡发送出去;我们说iptables的原因是类比varnish的状态引擎;varnish的状态引擎就类似iptables里的这5链;我们写的vcl配置就相当于iptables里的规则;他俩有个共同点就是在每个链上的规则只对当前链上的表或者被自定义链引用才会生效,而varnish里的状态引擎也是同样的逻辑,我们写的vcl配置只对当前状态引擎生效,不同的状态引擎处有着不同的意义,对其他状态引擎互不干扰;这样描述相信大家对varnish的状态引擎有了初步的概念,这也是我们在上一篇文中说到的,发送给客户端的响应报文,为什么要配置在vcl_deliver里,而不是其他位置;接下来我们看看varnish的状态引擎;
提示:以上这张图上varnish4.0的状态引擎图,每个状态引擎彼此的关系,以及varnish内部缓存处理逻辑;首先当varnish服务器收到来自客户端的请求报文,最先到达的状态引擎是vcl_recv,我们可以在vcl_recv里面对客户端的请求报文做修改,或者其他操作,然后交给vcl_hash这个状态引擎,这个状态引擎主要是看是否可查缓存,如果可以查缓存,会判断是否命中,命中就交给vcl_hit处理,vcl_hit处理后,就直接交给vcl_deliver处理,最后响应给客户端,当然缓存命中后也可以将请求交给vcl_pass处理;如果vcl_hash处理后不能查缓存,就把报文发送给vcl_miss处理,意思是不能查缓存,或者缓存未能命中;当然我们也可以直接把报文交给vcl_pass处理;即便它可以被缓存命中,我们也是可以强行让该请求不查缓存,直接交给vcl_pass处理或者vcl_miss直接交给vcl_backend_fatch处理;vcl_backend_fetch就是去后端真正的服务器上取对应资源,然后它会对后端服务器的响应报文头部进行读的操作,如果没有什么错误,就把响应报文发送给vcl_backend_response,vcl_backend_response在处理响应报文时,会判断是否可缓存,如果可以缓存,就在本地缓存一份,然后通过vcl_deliver响应给客户端,如果不可缓存,在本地就不缓存,直接将响应报文发送给vcl_deliver响应给客户端;如果vcl_backend_fetch读后端服务器发来的响应报文是错误响应(或者vcl_backend_fatch未取到对应资源,或者后端主机宕机等等),它就会把该处理逻辑交给vcl_backend_error处理;如果用户的请求经过vcl_hash处理后,发现缓存内容变了或者说缓存过期了需要修剪缓存,它会把请求发往vcl_purge,vcl_purge主要处理缓存修剪相关的操作,然后把请求报文发送给vcl_synth处理,合成一响应发送给客户端;如果通过vcl_hash处理后发现用户请求的方法我们压根就不认识,这个时候会将请求报文交给vcl_pipe处理;
从上面的图来看,我们大概可以总结为两点,varnish的状态引擎分前端工作线程或者客户端状态引擎和后端工作线程或者服务端状态引擎;客户端状态引擎,主要处理客户端请求和响应相关的处理,比如是否可查缓存,是否命中,是否修剪缓存,是否识别用户请求的方法有或者直接交给vcl_pass,又或者说怎样响应客户端等等,可以看到客户端状态引擎vcl_pass,是一个额外处理机制,不管是否可查缓存,是否命中,都可以交给它处理;对于服务端状态引擎主要是处理和后端服务器请求和响应相关操作,比如怎样去后端服务器取资源,对服务器的响应报文是否可缓存,怎么缓存,对后端服务器的响应报文错误怎么处理等;
varnish的前端状态引擎有vcl_recv,vcl_pass, vcl_hit, vcl_miss, vcl_pipe, vcl_purge, vcl_synth, vcl_deliver;vcl_recv处理后可以通过return来指定下一跳处理的状态引擎是那个,如果是return(hash)就表示交给vcl_hash处理;return(pass)就表示交给vcl_pass处理;return(pipe)就表示交给vcl_pipe处理;return(synth)就表示交给vcl_synth处理;return(purge)就表示交给vcl_purge处理;对于vcl_hash来说,return(hit)就表示缓存命中交给vcl_hit处理,return(miss)表示缓存未能命中交给vcl_miss处理,return(pass)或者return(hit_for_pass)就表示即便缓存命中也交给vcl_pass处理,return(purge)就表示交给vcl_purge处理;
varnish的后端状态引擎有vcl_backend_fetch, vcl_backend_response, vcl_backend_error;vcl_backend_fetch处理去后端取资源的操作,vcl_backend_response处理后端服务器响应回来的报文,vcl_backend_error处理后端服务器错误;除此以外varinsh4.0还有两个特殊的状态引擎,分别是vcl_init和vcl_fini;vcl_init:在处理任何请求之前要执行的vcl代码:主要用于初始化VMODs;vcl_fini:所有的请求都已经结束,在vcl配置被丢弃时调用;主要用于清理VMODs;
了解了上面的状态引擎,我们在说一说varnish的变量,在前文我们大概说了下varnish的变量大概可以分5类,一类是客户端请求报文相关的,req.*;一类是varnish服务器请求后端服务器报文,bereq.*;一类是后端服务器响应varnish服务器的beresp.*;一类是varnish服务器响应客户端的resp.*;还有一类是obj.*,这类变量主要是储存缓存空间中的缓存对象的属性;结合上面说的状态引擎,不难里接在不同的状态引擎里,对应变量是有限的,比如bereq.*这类变量就不能用于vcl_recv,因为vcl_recv是接收用户请求相关的,而bereq.* 是varnish请求后端服务器的变量,这两者很明显是不再一个级别的,所以通常不同类的变量对应能够用于哪些状态引擎中是有限制的;而对应变量的属性也是有要求的,比如obj.hit这个变量是存储缓存项命中次数的,通常可用在vcl_hit和vcl_deliver状态引擎中,表示应用缓存命中次数,相对于这个变量来说,我们是不能修改的,所以obj.hits这个变量在vcl_hit和vcl_deliver状态引擎中只可读,不可修改;而对于obj.ttl这个值就不一样了;obj.ttl记录缓存项可缓存的时间;很显然obj.ttl这个变量只能用于可缓存的状态引擎上,比如vcl_hit,对于告诉客户端可缓存的时间,很明显它不能是一个不可修改的值;所以对于obj.ttl这个变量在vcl_hit状态引擎中就具有可读可写权限(即我们可以修改该变量的值);说这么多无外乎就是表达一个意思,不同类型的变量受限状态引擎,不同变量在不同的状态引擎上不是都可读可写,有的变量只可读;如下图
说明:以上这张表就是对于不同类型的变量对应varnish的状态引擎是否可读写的,没有读写就表示该类型变量不能用于对应状态引擎中;比如resp.*只能在error和deliver状态引擎中使用;beresp.*这类变量只能用于后端主机响应varnish服务器的过程中使用,比如fetch这个状态引擎就是处理后端服务器响应varnish服务器请求的;所以beresp.*这类变量只能用于fetch;当然这里的fetch是早期状态引擎的名称。在varnish4.0它不叫fetch,而叫vcl_backend_fatch;
了解了以上内容,我们接下来看几个示例
示例:强制对某类资源的请求不检查缓存
提示:以上配置表示对客户端请求的url进行判断,如果能够被.jpg、.jpeg、.png、.gif、.js、.css、.html匹配到,那么就把用户请求交给pass状态引擎处理;pass状态引擎处理就是不查缓存;所以对于客户端请求.jpg的资源,其对应obj.hits的值会一直为0;因为我们明确指定了不查缓存;
测试:用浏览器访问服务器上的.jpg资源,看看响应报文中我们自定义的X-Cache 首部是否是 miss via 192.168.0.99;
提示:可以看到我们访问/day.jpg这个资源时,不管怎么刷新浏览器,对应响应首部X-Cache的值都是 miss via 192.168.0.99,说明我们请求.jpg的资源的确没有查缓存;
示例:把客户端IP传到后端服务器
提示:以上vcl表示判断客户端请求首部X-Forwarded-For是否为空,如果不为空就把它的值在原有的值的基础上和客户端ip地址做字符串连接,并用逗号隔开;如果该首部为空或者没有这个首部就把这个首部的值设置成客户端ip地址;
更改后端web 服务的日志格式
提示:以上配置表示在日志格式中应用X-Forwarded-For这个首部的值;
测试:重新编译加载vcl,然后用浏览器访问,看看是否能够把浏览器所在主机的ip地址传到后端httpd服务器日志中做记录?
提示:从上面的日志结果看,我们分别用不同的浏览器去访问,在日志中可以看到不同浏览器所在主机的IP地址,说明我们通过判断用户请求报文X-Forwarded-For首部是否为空,从而实现对于非空和空值对应设置该首部值,继而实现把对应请求首部值记录到后端服务器日志中的目的;
示例:对于特定类型的资源,例如公开的图片等,取消其私有标识,并强行设定其可以由varnish缓存的时长;
提示:首先我们要清楚在那个位置去对报文操作,取消私有标识,是需要在后端服务器响应varnish这个过程中把对应响应首部的值给撤销了;所以我们需要在vcl_backend_response这个状态引擎中来设置,取消set-cookie首部,这个首部主要是给对应客户端设置一个cookie;以上配置表示判断后端服务器响应varnish服务器的响应报文首部cache-control的值是否匹配“s-maxage”,如果不匹配说明该资源不允许被共有缓存系统所缓存,如果匹配,则说明该资源允许被公有缓存系统所缓存;如果不匹配再继续判断varnish向后端请求的首部url的值是否匹配.jpg|jpeg|png|gif|css|js结尾的资源,如果匹配则取消后端服务器响应varnish服务器的响应首部set-cookie的值,并设置后端服务器响应varnish的资源缓存时长为1小时;简单讲就是判断后端服务器响应首部的cache-control的值是否匹配到“s-maxage”,如果不能匹配到在判断向后端服务器请求的首部url是否是匹配指定结尾的资源,如果是,就取消后端服务器响应首部set-cookie这个首部,同时把后端服务器响应资源的缓存时长设定为1小时;
测试:为了验证以上vcl配置正确性,我们把beresp.ttl的值通过cache-control这个首部传递到浏览器响应首部,从而来判断set-cookie首部是被撤销了;
提示:在上面的配置中加入了set beresp.http.cache-control = beresp.ttl;表示把后端响应给varnish的响应首部beresp.ttl的值 通过beresp.http.cache-control首部保存;这样客户端访问.jpg的资源就会在响应首部中把cache-control的值给显示出来,如果该值是我们设置的3600s,就说明我们撤销set-cookie这个首部的vcl语句是生效的;
提示:从上面的结果看,cache-control的值为3600是我们设置beresp.ttl的值;说明撤销set-cookie的vcl配置生效了;同时这也告诉我们如果后端服务器响应varnish的报文中没有的首部,在varnish响应客户端中就没有;简单说就是varnish会把后端服务器响应给varnish中首部的值通过响应客户端首部传递出来;比如我在后端响应报文中自定义一个aaa的报文首部,其值为bbb,那么在客户端的响应报文首部中就会有对应aaa首部和对应的值;如下
测试:
提示:做以上测试需要考虑varnish上的缓存,如果你始终访问同一个url可能会看到对应首部的值不会发生变化,需要重启varnish或者换个其他符合vcl定义的url去访问试试看;
WEB缓存系统之varnish状态引擎的更多相关文章
- WEB缓存系统之varnish代理以及健康状态检测配置
前文我们聊了下varnish的缓存项修剪配置,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/12666406.html:今天我来说一下varnish作为代理服务 ...
- WEB缓存系统之varnish基础入门(一)
前文我们聊了下http协议里的缓存控制机制以及varnish架构组件介绍,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/12620538.html:今天我们来聊 ...
- WEB缓存系统之varnish缓存项修剪
前文我们聊了下varnish的状态引擎和不同类型的变量对应该使用在那个状态引擎中,以及每个状态引擎的对应处理事务:回顾请参考https://www.cnblogs.com/qiuhom-1874/p/ ...
- varnish状态引擎1
vcl: state engine:各引擎之间存一定程度上的相关性:前一个engine如果可以有多种下游engine,则上游engine需要用return指明 要转移的下游engine vcl_rec ...
- varnish状态引擎2
如何让varnish支持虚拟主机: if (req.http.host = "www.nihao.com") { } 强制对某资源的请求,不检查缓存: 上图表示以/test1.ht ...
- 浅谈web缓存(转)
这是一篇知识性的文档,主要目的是为了让Web缓存相关概念更容易被开发者理解并应用于实际的应用环境中.为了简要起见,某些实现方面的细节被简化或省略了.如果你更关心细节实现则完全不必耐心看完本文,后面参考 ...
- Web缓存加速指南(转载)
这是一篇知识性的文档,主要目的是为了让Web缓存相关概念更容易被开发者理解并应用于实际的应用环境中.为了简要起见,某些实现方面的细节被简化或省略了.如果你更关心细节实现则完全不必耐心看完本文,后面参考 ...
- [转载]WEB缓存技术概述
[原文地址]http://www.hbjjrb.com/Jishu/ASP/201110/319372.html 引言 WWW是互联网上最受欢迎的应用之一,其快速增长造成网络拥塞和服务器超载,导致客户 ...
- 项目实战5—企业级缓存系统varnish应用与实战
企业级缓存系统varnish应用与实战 环境背景:随着公司业务快速发展,公司的电子商务平台已经聚集了很多的忠实粉丝,公司也拿到了投资,这时老板想通过一场类似双十一的活动,进行一场大的促销,届时会有非常 ...
随机推荐
- Python读取和写入文件
1 从文件中读取数据 1.1 读取整个文件 创建名为test的txt文本文件,添加内容如下所示: 123456789023456789013456789012 实现代码: with open('tes ...
- JavaScript对象(二)
Part One:对象的三个特性 原型(prototype) 类(class) 可扩展性(extensible attribute) 1,b.isPrototypeOf(o) //判断b是不是o的 ...
- oracle 10g 搭建备库以及一次DG GAP的处理情况
1.主庫全庫備份rman target/rman> backup database format '/backup/fullbak/fullbak_%U';2.用scp傳到備庫,最好是rman目 ...
- # 爬虫连载系列(1)--爬取猫眼电影Top100
前言 学习python有一段时间了,之前一直忙于学习数据分析,耽搁了原本计划的博客更新.趁着这段空闲时间,打算开始更新一个爬虫系列.内容大致包括:使用正则表达式.xpath.BeautifulSoup ...
- 网址封锁的几种方法 公司把 pan.baidu.com 封了 研究实现原理
HTTP 和 HTTPS 协议HTTP 协议在 头部会发送 host 就是要访问的域名,可以用来被检测. HTTPS 协议虽然会加密全部通讯,但是在握手之前还是明文传输.有证书特证可被检测. 1, D ...
- Spring Boot从入门到精通(九)整合Spring Data JPA应用框架
JPA是什么? JPA全称Java Persistence API,是Sun官方提出的Java持久化规范.是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中. ...
- 【.net core】电商平台升级之微服务架构应用实战
一.前言 这篇文章本来是继续分享IdentityServer4 的相关文章,由于之前有博友问我关于微服务相关的问题,我就先跳过IdentityServer4的分享,进行微服务相关的技术学习和分享.微服 ...
- C#窗体排列方式
2020-03-11 每日一例第3天 1.设置父窗体属性:IsMdicontainer设置成true; 2.拖入menustrip控件,修改标题栏中的text文字. 3.点击“加载子窗体”设置代码: ...
- C++ 回调函数,拷贝文件
#include <iostream> #include <windows.h> using namespace std; unsigned long long transla ...
- 通过极简模拟框架让你了解ASP.NET Core MVC框架的设计与实现[上篇]
<200行代码,7个对象--让你了解ASP.NET Core框架的本质>让很多读者对ASP.NET Core管道有了真实的了解.在过去很长一段时间中,有很多人私信给我:能否按照相同的方式分 ...