一、Varnish是用来干什么的?
varnish是web服务器的加速器,用来提高客户访问web服务器的速度; 它被安装在web服务器之前,可以缓存web服务器的应用程序和数据,并且可以响应客户端的web请求。 其功能与Squid服务器相似,都可以用来做HTTP缓存。
与Squid不同之处在于,Squid是将访问内容缓存到硬盘文件中,然后从硬盘读取缓存的数据,而Varnish把数据缓存到内存空间中,进而直接从内存中读取要访问的内容,避免了频繁的在内存、磁盘中交换文件。所以Varnish要相对更高效,但它也有缺点,内存中的缓存在服务器重启后会丢失,不易保存。
二、搭建Varnish 服务器要了解的知识:
1)、 Varnish服务器启动的的初始化过程:
varnish启动会产生两个进程:master进程 和 child进程,如下图,第一个是master进程,第二个是child进程。
master进程:master进程负责varnish服务的启动工作;master进程会读取配置文件,根据指定的配置信息做出相应的动作,例如管理员在配置文件中分配了2G内存大小,它就会在内存中创建2G的存储空间; master进程还会创建并管理child进程。
child进程: child进程来处理后续任务,它会分配一些线程来执行不同的工作,例如:(1) 接受http请求 (2)为缓存对象分配存储空间 (3)清除过期缓存对象(4)释放空间 碎片整理
2) 分配缓存过程:
当有一个对象需要缓存时,根据这个对象的大小,到空闲缓存区中查找大小最适合的空闲块,找到后就把这个对象放进去;
如果这个对象没有填满这个空闲块,就把剩余的空间做为一个新的空闲块; 如果空闲缓存区中没地方了,就要先删除一部分缓存来腾出地方,删除是根据最近最少使用原则。
3) 释放缓存过程:
有一个线程会负责缓存的释放工作。他定期检查缓存中所有对象的生存周期,如果某个对象在指定的时间段内没有被访问,就把这个对象删除,释放其占用的缓存空间; 释放空间后,检查一下临近的内存空间是否是空闲的,如果是,就整合为一个更大的空闲块,实现空间碎片的整理。(实验证明有点问题,缓存的内容,无论在指定时间内有没有被访问,生存周期到了都会被释放)
4)VCL(varnish configuration Langage)语言:
(1) VCL的基本概念:
VCL语言被使用在default.vcl这个文件中,用来设置varnish服务器对后端web服务器加速的一些规则; vcl是一种区域配置语言。在执行vcl时,varnish会将vcl语言转化未二进制代码; default.vcl文件中的vcl语言被分为多个子程序, 不同的子程序在不同的时间点执行,比如有的子程序在接收到客户端请求时执行,有的子程序在接收到后端服务器的文件时执行。
(2) backend servers(后端服务器):
backend servers在配置文件中代表后端服务器,即实验中的web服务器; 后端服务器提供了varnish服务加速的内容,即后端服务器是varnish服务器进行缓存的目标。 在/etc/varnish/default.vcl文件中会配置匹配后端服务器的相关信息和规则,这些信息会指引varnish服务器去何处寻找缓存的内容。如下图配置:
(3) vcl_recv
前面说过vcl语言是一个区域型语言, 并且对于varnish服务来说,在default.vcl文件中的vcl语言被分为多个子程序;vcl_recv就是其中的一种子程序块。
vcl_recv子程序在请求的开始被调用,在接收、解析了客户端的请求后,该子程序会决定是否响应请求、怎么响应请求以及使用哪个后台服务器响应请求。
(4) vcl_fetch
vcl_fetch 在一个文件成功从后台获取后被调用,通常他的任务就是改变 responseheaders,触发 ESI 进程,在请求失败的时候轮询其他服务器。
在 vcl_fetch 中一样的包含请求的 object,req,available,他们通常是 backendresponse,beresp。beresp 将会包含后端服务器的 HTTP 的头信息。
5) varnish的工作流程:
varnish处理客户请求的工作过程如下图 :
pass:当一个请求被 pass 后,这个请求将通过 varnish 转发到后端服务器,但是它不会被缓存。pass 可以放在 vcl_recv 和 vcl_fetch 中。
lookup:当一个请求在 vcl_recv 中被 lookup 后,varnish 将从缓存中提取数据,如果缓存中没有数据,将被设置为 pass,不能在 vcl_fetch 中设置 lookup。
pipe:pipe 和 pass 相似,都要访问后端服务器,不过当进入 pipe 模式后,在此连接未关闭前,后续的所有请求都发到后端服务器。
deliver:请求的目标被缓存,然后发送给客户端。
下面以一个例子说明请求的过程:
当客户端访问varnish服务器时,处理过程大致分为如下几个步骤:
(1) 客户端请求varnish动作: curl www.room.com
(2) varnish服务器的一个线程一直在侦听本机的80端口,此时收到客户端请求的动作,将其交给Receive线程。
(3)Receive ,也就是请求处理的入口状态,根据 VCL 规则判断该请求应该是 Pass 或Pipe,或者进入 Lookup(本地查询)。
(4)Lookup 状态,进入此状态后,会在 hash 表中查找数据,若找到,则进入 Hit 状态,否则进入 miss 状态。
(5)Pass 状态,在此状态下,会进入后端请求,即进入 fetch 状态。
(6)Fetch 状态,在 Fetch 状态下,对请求进行后端的获取,发送请求,获得数据,并进行本地的存储。
(7)Deliver 状态,将获取到的数据发送给客户端,然后完成本次请求。
6)varnish服务中的3个重要数据结构:
req:客户端请求的目标,当 varnish 接收到一个请求,这时 req object 就被创建了,你在 vcl_recv 中的大部分工作,都是在 req object 上展开的。
beresp:后端服务器返回的目标,它包含返回的头信息,你在 vcl_fetch 中的大部分工作都是在 beresp object 上开展的。
obj:被 cache 的目标,只读的目标被保存于内存中,obj.ttl 的值可修改,其他的只能读。
7) 两个varnish服务器上的监控命令:
在这之前先放一张图,使我们能够对监控信息进行阅读:
(1) varnishlog:
在客户端请求之前查看日志记录:
在客户端做出访问varnish服务器的请求:
这时在观察,发现日志已经有了访问过程的记录:
(2) varnishtop:
客户端做出动作:
varnish服务器的监控画面: