Varnish的简介
Varnish使用内存缓存文件来减少响应时间和网络带宽消耗。这个项目是由挪威的一家报纸 Verdens Gang 的网络分支起始的,其架构设计和开发总监Poul-Henning Kamp 是FreeBSD 核心的开发人员之一,最初项目的管理与基础设施及额外开发由挪威一家Linux咨询公司 Linpro提供。
说到varnish,squid 就不得不提及。squid 算得上是古老的缓存服务器。由于varnish先进的设计理念,性能要比squid高上许多Verdens Gang使用3台Varnish代替了原来的12台Squid,性能比以前更好。,varnish还可以通过端口进行管理,使用正则语句做到清除指定缓存的功能,这些squid都做不到。但是varnish在高并发的情况下,资源消耗较高,而且varnish服务进程一旦崩溃,重启,内存中的缓存数据将全部丢失。
1 设计架构
1.1Management进程
Management进程主要实现应用新的配置、编译VCL、监控varnish、初始化varnish以及提供一个命令行接口等。Management进程会每隔几秒钟探测一下Child进程以判断其是否正常运行,如果在指定的时长内未得到Child进程的回应,Management将会重启此Child进程。
管理的接口
CLI interface :命令行接口
Telnet interface :telnet接口
Web interface :Web管理接口
1.2 Cacher进程
进程包括多个线程
Accept 线程:接收新的连接请求并响应
Worker 线程:child进程会为每个会话启动一个worker线程,因此,在高并发的场景中可能会出现数百个worker线程甚至更多;
Object Expiry 线程:从缓存中清理过期内容;
Commad line 线程 : 管理接口
Storage/hashing 线程 :缓存存储
Log/stats 线程:日志管理线程
Backend Communication 线程:管理后端主机线程
Varnish依赖“工作区(workspace)”以降低线程在申请或修改内存时出现竞争的可能性。在varnish内部有多种不同的工作区,其中最关键的当属用于管理会话数据的session工作区。
1.3 Varnish的日志
为了与系统的其它部分进行交互,Child进程使用了可以通过文件系统接口进行访问的共享内存日志(shared memory log),因此,如果某线程需要记录信息,其仅需要持有一个锁,而后向共享内存中的某内存区域写入数据,再释放持有的锁即可。而为了减少竞争,每个worker线程都使用了日志数据缓存。共享内存日志大小一般为90M,其分为两部分,前一部分为计数器,后半部分为客户端请求的数据。varnish提供了多个不同的工具如varnishlog、varnishncsa或varnishstat等来分析共享内存日志中的信息并能够以指定的方式进行显示。
1.4Vcl的工作流程
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命令完成。
(1)Receive 状态,也就是请求处理的入口状态,根据 VCL 规则判断该请求应该是 Pass 或
Pipe,或者进入 Lookup(本地查询)。
(2)Lookup 状态,进入此状态后,会在 hash 表中查找数据,若找到,则进入 Hit 状态,否则进
入 miss 状态。
(3)Pass 状态,在此状态下,会进入后端请求,即进入 fetch 状态。
(4)Fetch 状态,在 Fetch 状态下,对请求进行后端的获取,发送请求,获得数据,并进行本地
的存储。
(5)Deliver 状态, 将获取到的数据发送给客户端,然后完成本次请求。
2 Varnish的工作模式
详细的流程:
图中椭圆形部分称为varnish的状态节点,又称为状态引擎,还有种叫法为varnish的内置函数。
图中红色的线条:没有查询缓存/缓存中数据过期/缓存中没有数据 情况下的流程
图中橙黄色的线条:直接将匹配数据通过内置函数vcl_pipe送往后台主机的流程
图中绿色的线条:查询缓存数据命中且数据没有过期/经后台主机返回的数据经被缓存后返回给客户流程
图中蓝色的线条:数据没有命中缓存向后台主机发出查询的流程
图中黑色的线条:数据从后台主机返回给varnish缓存的流程
2.1 内置参数的用法
1) vcl_recv:用于接收和处理请求,请求到达并被成功接受后被调用。
四个主要用途:
修改客户端请求数据减少缓存对象差异性:比如删除URL中的www.字符
基于客户端数据选用缓存策略:不如不缓存POST请求,
为web应用程序执行URL重写规则
挑选合适的后端服务器
经常使用的终止语句
pass:绕过缓存,不从缓存中查询内容或不将内容存储至缓存
pipe:不对客户端进行检查或做出任何操作,而是在客户端与后台服务间建立“管道”进行数据传输。
lookup:在缓存中查找用户请求的对象
error :格式:error code [reason] ,向客户端返回一个错误代码code 和 原因resion,该reason可自定义
2) vcl_pipe:将请求直接传递至后端主机,在请求和返回的内容没有改变的情况下,将不变的内容传递给客户端,直到这个链接被关闭。
3)vcl_hash: 在缓存中进行查询
4)vcl_hit:在缓存中找到请求的内容
经常使用的终止语句:
deliver:将找到的内容发送给客户端,把控制权交个函数vcl_deliver
error code [reason]:说明见上
pass:将控制权交个vcl_pass函数处理,可能是缓存中数据过期所致
5)vcl_miss:当在缓存中没有找到匹配数据时被调用
经常使用的结束语
error code [reason]:说明见上
pass:说明见上
fetch:表示从后端获取的请求的内容,并将控制权交给VCL_fetch函数
6)vcl_pass:将请求直接传递给后端主机,后端主机将应答数据发送给客户端,而不执行缓存,每次都返回最新内容。
7)vcl_fetch:向后端主机获取内容,通过判断将内容放入缓存,还是直接返回给客户端。
经常使用的结束语:
error code [reason]:说明见上
deliver:将控制器交给vcl_deliver函数,将数据返回给客户端
hit_no_pass:不缓存数据,直接返回给客户端
8)vcl_deliver函数:将缓存中找到的数据返回给客户端
经常使用的结束语:
error code [reason]:说明见上
deliver:将内容返回给客户端
3 Varnish的简单配置
3.1Varnish服务器的部署 (server1虚拟机 ip 172.25.1.2)
1)Varish的安装
2)Varish的主配文件说明
/etc/rc.d/init.d/varnish # 启动脚本
/etc/varnish/default.vcl # 默认的vcl规则配置
/etc/sysconfig/varnish # 向varnish传递的参数
/etc/sysconfig/varnish 配置说明
NFILES=131072 --->打开的最大文件数,varnish 自动调整该值
MEMLOCK=82000 --->内存中共享日志空间的大小
NPROCS="unlimited" --->单个用户运行的线程数
RELOAD_VCL=1 --->设置为1 ,表示随着varnish的重启自动状态vcl策略配置文件
VARNISH_VCL_CONF=/etc/varnish/default.vcl --->默认vcl策略文件的位置
VARNISH_LISTEN_PORT=80 --->varnish监听的端口,默认为 6081
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1 --->varnish提供telnet管理端口监听的地址
VARNISH_ADMIN_LISTEN_PORT=6082 --->varnish提供telnet管理端口监听的端口 VARNISH_SECRET_FILE=/etc/varnish/secret --->varnish为管理端口提供的共享密钥文件
VARNISH_MIN_THREADS=50 --->varnish启动时启动最少的线程数
VARNISH_MAX_THREADS=1000 --->varnish启动时启动最多的线程数 VARNISH_THREAD_TIMEOUT=120 --->varnish线程数的空闲时间,超过该时间自动销毁线程
VARNISH_STORAGE_MEM=100M --->使用内存为存储设备时使用的空间大小
VARNISH_STORAGE="malloc,${VARNISH_STORAGE_MEM}"
--->当varnish后端存储的配置,使用内存用来缓存数据,大小为100M
VARNISH_TTL=120
DAEMON_OPTS="-a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \
-f ${VARNISH_VCL_CONF} \
-T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \
-t ${VARNISH_TTL} \
-w ${VARNISH_MIN_THREADS},${VARNISH_MAX_THREADS},${VARNISH_THREAD_TIMEOUT} \
-u varnish -g varnish \
-S ${VARNISH_SECRET_FILE} \
-s ${VARNISH_STORAGE}"
3)编辑/etc/security/limits.conf
[root@Server1 mnt]# vim /etc/security/limits.conf
内容如下:
在文件最后添加:
# End of file
varnish - nofile 131072
varnish - memlock 82000
varnish - nproc unlimited
4)编辑/etc/sysconfig/varnish 配置服务端口
5)编辑/etc/varnish/default.vcl 配置后端服务器
3.2 web1服务器的部署 (server2虚拟机 ip 172.25.1.3)
1)httpd服务安装
yum install httpd -y
/etc/init.d/httpd start #打开服务
2)默认发布目录下测试内容编写
vim /etc/www/html/index.html
3.3 客户端测试
1)本机域名解析(解析的域名和ip对应的是Varnish服务器)
2)实现结果
结果分析:发现客户端可以通过Varnish服务器来实现访问后端web服务器的功能。下面的实验会展现出Varnish的Cache功能
1)配置Varnish配置文件/etc/varnish/default.vcl
root@Server1 mnt]# vim /etc/varnish/default.vcl
编辑如下:
# 编辑后段服务器:
7 backend web1 {
8 .host = "172.25.1.3"; # 服务器 ip
9 .port = "80";
10 }
11
# 查看缓存命中情况
12 sub vcl_deliver {
13 if (obj.hits > 0) {
14 set resp.http.X-Cache = "HIT from varnish cache"; #有缓存
15 }
16 else {
17 set resp.http.X-Cache = "MISS from varnish cache"; #没有缓存
18 }
19 return (deliver);
20 }
3.4 当出现多个不同域名后端web服务器时的配置
1)在上面的基础上加入一个web2服务器(server3 ip 172.25.1.4)
2)http服务安装
yum install httpd -y
/etc/init.d/httpd start #打开服务
3)默认发布目录内容发布
4 )Varnish的服务器配置
编辑/etc/varnish/default.vcl
[root@Server1 mnt]# vim /etc/varnish/default.vcl
编辑内容如下:
8 backend web1 { # 第一个后端服务器
9 .host = "172.25.1.3";
10 .port = "80";
11 }
12 backend web2 { # 第二个后端服务器
13 .host = "172.25.1.4";
14 .port = "80";
15 }
16
17
18
19
# 当访问 www.james.org 域名时从 web1 上取数据,访问 www.kobe.org 域名时到 web2 取数据,
# 访问其他页面报错。
20 sub vcl_recv {
21 if (req.http.host ~ "^(www.)?jaems.org") {
22 set req.http.host = "www.jaems.org";
23 set req.backend = web1;
24
25 } elsif (req.http.host ~ "^www.kobe.org") {
26 set req.backend = web2;
27 } else {
28 error 404 "varnish cache";
29 }
5)客户端进行测试
本地域名解析,加入第三个web服务器维护的域名
172.25.1.4 www.kobe.org
看图上解析
在浏览器输入不是这个两个后端web服务器维护的域名时
3.5 健康检查和负载均衡
varnish可以对后端主机进行健康检测,动态进行移除或恢复后端主机调度列表
#probe:定义健康状态检测方法
#url:检测时请求的URL,默认为”/”;
#request:发出的具体请求;
#request =
#“GET /.healthtest.html HTTP/1.1”
#“Host: www.magedu.com”
#“Connection: close”
#window:基于最近的多少次检查来判断其健康状态;
#threshhold:最近.window中定义的这么次检查中至有.threshhold定义的次数是成功的;
#interval:检测频度;
#timeout:超时时长;
#expected_response:期望的响应码,默认为200;
**负载均衡**
英文名称为Load Balance,其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。
注意:varnish 的负载均衡可浅显的理解为,将一个服务器上的信息分摊到多个服务器上,防止一个服务器崩溃导致无法进行数据访问
1)Varnish服务器配置
配置/etc/varnish/default.vcl
[root@Server1 mnt]# vim /etc/varnish/default.vcl
编辑如下:
probe healthcheck {
.url = "/index.html"; # 哪个 url 需要 varnish 请求
.interval = 5s; # 检查的间隔时间
.timeout = 1s; # 等待多长时间探针超时
.window = 5; # 维持 5 个 sliding window 的结果
.threshold = 3; # 至少有三次 window 是成功的,就宣告bachend 健康
}
backend web1 {
.host = "172.25.1.3";
.port = "80";
.probe = healthcheck;
}
backend web2 {
.host = "172.25.1.4";
.port = "80";
.probe = healthcheck;
}
director skr round-robin { # 把多个后端聚合为一个组
{ .backend = web1; }
{ .backend = web2; }
}
sub vcl_recv {
if (req.http.host ~ "^(www.)?james.org") {
set req.http.host = "www.james.org";
set req.backend = skr;
return(pass); # 为了测试方便,不进行缓存
}
elsif (req.http.host ~ "^www.kobe.org") {
set req.backend = web2;
}
else {
error 404 "test cache";
}
}
编辑完成,进行重新加载
[root@Server1 mnt]# /etc/init.d/varnish reload
2)客户端测试
结果分析:就会发现后端的两个web服务器轮询的方式出现
3.6 varnish cdn 推送平台
3.6.1 cdn 的概念
CDN的全称是Content Delivery Network,即内容分发网络。其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络,CDN系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。其目的是使用户可就近取得所需内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度。
CDN是构建在网络之上的内容分发网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术。
CDN的基本原理是广泛采用各种缓存服务器,将这些缓存服务器分布到用户访问相对集中的地区或网络中,在用户访问网站时,利用全局负载技术将用户的访问指向距离最近的工作正常的缓存服务器上,由缓存服务器直接响应用户请求。
3.6.2 cdn 的简单测试
环境设置:httpd 服务 varnish服务 php服务 (server1 ip 172.25.1.2)
1)安装bansys软件包
unzip bansys.zip -d /var/www/html
2 )把解压后的所有文件必须放在httpd默认发布目录下
3)配置 /var/www/html/config.php
将文件内容删减至下图
<?php
//varnish主机列表
//可定义多个主机列表
$var_group1 = array(
'host' => array('172.25.1.2'),
'port' => '80',
);
//varnish群组定义
//对主机列表进行绑定
$VAR_CLUSTER = array(
'www.test.org' => $var_group1,
);
//varnish版本
//2.x和3.x推送命令不一样
$VAR_VERSION = "3";
?>
~
4)修改httpd的配置文件
vim /etc/httpd/conf/httpd.conf
将默认的监听端口80 改成8080 (在上面的cdn配置中80端口已经被占用)
5 )客户端测试
6)cdn的工作模式
bansys 有两种工作模式,分别是:telnet 和 http 模式。
telnet 模式需要关闭 varnish 服务管理端口的验证,注释掉/etc/sysconfig/varnish 文件中的 “ -S $
{VARNISH_SECRET_FILE}”这行,重启 varnish 服务即可。
如果是 http 模式需要对 varnish 做以下设置:
vim /etc/varnish/default.vcl
acl skr{ #设置访问控制
"127.0.0.1";
"172.25.1.2"/24;
}
sub vcl_recv {
if (req.request == "BAN") {
if (!client.ip ~ skr) {
error 405 "Not allowed.";
}
ban("req.url ~ " + req.url);
error 200 "ban added";
}
7)可以在cdn在http模式推送内容
8)如果推送成功会出现以下界面