varnish原理精解

1、Varnish简介 html

2、Varnish特色web

3、Varnish系统结构正则表达式

4、Varnish日志算法

5、Varnish的算法编程

6、VCL介绍后端

7、Varnish后端存储浏览器

8、VCL内置函数缓存

9、VCL内置公用变量bash

10、Http与缓存相关的经常使用首部服务器


1、Varnish简介

Varnish是一款高性能且开源的反向代理服务器和HTTP缓存加速器;它 的做者Poul-Henning Kamp是FreeBSD的内核开发者之一,他认为如今的计算机比起1975年已经复杂许多。在1975年时,储存媒介只有两种:内存与硬盘。但如今计算机系统的内存除了主存外,还包括了CPU内的L一、L2,甚至有L3快取。硬盘上也有本身的快取装置,所以Squid Cache自行处理物件替换的架构不可能得知这些状况而作到最佳化,但操做系统能够得知这些状况,因此这部份的工做应该交给操做系统处理,这就是 Varnish cache设计架构。

2、Varnish特色

一、是基于内存缓存,重启后数据将消失
二、利用虚拟内存方式,io性能好
三、支持设置0~60秒内的精确缓存时间
四、VCL配置管理比较灵活
五、32位机器上缓存文件大小为最大2G
六、具备强大的管理功能,例如top,stat,admin,list等
七、状态机设计巧妙,结构清晰
八、利用二叉堆管理缓存文件,达到积极删除目的

3、Varnish系统结构

Varnish主要有两个进程:Management与Child进程(也称为Cache进程);以下图:

101020782.png

Management进程主要实现了应用新更新的配置,编译VCL配置、监控Varnish、初始化Varnish及提供一个管理接口等;Management进程会每隔一段时间检测一下Child进程是否运行正常,若是在指定的时间内没有响应则Memagement会重启Child进程

4、Varnish日志

为了与系统的其它部分进行交互,Child进程使用了能够经过文件系统接口进行访问的共享内存日志(shared memory log),所以,若是某线程须要记录信息,其仅须要持有一个锁,然后向共享内存中的某内存区域写入数据,再释放持有的锁便可。而为了减小竞争,每一个worker线程都使用了日志数据缓存。共享内存日志大小通常为90M,其分为两部分,前一部分为计数器,后半部分为客户端请求的数据。varnish提供了多个不一样的工具如varnishlog、varnishncsa或varnishstat等来分析共享内存日志中的信息并可以以指定的方式进行显示

5、Varnish的算法

Varnish的director支持的挑选方法中比较简单的有round-robin和random两种。其中,round-robin类型没有任何参数,只须要为其指定各后端主机便可,挑选方式为“轮叫”,并在某后端主机故障时再也不将其视做挑选对象;random方法随机从可用后端主机中进行挑选,每个后端主机都须要一个.weight参数以指定其权重,同时还能够director级别使用.retires参数来设定查找一个健康后端主机时的尝试次数。

2.1.0后,random挑选方法又多了两种变化形式client和hash。client类型的director使用client.identity做为挑选因子,这意味着client.identity相同的请求都将被发送至同一个后端主机。client.identity默认为cliet.ip,但也能够在VCL中将其修改成所须要的标识符。相似地,hash类型的director使用hash数据做为挑选因子,这意味着对同一个URL的请求将被发往同一个后端主机,其经常使用于多级缓存的场景中。然而,不管是client还hash,当其倾向于使用后端主机不可用时将会从新挑选新的后端其机。

6、VCL介绍

Varnish Configuration Language (VCL)是varnish配置缓存策略的工具,它是一种基于“域”(domain specific)的简单编程语言,可使用指定运算符:“=”,比较运算符“==”,逻辑运算符“!,&&,!!”等;支持使用正则表达式进行字符串匹配、容许用户使用set自定义变量、支持if判断语句,也有内置的函数和变量等;VCL策略在启用前,会由management进程将其转换为C代码,然后再由gcc编译器将C代码编译成二进制程序。编译完成后,management负责将其链接至varnish实例,即child进程

7、Varnish后端存储

varnish支持多种不一样类型的后端存储,这能够在varnishd启动时使用-s选项指定。后端存储的类型包括:

file:使用特定的文件存储所有的缓存数据,并经过操做系统的mmap()系统调用将整个缓存文件映射至内存区域(若是条件容许)
malloc:使用malloc()库调用在varnish启动时向操做系统申请指定大小的内存空间以存储缓存对象
persistent(experimental):与file的功能相同,但能够持久存储数据(即重启varnish数据时不会被清除);仍处于测试期

varnish没法追踪某缓存对象是否存入了缓存文件,从而也就无从得知磁盘上的缓存文件是否可用,所以,file存储方法在varnish中止或重启时会清除数据。而persistent方法的出现对此有了一个弥补,但persistent仍处于测试阶段,例如目前尚没法有效处理要缓存对象整体大小超出缓存空间的状况,因此,其仅适用于有着巨大缓存空间的场景。

选择使用合适的存储方式有助于提高系统性,从经验的角度来看,建议在内存空间足以存储全部的缓存对象时使用malloc的方法,反之,file存储将有着更好的性能的表现。然而,须要注意的是,varnishd实际上使用的空间比使用-s选项指定的缓存空间更大,通常说来,其须要为每一个缓存对象多使用差很少1K左右的存储空间,这意味着,对于100万个缓存对象的场景来讲,其使用的缓存空间将超出指定大小1G左右。另外,为了保存数据结构等,varnish自身也会占去不小的内存空间

为varnishd指定使用的缓存类型时,-s 选项可接受的参数格式以下:
malloc[,size] 或 file[,path[,size[,granularity]]] 或 persistent,path,size {experimental}

8、VCL内置函数

一、vcl_recv函数
用于接收和处理请求,当请求到达并成功接收后被调用,经过判断请求的数据来决定如何处理请求。
此函数通常以以下几个关键字结束:
pass:表示进入pass模式,把请求控制权交给vcl_pass函数。
pipe:表示进入pipe模式,把请求控制权交给vcl_pipe函数。
error code [reason]:表示返回“code”给客户端,并放弃处理该请求,“code”是错误标识,例如200、405等,“reason”是错误提示信息。
二、vcl_pipe函数
此函数在进入pipe模式时被调用,用于将请求直接传递至后端主机,在请求和返回的内容没有改变的状况下,将不变的内容返回给客户端,直到这个连接关闭
此函数通常以以下几个关键字结束:
error code [reason]
pipe
三、vcl_pass函数
此函数在进入pass模式时被调用,用于将请求直接传递至后端主机,后端主机应答数据后送给客户端,但不进行任何缓存,在当前链接下每次都返回最新的内容
此函数通常以以下几个关键字结束:
error code [reason]
pass
四、lookup
表示在缓存里查找被请求的对象,而且根据查找的结果把控制权交给函数vcl_hit或者函数vcl_miss
五、vcl_hit函数
在执行lookup指令后,若是在缓存中找到请求的内容,将自动调用该函数
此函数通常以以下几个关键字结束:
deliver:表示将找到的内容发送给客户端,并把控制权交给函数vcl_deliver
error code [reason]
pass
六、vcl_miss函数
在执行lookup指令后,若是没有在缓存中找到请求的内容时自动调用该方法,此函数能够用于判断是否须要从后端服务器取内容
此函数通常以以下几个关键字结束:
fetch:表示从后端获取请求的内容,并把控制权交给vcl_fetch函数
error code [reason]
pass
七、vcl_fetch函数
在从后端主机更新缓存而且获取内容后调用该方法,接着,经过判断获取的内容来决定是否将内容放入缓存,仍是直接返回给客户端
此函数通常以以下几个关键字结束:
error code [reason]
pass
deliver
八、vcl_deliver函数
在缓存中找到请求的内容后,发送给客户端前调用此方法。此函数通常以以下几个关键字结束:
error code [reason]
deliver
九、vcl_timeout 函数
此函数在缓存内容到期前调用。通常以以下几个关键字结束:
discard:表示从缓存中清除该内容。
fetch
十、vcl_discard函数
在缓存内容到期后或缓存空间不够时,自动调用该方法,通常以以下几个关键字结束:
keep:表示将内容继续保留在缓存中
discard

下面以一张VCL处理流程图来VCL函数介绍,对以上VCL函数有一个了解以后,再来看每一个函数之间是如何关联的:

153839933.png

处理过程大体分为以下几个步骤:

Receive 状态:

也就是请求处理的入口状态,根据VCL规则判断该请求应该是Pass或Pipe

或者进入Lookup(本地查询)

Lookup 状态: 进入此状态后,会在hash表中查找数据,若找到,则进入Hit状态,不然进入miss状态
Pass 状态: 在此状态下,会进入后端请求,即进入fetch状态
Fetch 状态: 在Fetch状态下,对请求进行后端的获取,发送请求,得到数据,并进行本地的存储
Deliver 状态: 将获取到的数据发送给客户端,而后完成本次请求

9、VCL内置公用变量

VCL内置的公用变量能够用在不一样的VCL函数中使用,根据这些公用变量使用的不一样阶段,以下介绍:

当请求到达后,可使用的公用变量以下所示:
公用变量名称 含义
req.backend 指定对应的后端主机
server.ip 表示服务器端IP
client.ip 表示客户端IP
req.request 指定请求的类型,例如GET、HEAD、POST等
req.url 指定请求的地址
req.proto 表示客户端发起请求的HTTP协议版本
req.http.header 表示对应请求中的http头部信息
req. restarts 表示请求重启的次数,默认最大值为4

Varnish 在向后端主机请求时,可使用的公用变量以下所示:
公用变量名称 含义
beresp.request 指定请求的类型,例如GET、HEAD等
beresp.url 指定请求的地址
beresp .proto 表示客户端发起请求的HTTP协议版本
beresp .http.header 表示对应请求中的http头部信息
beresp .ttl 表示缓存的生存周期,也就是cache保留多长时间,单位是秒

从cache或者后端主机获取内容后,可使用的公用变量以下所示:
公用变量名称 含义
obj.status 返回内容的请求状态代码,例如200、30二、504等
obj.cacheable

返回的内容是否能够缓存,也就是说,若是HTTP返回

是200、20三、300、30一、30二、40四、410等,而且有非0的生存期,则能够缓存

obj.valid 表示是不是有效的HTTP应答
obj.response 返回内容的请求状态信息
obj.proto 返回内容的HTTP协议版本
obj.ttl 返回内容的生存周期,也就是缓存时间,单位是秒
obj.lastuse 返回上一次请求到如今的间隔时间,单位是秒

对客户端应答时,可使用的公用变量以下所示
公用变量名称 含义
resp.status 返回客户端的HTTP状态代码
resp.proto 返回客户端的HTTP协议版本
resp.http.header 返回客户端的HTTP头部信息
resp.response 返回客户端的HTTP状态信息

上面主要介绍了一些经常使用的VCL内置公用变量,若是想要了解更多请查阅Varnish官方文档 查看文档


若是想要精确熟练的配置缓存,须要对Http协议有个详细了解,这里只介绍一些经常使用的与缓存相关的Http首部

10、Http与缓存相关的经常使用首部

Expires:指定WEB对象的过时时间,不宜设置缓存时间过长

Cache-Control:定义全部缓存机制必须遵循的缓存指示,包括以下一些指令:

max-age=[seconds]:执行缓存被认为是最新的最长时间。相似于过时时间,这个参数是基于请求时间的相对时间间隔,而不是绝对过时时间

s-maxage=[seconds]:相似于max-age属性,除了他应用于共享(如:代理服务器)缓存

public:响应被缓存,而且在多用户之间共享

no-cache:强制每次请求直接发送给源服务器,而不通过本地缓存

no-store:绝对禁止缓存,用于一些敏感数据

Must-revalidate:保证缓存的数据都是最新的,会到服务器端验证当前数据是否是最新的数据

proxy-revalidate:和must-revalidate相似,除了他只对缓存代理服务器起做用

Etag:响应首部,是实体标签(EntityTag)的缩写,用于在响应报文中为某web资源定义版本标识符

Last-Mofified:响应首部,用于回应客户端关于Last-Modified-Since或If-None-Match首部的请求,以通知客户端其请求的web对象最近的修改时间

If-Modified-Since:条件式请求首部,若是在此首部指定的时间后其请求的web内容发生了更改,则服务器响应更改后的内容,不然就响应304状态码(not modified);

If-None-Match:条件式请求首部;web服务器为某web内容定义了Etag首部,客户端请求时能获取并保存这个首部的值(即标签);然后在后续的请求中会经过If-None-Match首部附加其承认的标签列表并让服务器端检验其原始内容是否有能够与此列表中的某标签匹配的标签;若是有,则响应304,不然,则返回原始内容

Vary:响应首部,原始服务器根据请求来源的不一样响应的可能会有所不一样的首部,最经常使用的是Vary: Accept-Encoding,用于通知缓存机制其内容看起来可能不一样于用户请求时Accept-Encoding-header首部标识的编码格式

Age:缓存服务器能够发送的一个额外的响应首部,用于指定响应的有效期限;浏览器一般根据此首部决定内容的缓存时长;若是响应报文首部还使用了max-age指令,那么缓存的有效时长为“max-age减去Age”的结果

下面以实际请求与响应报文来介绍:

######打开百度的请求报文信息
----------------------------------------------------------------------
Request URL:http://www.baidu.com/        #请求的URL
Request Method:GET                       #请求方法
Status Code:200 OK                       #状态码
Request Headers    view source       
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 #通知服务器能够发送的类型
Accept-Encoding:gzip,deflate,sdch        #通知服务器能够发送的编码方式
Accept-Language:zh-CN,zh;q=0.8           #通知服务器能够发送的语言
Cache-Control:max-age=0                  #报文传送缓存指示
Connection:keep-alive                    #保持长链接状态
Cookie:BAIDUID=6CB063786195FA7025F715DDACDB9D32:FG=1; BDSVRTM=5; H_PS_PSSID=3524_2777_1464_3421_2975_3090_3501_3439  #Cookie,服务器存储在客户端的信息
Host:www.baidu.com                       #主机地址
Referer:http://baidu.com/        
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.76 Safari/537.36 #将发起请求的应和程序名称告知服务器,也就是浏览器

######打开百度的响应报文信息
----------------------------------------------------------------------
Response Headers    view source
BDPAGETYPE:1                     
BDQID:0xf06adb8c076aa3fa
BDUSERID:0
Cache-Control:private                  #缓存指示
Connection:Keep-Alive                  #状态为保持链接
Content-Encoding:gzip                  #对主体执行的编码方式为gzip
Content-Length:4386                    #响应主体内容的长度为4386个字节
Content-Type:text/html;charset=utf-8   #响应类型为HTML文本,编码类型为utf-8
Date:Sun, 06 Oct 2013 03:35:47 GMT     #响应的时间日期
Expires:Sun, 06 Oct 2013 03:35:47 GMT  #实体不在有效,要从原始的源端再次获取此实体的日期和时间
Server:BWS/1.0    #服务器应用程序软件的名称和版本 BWS/1.0
Set-Cookie:BDSVRTM=2; path=/    #设置cookie,path
Set-Cookie:H_PS_PSSID=3524_2777_1464_3421_2975_3090_3501_3439; path=/; domain=.baidu.com    #设置cookie,path,domain都是cookie的信息(做用范围等等)

到此,Varnish的基本原理已经讲清楚了,下一篇博客将会写Varnish的安装配置;敬请关注...

相关文章
相关标签/搜索