Varnish 4.0 简介

Varnish 是一款开源的HTTP加速器和反向代理服务器,它的主要特点有:

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

与Squid服务器相比,Varnish的优点包括:

1、稳定性很高。两者在完成相同负荷的工作时,Squid服务器发生故障的几率要高于Varnish,因为Squid需要经常重启。

2、访问速度更快。采用了“Visual Page Cache”技术,所有缓存数据都直接从内存读取;而Squid是从硬盘读取缓存数据,因此Varnish在访问速度方面会更快。

3、支持更多的并发连接。因为Varnish的TCP连接释放要比Squid快,所以在高并发连接情况下可以支持更多的TCP连接。

4、可以通过管理端口,使用正则表达式批量清除部分缓存,而Squid做不到。

缺点也有:

1、在高并发状态下CPU、I/O和内存等资源开销都高于Squid。
2、进程一旦挂起、崩溃或者重启,缓存数据都会从内存中完全释放,此时所有请求都会被发送到后端服务器,在高并发情况下,这会给后端服务器造成很大压力。

varnish 安装:
wget http://repo.varnish-cache.org/source/varnish-4.0.0.tar.gz
tar -zxvf varnish-4.0.0.tar.gz
cd varnish-4.0.0
./autogen.sh
./configure --prefix=/usr/local/varnish
 
varnish 运行:
varnishd -f default.vcl -s malloc,1024m -T 127.0.0.1:200 -a 0.0.0.0:80
 
其中,-f 指定VCL 配置文件,-s 指定内存分配类型和大小,-T 指定文本管理接口, -a 指定服务监听IP和端口;
 
 
 

架构

 
 
Varnish主要有两个进程:管理进程(management)和子进程(child):
管理进程提供了VCL编译、进程监控、进程初始化、命令行接口等功能,我们可以通过终端或者CLI接口访问管理进程:
  • 管理进程会定期检查child进程的状态,如果child进程发生异常会被重启,并将错误日志写入syslog;
  • 管理进程会解析VCL并转化为C语言,然后由C编译器(如gcc)来编译,编译后的VCL会被链接到正在运行的Varnish实例;

编译后的VCL文件一直被保留直到重启Varnish或通过管理客户端的vcl.discard命令丢弃它。在Varnish不停止运行的情况下,可通过管理客户端重新加载VCL配置,新VLC的缓存策略会立即生效,如下面的例子:

查看当前Varnish实例的可用vcl列表:
# varnishadm vcl.list
available 0 boot
available 0 reload_2013-04-06T23:00:44
available 0 reload_2013-04-06T23:00:47
available 0 reload_2013-04-06T23:00:48
active 0 reload_2013-04-06T23:00:49

编译一个新的vcl,并加载使用:

# varnishadm vcl.load full_vcl /usr/local/varnish/etc/varnish/full_fdfs.vcl
# varnishadm vcl.list
available 0 boot
available 0 reload_2013-04-06T23:00:44
available 0 reload_2013-04-06T23:00:47
available 0 reload_2013-04-06T23:00:48
active 0 reload_2013-04-06T23:00:49
available 0 full_vcl
# varnishadm vcl.use full_vcl

丢弃一个名为”reload_2013-04-06T23:00:44″ 的vcl配置:

# varnishadm vcl.discard reload_2013-04-06T23:00:44
 
child进程包含了若干不同类型的线程:
线程名称 线程数目 任务
acceptor 线程 1个 接收新连接
cache-worker 线程 每个会话(活动连接)一个 处理请求
cache-main 线程 1个 用于Varnish启动
expiry 线程 1个 将旧内容从缓存中移除
ban lurker 线程 1个 清除bans
epoll/kqueue 线程 可配置,默认为2个 管理线程池
backend 探测线程 每个后端探测有一个 健康检查
 
 

Varnish支持几种方式来给缓存分配空间:

  • malloc存储方式,使用malloc 分配整个预设缓存大小的内存,Linux通过使用swap将不能装载到内存的数据存储到磁盘;
  • file存储方式,在文件系统上创建一个文件去包含整个缓存,并通过mmap将整个文件映射到内存中,即file方式实际上也是使用内存去缓存数据;
  • persistent(仍在试验中),类似file存储方式,是一种试验性的持久存储方式,它还没有很好解决空间全部消耗完的情况;

注意:选择存储方式的时候,如果内存足够大的话,最好选择malloc,这样可以让缓存全部或是大部分保存在内存中;

如果需要缓存的数据超过可用物理内存,可以选择file存储方式。但需要注意的是,在停止或重启Varnish的时候,file存储的方式不会保留数据。使用file存储方式,Varnish不会记录哪些数据写入到磁盘,哪些没有写入,因此不可能知道磁盘上的缓存是否可用,它仅仅是随机数据,如果使用file存储方式的话,Varnish不会重新使用旧的缓存。

 
child进程使用共享内存记录日志,如果一个线程想要写日志,需要先对共享内存加锁,并在写完日志后释放锁。为了减少线程之间的锁竞争,每个线程还有一个自己的cache用于记录日志。共享日志文件大小一般是80MB,并且被分成2份,一份是计数器,另一份是请求数据,为了解析日志,Varnish提供了一些工具,比如varnishlog等。
 
 

VCL

VCL(varnish configuration language)是varnish配置语言,在执行VCL时,varnish会把其转换成二进制代码。
 
VCL语法特点
  1. 块是由花括号分隔,语句以分号结束,使用 '#' 添加注释;
  2. VCL支持以下运算符:=(赋值),==(对比),~(匹配),!(否定),&&(逻辑与),||(逻辑或);
  3. 在VCL中,有三个重要的数据结构req(client request)、bereq(backend request)、beresp(backend response)和obj(cache object);
  4. 两个字符串的连接,它们之间没有任何运算符;
  5. VCL没有用户自定义的变量,但可以使用set关键字设置变量值,例如set beresp.ttl=5d;
  6. 使用set关键字设置http头,使用unset关键字移除http头,例如
    set req.http.User-Agent = "unknown";
    unset req.http.Range;
  7. VCL有if/else的条件语句,但没有循环语句;
  8. 支持include,加载配置文件,例如
    include "foo.vcl";
  9. 支持import,加载模块,例如
  10. import std;
    sub vcl_recv {
    std.log("foo");
    }

 
定义backend
 
probe healthcheck {
.url = "/test.jpg"; # 定义健康检查的页面
.interval = 6s; # 探测请求的发送周期,默认为5s
.timeout = 0.3 s; # 每次探测请求的过期时长,默认为2s
.window = ; # 设定在判定后端主机健康状态时基于最近多少次的探测进行,默认为8
.threshold = ; # 在.window中指定的次数中,至少有多少次是成功的才判定后端主机正健康运行,默认为3
.initial = ; # Varnish启动时对后端主机至少需要多少次的成功探测,默认同.threshold
}
backend default {
.host = "127.0.0.1";
.port = "";
   .probe = healthcheck;
   .host_header = "www.example.com";
.connect_timeout = 60s;
.first_byte_timeout = 60s;
.between_bytes_timeout = 60s;
.max_connections = ;
}

其中,host选项是必须显式赋值的,其它选项都可选;

如果host是动态域名(而非IP),Varnish会报错:resolves to too many addresses,解决办法可以参考这里

VCL可以把多个backends聚合成一个组(director),当组里有一个backend挂掉后,可以把流量导入其他健康的backend;
director可以采用不同的算法选择backend:
  1. random,根据设置的权值(.weight参数)来选择backend;
  2. round-robin,轮询;
  3. client,根据client.identity来选择backend,可以设置client.identity的值为session cookie来标识backend;
  4. hash,
  5. dns,
   
import directors;

sub vcl_init {
new vdir = directors.round_robin();
vdir.add_backend(backend1);
vdir.add_backend(backend2);
} sub vcl_recv {
set req.backend_hint = vdir.backend();
}
 
 

定义ACL(Access Control List)
 
ACL用于定义Varnish的访问控制机制。
 
acl localnetwork {
"localhost"; # myself
"192.0.2.0"/; # and everyone on the local network
! "192.0.2.23"; # except for the dial-in router
}
if (client.ip ~ localnetwork) {
return (pipe);
}
 
 
 

VCL 代码流程
 
 
 
  • vcl_recv,用于接收和处理请求,当请求到达并成功接收后被调用,vcl_recv中的数据结构主要是req。
  • vcl_fetch,获取backend响应后调用该方法,通过判断获取的内容来决定是将内容放入缓存,还是直接返回给客户端,vcl_fetch的主要数据结构是beresp;该函数在4.0版本已分解为下面两个函数:
    • vcl_backend_fetch,向后端主机发送请求前,调用此函数,可修改发往后端的请求;
    • vcl_backend_response ,获得后端主机的响应后,可调用此函数;
  • vcl_pipe,将请求直接传递至backend;
  • vcl_pass,将请求直接传递至backend,并将backend的响应发送给客户端,但不进行任何缓存,在当前连接下每次都返回最新的内容;
  • vcl_hash,设置文件索引的key;
  • vcl_deliver,将在缓存中找到的请求的内容发送给客户端前调用此方法;
  • vcl_hit,执行lookup指令后,在缓存中找到请求的内容将自动调用该函数;
  • vcl_miss,执行lookup指令后,在缓存中没有找到请求的内容将自动调用该函数,此函数可用于判断是否需要从backend获取内容;
  • vcl_error,出现错误时调用此函数;

VCL 动作(Actions)

  1. pass,把请求控制权交给vcl_pass函数;
  2. lookup,在缓存中查找被请求的对象,并根据查找的结果把控制权交给函数vcl_hit或vcl_miss;
  3. pipe,把请求控制权交给vcl_pipe函数;
  4. deliver,将在缓存中找到的内容发送给客户端,并把控制权交给函数vcl_deliver;
  5. esi,ESI-process,
  6. error code [reason],返回code给客户端,并放弃处理该请求;

pipe与pass的区别

当 vcl_recv 函数接收到请求时,有三种情况 :

  • 调用 pass 函数,从后端服务器调用数据;
  • 调用 pipe 函数,建立客户端和后端服务器之间的直接连接,从后端服务器调用数据;
  • 调用lookup函数,从缓存中查找应答数据并返回,如果查找不到,则调用pass函数从后端服务器调用数据。

pass和pipe都从后端服务器取数据,那么它们之间有什么不同呢?

pass是将当前请求直接转发到后端服务器,而后续的请求仍然通过varnish处理。 例如,建立了HTTP连接之后,客户端顺序请求 a.css 、b.png两个文件,“当前请求” 指的是第一个请求,即a.css,a.css被直接转发到后端服务器,不被缓存。而后续的b.png则再由varnish来做处理,varnish会判断b.png 如何处理。
而pipe模式则不一样,它会在客户端和服务器之间建立一条直接的连接,之后客户端的所有请求都直接发送给服务器,绕过varnish,不再由varnish检查请求,直到连接断开。


VCL公共变量

 
请求到达varnish时:
req.backend_hint        指定对应的后端主机
server.ip           表示服务器 IP
client.ip           表示客户端 IP
req.quest          只是请求的类型,例如 GET、HEAD 等
req.url            指定请求的地址
req.proto          表示客户端发起请求的 HTTP 协议版本
req.http.header       表示对应请求中的头,例如req.http.cookie
req.restarts         表示重启次数,默认最大值为 4
 
 
varnish向backend发送请求时:
beresp.requset       指定请求类型,例如 GET、HEAD 等
beresp.url          表示请求地址
beresp.proto         表示客户端发起请求的 HTTP 协议版本
beresp.http.header      表示对应请求中 HTTP 头部信息
beresp.ttl           表示缓存的生存周期,cache 保留时间(s)
 
 
backend获取内容时:
obj.status       返回内容的请求状态码,例如 200、302、504 等
obj.cacheable     返回的内容是否可以缓存
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 头部状态

varnish4.0简介的更多相关文章

  1. varnish4.0缓存代理配置

    防伪码:你必须非常努力,才能看起来毫不费力. 一.varnish原理: 1)Varnish简介: varnish缓存是web应用加速器,同时也作为http反向缓存代理.你可以安装varnish在任何h ...

  2. IOS 网络浅析-(十一 三方 AFNetworking3.0简介)

    AFNetworking3.0是目前最新的版本,本来打算介绍一下2.6,但是想想2.6名不久矣,就决定不介绍了,有兴趣的小伙伴可以上网查一查.下面我就开始进入正题了. 目前使用人数最多的第三方网络库, ...

  3. 编译安装 varnish-4.1.2和yum 安装 varnish-4.0.3

    vanish可以让用户自己选择缓存数据是存于内存还是硬盘,存于内存一般基于二八法则即常访问的数据是磁盘存储的总数据五分之一,因此内存也应该是硬盘文件大概五分之一.如果有多台vanish则,总内存满足即 ...

  4. 流风ASP.NET框架商业版-工作流1.0简介

    流风ASP.NET框架商业版-工作流1.0简介 工作流简介 在流风ASP.NET框架商业版1.0推出后,就有集成工作流的想法,但是由于工作繁忙和其他事情的耽搁,时隔半年之久工作流1.0的版本才姗姗来迟 ...

  5. .NET Core 1.0、ASP.NET Core 1.0和EF Core 1.0简介

    .NET Core 1.0.ASP.NET Core 1.0和EF Core 1.0简介 英文原文:Reintroducing .NET Core 1.0, ASP.NET Core 1.0, and ...

  6. 一个RtspServer的设计与实现和RTSP2.0简介

    一个RtspServer的设计与实现和RTSP2.0简介   前段时间着手实现了一个RTSP Server,能够正常实现多路RTSP流的直播播放,因项目需要,只做了对H.264和AAC编码的支持,但是 ...

  7. Identity Server 4 预备知识 -- OAuth 2.0 简介

    OAuth 2.0 简介 OAuth有一些定义: OAuth 2.0是一个委托协议, 它可以让那些控制资源的人允许某个应用以代表他们来访问他们控制的资源, 注意是代表这些人, 而不是假冒或模仿这些人. ...

  8. 第64节:Java中的Spring Boot 2.0简介笔记

    Java中的Spring Boot 2.0简介笔记 spring boot简介 依赖java8的运行环境 多模块项目 打包和运行 spring boot是由spring framework构建的,sp ...

  9. ElasticSearch 5.0 简介

    参考:http://blog.csdn.net/wzhg0508/article/details/52063676 Elasticsearch 5.0 简介(medcl微信直播实录) 大家好,非常高兴 ...

随机推荐

  1. Sublime 将 Tab 转为空格

    最近在使用 vue-cli 搭建项目,但每次用 Hbuilder 编写 vue 文件的时候,如果存在<script>部分就会报错,错误信息大意是说空格有问题.仔细研究了之后才知道,这是因为 ...

  2. Git基础 - git blame

    当想知道一段代码历史上有哪些人修改时,可以使用git blame查看,正如其名,当你看到那段让你抓狂的代码时,一定想找出是谁写的来一顿blame吧 : ) 使用方法 icebug@localhost: ...

  3. Quartz.net打造信息抽取器

    由于最近的一个项目需要定时抽取特定XML信息,然后保存到数据库,最后通过WebApi把手机端要使用的方法给暴露出来,所以去研究了一下Quartz.net.由于项目很小,我没用到Autofac,Repo ...

  4. [CareerCup] 2.6 Linked List Cycle 单链表中的环

    2.6 Given a circular linked list, implement an algorithm which returns the node at the beginning of ...

  5. LeetCode 笔记26 Maximum Product Subarray

    Find the contiguous subarray within an array (containing at least one number) which has the largest ...

  6. 20135316王剑桥 linux第五周课实验笔记

    4.1.1程序员的可见的状态 ———— Y86的每条指令都会读取或修改处理器状态的某些部分,称为程序员可见状态.如图1所示. 1.程序寄存器(Program registers): %eax, %ec ...

  7. (转)shell实例手册

    原文地址:http://hi.baidu.com/quanzhou722/item/f4a4f3c9eb37f02d46d5c0d9 实在是太好的资料了,不得不转 shell实例手册 0说明{ 手册制 ...

  8. UEditor编辑文章出现多余空行问题的解决办法

    网站后台管理编辑文章以后,保存.再次打开编辑是文章前后多出多余的空行.一直以为是编辑器有问题,也没在意,但是自己编辑文章多了,感觉太麻烦了.想一定可以解决这个问题.百度一下果然找到原因.原来是加载编辑 ...

  9. 最新微信小程序(应用号)视频教程,实战教程

    1.1课程介绍,定个小目标            http://v.youku.com/v_show/id_XMTc2NzIwNDk1Ng==.html 1.2开发文档简读,了解全貌       ht ...

  10. css限制图片大小,避免页面撑爆

    /*==========限制图片大小======避免页面撑暴========*/img { max-width:100%;width:expression(width>669?"100 ...