varnish缓存-介绍

varnish-简介

Varnish是一款高性能、开源的反向代理服务器和缓存服务器。Varnish使用内存缓存文件来减少响应时间和网络带宽消耗。这个项目是由挪威的一家报纸Verdens Gang的网络分支起始的,其架构设计和开发总监Poul-Henning Kamp是FreeBSD核心的开发人员之一,最初项目的管理与基础设施及额外开发由挪威一家Linux咨询公司Linpro提供。
说到varnish,squid就不得不提及。squid算得上是古老的缓存服务器。由于varnish先进的设计理念,性能要比squid高上许多,varnish还可以通过端口进行管理,使用正则语句做到清除指定缓存的功能,这些squid都做不到。但是varnish在高并发的情况下,资源消耗较高,而且varnish服务进程一旦崩溃,重启,内存中的缓存数据将全部丢失。

varnish程序架构

Manager进程(管理进程):负责Cacher加载文件,确保Cacher正常运行,更新和升级,编译VCL、监控varnish、初始化varnish等等
Cacher进程(缓存进程),包含多种类型的线程,如accept(接收), worker(处理), expiry(清理本地缓存)...

Cacher Process 功能:

  • 监听客户端请求
  • 管理worker 线程
  • 存储缓存数据
  • 记录流量日志
  • 根据统计更新计数器数值

shared memory log:统计数据:计数器;日志区域:日志记录,命中多少次,没命中多少次等等,大小80-90M,滚动来存储日志。

所有要认为再启动一个日志,来存储。

在日志记录方面,Cacher process 使用VSL 机制来处理,这是一个共享内存空间,可以有效减少记录阻塞。日志空间分为两个部分,分别记录格式化的请求日志,以及计数器数值。可以通过varnish自带log工具进行查看,分析或者永久存储日志。

VCC Process:把用户自定义的配置文件转成C代码,然后调用C语言编译器,编译成共享模块,被多个Cacher Process 加载使用,这种编程语言叫做VCL。

VCL:配置接口

vcl complier --> c complier --> shared object

Varnish Configuration Language (VCL)是varnish配置缓存策略的工具,用来描述请求处理和制定缓存策略,它是一种基于“域”(domain specific)的简单编程语言,它支持有限的算术运算和逻辑运算操作、允许使用正则表达式进行字符串匹配、允许用户使用set自定义变量、支持if判 断语句,也有内置的函数和变量等。使用VCL编写的缓存策略通常保存至.vcl文件中,其需要编译成二进制的格式后才能由varnish调用。事实上,整 个缓存策略就是由几个特定的子例程如vcl_recv、vcl_fetch等组成,它们分别在不同的位置(或时间)执行,如果没有事先为某个位置自定义子 例程,varnish将会执行默认的定义。

VCL策略在启用前,会由management进程将其转换为C代码,而后再由gcc编译器将C代码编译成二进制程序。编译完成 后,management负责将其连接至varnish实例,即child进程。正是由于编译工作在child进程之外完成,它避免了装载错误格式VCL 的风险。因此,varnish修改配置的开销非常小,其可以同时保有几份尚在引用的旧版本配置,也能够让新的配置即刻生效。编译后的旧版本配置通常在 varnish重启时才会被丢弃,如果需要手动清理,则可以使用varnishadm的vcl.discard命令完成。

想要写好vcl配置,需要了解varnish内部报文的处理流程,其核心关键词是 finite state machine——有限状态引擎。

varnishd:6081
varnishadm:6082

下图为简单的处理流程:

 

简述过程

1、首先客户端请求发来,接收到,接收到后5个钩子分析这个请求报文是不是标准的http请求报文,

请求方法:GET,PUT,POST,HEAD,DELETE,OPTIONS,TRACE

如果客户端发来的求情不是以上7个中的某一个,将用4层方式来处理,如果是将用7层方式来处理。

2、如果是7层报文,一般只缓存GET和HEAD这两中方法,下一个状态引擎分析是不是可缓存的,如果不是可缓存的直接去后端服务器取数据(在到达服务器之前有一个处理请求报文的)

3、如果是可查缓存的,有两种情况,命中与没有命中,如果没有命中,直接去后台服务器去数据

4、命中從缓存中取,在发给用户之前,可以更改请求报文,在发个客户端

备注:命中率取决于用那部分当键,如www.liuxiaosi.com.cn/log.jpg和www.liuxiaoosi.com.cn/log.jpg这里用log.jpg当键提高命中率

前端状态可分为四个阶段:

第一阶段:

vcl_recv     #接受客户端请求,进行判断

第二阶段:

vcl_hash   #进行hash计算,不进行判读处理,计算之后送往各个第三阶段状态引擎中

第三阶段:

vcl_hit        #缓存命中,到此处理

vcl_pass      #缓存跳过

vcl_miss      #缓存未命中

vcl_purge   #清理缓存

vcl_pipe       #对于无法识别的http首部请求直接送入管道,交由后端处理不再处理

第四阶段

vcl_deliver: 大部分响应客户端的请求由此发送回去

vcl_synth:接受来自vcl_purge的任务,对于指定的缓存,进行删除处理

后端状态分为两阶段:

第一阶段:

vcl_backend_fetch:接受来自前端状态vcl_pass或vcl_miss 的任务,向后端主机请求

第二阶段:

vcl_backend_response:接受到后端返回正常状态报文,进行是否缓存检查,需要缓存的响应将其缓存,不需要则不缓存,最后送到vcl_deliver

vcl_backend_error:后端主机错误,返回错误响应

除此之外还有两个特殊状态引擎:

vcl_init:在处理任何请求之前要执行的vcl代码:主要用于初始化VMODs;
vcl_fini:所有的请求都已经结束,在vcl配置被丢弃时调用;主要用于清理VMODs;

VCL语法

注意:varnish 4.0版本开始,vcl拥有自己的默认规则,它不可移除,总是追加在自定义的规则之后。

(1) vcl配置文件以 vcl 4.0 开头;
(2) C语言注释风格://, # and /* foo */ ;
(3) 子函数使用sub关键字声明, 例如sub vcl_recv { ...};
(4) 无循环, state-limited variables(受限于引擎的内建变量);
(5) 使用return(action)中断引擎状态,指向下一步处理,action为关键字 ,例如: return(pass);
(6) 可动态装载;

三类主要语法

sub subroutine {
...
}
if CONDITION {
...
} else {
...
}

return(), hash_data()

内建函数与关键字

函数:

hash_data():指明哈希计算的数据;减少差异,以提升命中率;

regsub(str,regex,sub):把str中被regex第一次匹配到字符串替换为sub;主要用于URL Rewrite

regsuball(str,regex,sub):把str中被regex每一次匹配到字符串均替换为sub;

return():

ban(expression)

ban_url(regex):Bans所有的其URL可以被此处的regex匹配到的缓存对象;

synth(status,"STRING"):purge操作;

关键字:

call subroutine, return(action),new,set,unset

操作符

==, !=, ~, >, >=, <, <=

逻辑操作符:&&, ||, !

变量赋值:=

举例:obj.hits是内建变量,用于保存某缓存项的从缓存中命中的次数;

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 from " + server.ip;
}

变量类型

内建变量

req.*:request,表示由客户端发来的请求报文相关;

req.http.*

req.http.User-Agent, req.http.Referer, ...

bereq.*:由varnish发往BE主机的httpd请求相关;

bereq.http.*

beresp.*:由BE主机响应给varnish的响应报文相关;

beresp.http.*

resp.*:由varnish响应给client相关;

obj.*:存储在缓存空间中的缓存对象的属性;只读;

常用变量:

bereq.*, req.*:
bereq.http.HEADERS
bereq.request:请求方法;
bereq.url:请求的url;
bereq.proto:请求的协议版本;
bereq.backend:指明要调用的后端主机;

req.url:请求的url
req.http.Cookie:客户端的请求报文中Cookie首部的值;
req.http.User-Agent:浏览器类型

beresp.*, resp.*:
beresp.http.HEADERS
beresp.status:响应的状态码;
reresp.proto:协议版本;
beresp.backend.name:BE主机的主机名;
beresp.ttl:BE主机响应的内容的余下的可缓存时长;

obj.*
obj.hits:此对象从缓存中命中的次数;
obj.ttl:对象的ttl值

server.*
server.ip:varnish主机的IP;
server.hostname:varnish主机的Hostname;
client.*
client.ip:发请求至varnish主机的客户端IP;

同时注意变量是受状态限制的,下图为可用表

 

 

 

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注