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列表:
  1. # varnishadm vcl.list
  2. available 0 boot
  3. available 0 reload_2013-04-06T23:00:44
  4. available 0 reload_2013-04-06T23:00:47
  5. available 0 reload_2013-04-06T23:00:48
  6. active 0 reload_2013-04-06T23:00:49

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

  1. # varnishadm vcl.load full_vcl /usr/local/varnish/etc/varnish/full_fdfs.vcl
  2. # varnishadm vcl.list
  3. available 0 boot
  4. available 0 reload_2013-04-06T23:00:44
  5. available 0 reload_2013-04-06T23:00:47
  6. available 0 reload_2013-04-06T23:00:48
  7. active 0 reload_2013-04-06T23:00:49
  8. available 0 full_vcl
  9. # varnishadm vcl.use full_vcl

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

  1. # 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头,例如
    1. set req.http.User-Agent = "unknown";
    2. unset req.http.Range;
  7. VCL有if/else的条件语句,但没有循环语句;
  8. 支持include,加载配置文件,例如
    1. include "foo.vcl";
  9. 支持import,加载模块,例如
    1. import std;
    2. sub vcl_recv {
    3. std.log("foo");
    4. }

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

其中,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,
   
  1. import directors;
  2.  
  3. sub vcl_init {
  4. new vdir = directors.round_robin();
  5. vdir.add_backend(backend1);
  6. vdir.add_backend(backend2);
  7. }
  8.  
  9. sub vcl_recv {
  10. set req.backend_hint = vdir.backend();
  11. }
 
 

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

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. matlab建立双坐标

    (1)设定双Y坐标 x=0:0.1:2*pi; y1=sin(x); y2=cos(x); y3=1-sin(x); [AX]=plotyy(x,y1,x,y2); %双Y坐标的建立 hold on; ...

  2. 20135220谈愈敏Blog6_进程的描述和创建

    进程的描述和创建 谈愈敏 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.com/course/USTC-1000029000 进程 ...

  3. 将Mininet与真实网络相连接

    原文发表在我的博客主页,转载请注明出处 前言 Mininet是SDN网络仿真的一大利器,在小规模网络模拟使用上独领风骚,其开源性允许使用者按照自己的需求修改源码,得到想要的数据,其提供了多个函数用来满 ...

  4. Android应用程序模拟手机按键

    记得以前在做一个C++项目时,需要在某一步操作之后人为用代码模拟敲键盘上的回车键(Enter)效果. 出于好奇,这几天研究了一下Android中手机(或平板)上各种按键的键值.模拟方法及最终效果. 1 ...

  5. css的小三角实现的方式

    先上一个简单的例子哈: 此时的方向向下. 如果想方向向上的话用:border-top:0;border-bottom:4px solid; 1. width:0 height:0 border宽度,颜 ...

  6. C#中判断一个数组中是否存在某个数组值 及相关

    声明:reference:http://www.cnblogs.com/icebutterfly/archive/2010/06/22/1762738.html:http://blog.csdn.ne ...

  7. sql脚本比较大,sqlserver 无法导入,就用cmd命令执行

    osql简单用法:用来将本地脚本执行,适合sql脚本比较大点的情况,执行起来比较方便 1 osql -S serverIP -U sa -P 123 -i C:\script.sql serverIP ...

  8. use case

  9. 使用git管理代码的心得

    一.简易使用流程 首先下载安装git,点击Git Bash进入编辑界面,之后如下图进入目录并通过命令 git init 把这个目录变成git可以管理的仓库 接下来使用git add .命令将所有文件添 ...

  10. hdu1217 floyd

    floyd一遍即可.如果floyd后值有变大就是 #include<map> #include<string> #include<stdio.h> #include ...