varnish
首先介绍缓存系统:
程序运行的两种逻辑:1.运行在单个主机
2.协同运行在不同主机(1.横向切 2.纵向切---->1.只负责一个层次 2.只负责整体功能的一小部分功能)
服务器扩展方式:1.向上(scale up)
2.向外(scale out):一个业务可以分割成多个小业务独立完成
http协议是各种主流程序中最常用的协议
用户与web server之间的通信:有请求和响应过程。应用程序运行产生的结果是数据,将数据美化,需要将数据的展示接口加以定义,即需要前端设计的css,js等工具处理,形成一个个的文件,有些在客户端加载完后可以直接被浏览器上解析,有些需要执行引擎运行。
后端开发包括gsp、php等,前端开发有js等,js作为程序,不是在服务器端运行以后,将结果直接展示给客户端,而是作为静态文件,直接响应给客户端,由客户端自身执行,得出结果--------------------------------------------------------因此,需要在服务器端运行的称为动态,与之相反的称为静态,静态资源可以原封不动的返回给客户端。
web服务器页面有众多资源组成,每个资源对于浏览器来讲都需要单独请求,浏览器需要多次请求才能将资源加载到本地,服务器对应有多次响应,而客户端只有一个,所以请求与客户端不是一一对应的关系。
缓存的类型:
1.代理式缓存:缓存器代表客户端去寻找资源
2.旁挂式缓存:若缓存器无法找到资源,客户端需自行寻找资源
代理缓存分为:正向代理与反向代理
1.正向代理:代表客户端发请求
2.反向代理:代表服务器端提供服务
varnish:反向代理服务器,其中缓存功能强大,varnish之前的缓存软件是squid
varnish工作在客户端与Web服务器之间,有时还会用到nginx作为调度器:
首先调度器接入用户请求,这一层称为接入层;然后是缓存器,这一层为缓存层;之后是处理业务的业务层,业务层分为两种类型:1.执行动态内容 2.响应静态内容
对于协议层,http协议有请求报文和响应报文,通过协议首部来组织协议事物,比如告知服务器不能用缓存来响应用户;协议首部可以控制缓存的工作机制。
浏览器缓存叫做private cache(私有缓存);中间的代理服务器缓存叫做public cache
缓存系统对Web服务有两类工作逻辑:
1.过期机制:服务器通知客户端缓存能用多长时间,这段时间内,客户端不会向服务器发送请求,而是从缓存服务器中获取内容,期间一旦服务器更新内容,客户端无法得知,会继续使用旧内容。另一种情况:原始内容没有更新,但缓存过期了,客户端还需要向服务器发请求
2.条件式缓存:解决过期缓存的问题。客户端第一次发请求,将服务器响应的数据缓存下来,再次使用时,会向服务器发请求,验证缓存内容是否变化,如果内容没有变化就用304来响应,告知客户端内容没有变化,如果发生变化,就响应200,正常响应(没变告知没变,变化则响应新内容)
服务端判断内容是否发生变化的方式:
1.文件最近一次修改的时间戳
2.扩展标签(Etag):服务器响应的内容会打一个随机码,当作标签来使用,更新内容后会再打一个新的随机码
为了减小服务器的压力,两种机制可以结合使用(过期机制与条件式缓存)
以上的工作机制是通过请求与响应报文的首部来实现:
过期机制的首部:
Expires:定义过期时间,缺陷是使用绝对时间(精确到秒),而全球的主机有时间偏差
所以http1.1版本引入了新的缓存首部:
cache-control:可以告知缓存系统如何进行缓存(指明缓存可以是私有还是公有,指明缓存时间,并且使用相对时间)
程序的运行具有局部性特征,才能使用缓存:
时间局部性:一个数据被访问过之后,可能很快会被再次访问到;
空间局部性:一个数据被访问时,其周边的数据也有可能被访问到;
程序运行的局部性使得数据有--热区,热区有局部性特征:经常访问的数据加载到缓存中,不经常被访问的冷数据放在服务器上。
当缓存空间已满,就需要清理缓存:
1.使用算法LRU:最近最少使用算法
2.缓存过期:对过期的缓存进行清理
但缓存过期不意味者原始数据的变化,进行清理会导致误伤。所以衡量缓存是否有效的指标是-----缓存命中率:
缓存命中率:hit/(hit+miss)(命中次数除以访问总次数)
页面命中率:基于页面数量进行衡量
字节命中率:基于页面的体积进行衡量
缓存与否:
私有数据:private,private cache;(浏览器缓存)
公共数据:public, public or private cache;(缓存服务器缓存)
有关缓存的几类报文首部:
Expires:过期时间;
Expires:Thu, 22 Oct 2026 06:34:30 GMT
Cache-Control:max-age=
Etag
If-None-Match
Last-Modified
If-Modified-Since
能够实现cache-control首部的相关属性:
1.用于请求报文首部的:ctrl+F5是强行刷新,意味着不从缓存中获取内容,相当于在请求报文中加一个首部,绕过缓存,去请求原始内容。
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
2.用于响应报文首部的:
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
用于Web Page Cache的两个工具:
squid(上一代产品,在重大并发压力下可以稳定运行)
varnish(新产品,重大并发压力下不稳定)
varnish两个版本:
Community社区版
Enterprise有图形化管理工具
varnish的工作进程:
Manager进程(主进程)
Cacher进程,包含多种类型的线程:accept, worker, expiry, ...
shared memory log(共享内存日志)结构:该日志直接记录到内存中
统计数据:计数器;记录收到多少次请求,命中多少次等
日志区域:日志记录;记录请求发生的时间。(有固定大小的区域记录日志内容,一旦填满就会将最早的信息覆盖掉)
varnish的程序架构图:
主进程还可以加载缓存控制的配置文件,而配置文件是通过VCL语言编程实现的。VCL是域类型的配置语言,即有些配置项只能用于某个位置,配置项的作用域。但VCL语言最终要转为c语言,c语言再进行编译,变为c模块,被子进程装载使用
varnish的作用位置:
响应客户端请求的有专用线程(worker threads),与服务器通信也有专用线程(backend communication)。可以看出,varnish需要有两个网卡,一个连接内网,一个连接外网。
实验:
两台虚拟机,67地址当varnish(node 1),68地址当http server(node 2)
1.安装服务
2.协调主机进行通信时,要将主机时间同步
3.安装varnish,其中4.0的版本已被收入epel源。安装方式:官方网站下载安装;epel源安装
4.为web服务提供测试页
也可以同时生成多个测试页:
5.启动http服务:
测试
6.查看varnish安装后生成的文件:
其中,reload_vcl是一次完成两个语言编译并重新模块装载的工具
varnish有两类配置:
1.配置进程:varnish params
2.配置缓存系统与VCL语言:default vcl
/etc/varnish/varnish.params: 配置varnish服务进程的工作特性,例如监听的地址和端口,缓存机制;
/etc/varnish/default.vcl:配置各Child/Cache线程的缓存策略;
客户端命令行接口:
/usr/bin/varnishadm
Shared Memory Log交互工具:
/usr/bin/varnishhist
/usr/bin/varnishlog
/usr/bin/varnishncsa
/usr/bin/varnishstat
/usr/bin/varnishtop
测试工具程序:
/usr/bin/varnishtest
VCL配置文件重载程序:
/usr/sbin/varnish_reload_vcl
/usr/lib/systemd/system/varnish.service varnish服务
/usr/lib/systemd/system/varnishlog.service 日志服务(为防止覆盖掉早期信息,需要启动服务将信息同步到磁盘)
/usr/lib/systemd/system/varnishncsa.service 以另一种方式启动日志(日志的格式)
builtin.vcl文件内容:有许多sub子例程
vcl是域配置语言,每一个sub的作用是定义一个域:
varnish4.0逻辑:
上图适用于前端线程,即客户端请求,其中:
1.vcl_pass:无论请求是否命中的第二种处理方法,例如命中时不响应,由pass处理转发到后端服务器
2.vcl_purge:缓存清理的方法之一。
如果缓存的内容与元数据不符,并响应给用户,同时响应给用户不能缓存的直接获取的元数据,则整个响应内容就会混乱,此时,需要介入外力强行清理缓存。缓存清理的方法有两种:
(1)purge:请求内容在缓存中命中,则缓存继续生效,如果未命中,则失效,即清理缓存。
(2)ban机制:可以自定义正则表达式模式,匹配到模式的内容禁止从缓存中响应,要从元数据获取,然后再次进行缓存,覆盖之前的缓存内容,达到清理缓存的效果。
3.vcl_pipe:不能缓存的请求,直接与后端联系。两种情况:
(1)正常的http协议请求,但是其中只有get和head可以缓存,其他的method都不能缓存
(2)非http协议的请求
上图适用于向服务器发送请求,其中:
vcl_synth:负责清理缓存,之前的vcl_purge用来监控是否有清理缓存权限
以上两图中,椭圆形的代表子例程,即域,也叫状态引擎。
查看VCL配置文件:
其中,sub内容为空,但不代表没有定义内容,而是有默认内容,即builtin文件(内建文件)
查看varnish进程自己的配置文件:
params配置文件内容都可以通过命令行选项来定义:
通过环境配置文件(params)来定义一些变量让用户能够通过某些接口来改动命令行选项中的选项值或者选项本身。
配置文件中定义的**文件:跨主机登录时,客户端、服务器都需要有**进行认证;生成域共享**。
varnish_storage定义了缓存的机制,使用malloc,并定义内存使用256M空间。
缓存项分为两部分:键与值;键放在内存中,值放在磁盘中,二者通过哈希映射。
varnish的缓存机制有两种:基于内存(这里是指值也放在内存中)----malloc
基于磁盘 ------file
基于内存意味着,缓存在内存中需要分配内存空间;这里jemalloc是并发的能完成内存分配的系统调用,类似-------malloc,它表示值存放在内存中。缺点:缓存在内存会产生大量的内存碎片,影响系统性能,所以内存的缓存空间不宜过大。
基于磁盘是指将缓存以文件的方式放在磁盘上,但是是将整个缓存项做成黑盒,里面有高效机制来组织缓存数据如何被使用,但是如果varnish进程重启,黑盒缓存就会消失,而现在的服务高依赖于缓存,缓存被破坏,后端服务器就会崩溃,因此生产中不能随意重启服务。