Varnish高性能缓存服务器
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Varnish高性能缓存服务器相关的知识,希望对你有一定的参考价值。
一、Varnish概述
- 一款高性能、开源的HTTP反向代理服务器和缓存服务器,挪威最大的在线报纸 Verdens Gang 使用3台Varnish代替了原来的12台Squid,性能比以前更好。
- Varnish使用内存做为缓存设备(纯内存缓存服务器方案),相对于Squid(采用硬盘缓存),拥有更快的缓存速度(varnish内存管理完全交给内核,但当缓存内容超过阈值时,内核会自动将一部分缓存存入swap中,让出内存)
1.Varnish进程
Varnish与一般服务器软件类似,分为master(management)进程和child(主要做cache的工作)
Management进程主要实现应用新的配置、编译VCL、监控varnish、初始化varnish以及提供一个命令行接口等。Management进程会每隔几秒钟探测一下Child进程以判断其是否正常运行,如果在指定的时长内未得到Child进程的回应,Management将会重启此 Child进程
Child进程包含多种类型的线程,常见的如:
- Acceptor线程:接收新的连接请求并响应
- Worker线程:child进程会为每个会话启动一个worker线程,因此,在高并发的场景中可能会出现数百个worker线程甚至更多
- Expiry 线程:从缓存中清理过期内容;Varnish依赖“工作区(workspace)”以降低线程在申请或修改内存时出现竞争的可能性
在varnish内部有多种不同的工作区,其中最关键的当属用于管理会话数据的session 工作区
2.Varnish日志
为了与系统的其它部分进行交互,Child进程使用了可以通过文件系统接口进行访问的共享内存日志(shared memory log),当某线程需要记录信息,其仅需要持有一个锁,而后向共享内存中的某内存区域写入数据,再释放持有的锁即可。而为了减少竞争,每个 worker线程都使用了日志数据缓存
- 共享内存日志大小一般为 90M,其分为两部分,前一部分为计数器,后半部分为客户端请求的数据。varnish提供了多个不同的工具如varnishlog、varnishncsa或varnishstat等来分析共享内存日志中的信息并能够以指定的方式进行显示
3.Varnish中的VCL
VCL(Varnish Configuration Language)是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命令完成
4.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}
file中的granularity用于设定缓存空间分配单位,默认单位是字节,所有其它的大小都会被圆整
5.Varnish 的特点
- 基于内存进行缓存,重启后数据将消失
- 利用虚拟内存方式,I/O 性能好
- 支持设置 0~60 秒精确缓存时间
- VCL 配置管理比较灵活
- 32 位机器上缓存文件大小为最大 2GB
- 具有强大的管理功能
- 状态机设计巧妙,结构清晰
- 利用二叉堆管理缓存文件,可达到积极删除目的
6.Varnish与Squid对比
优点
- Varnish稳定性高,当Squid和Varnish同时完成相同负荷工作时,Squid发生故障的几率高于Varnish,因为使用Squid要经常重启
- Varnish访问速度快,Varnish采用Visual Page Cache技术,所有缓存数据都直接从内存中读取,而Squid从硬盘中读取
- Varnish支持更多的并发连接,因为Varnish的TCP连接释放要比Squid快,因此在高并发情况下可以支持更多的TCP连接
- Varnish可以通过管理端口,使用正则表达式批量的清除部分缓存
- Squid属于单进程使用单核CPU,但Varnish通过fork形式打开多进程来处理,所以可以合理的使用所有核来处理相应的请求
缺点
- 高并发下,Varnish消耗更多的CPU、I/O和内存资源
- Varnish进程一旦挂起、崩溃或重启,缓存的数据会从内存中释放,此时所有的请求都会转发到后端服务器上,给后端服务器造成很大压力
- Varnish使用中如果单个url的请求通过HA/F5(负载均衡)每次请求到不同的Varnish服务器中,被请求的Varnish服务器都会被穿透到后端,而且同样的请求会在多台服务器上缓存,造成Varnish缓存的资源浪费,也造成性能下降
- Varnish不支持正向代理缓存
综上所述在访问量很大的情况下推荐使用varnish的内存缓存方式启动,而且后面需要跟多台squid服务器。主要为了防止前面的varnish服务、服务器被重启的情况下,前期肯定会有很多的穿透这样squid可以担当第二层CACHE,而且也弥补了varnish缓存在内存中重启都会释放的问题
资源浪费的问题可以在负载均衡上做url哈希,让单个url请求固定请求到一台varnish服务器上,可以解决该问题
7.Varnish与其余主流软件对比
二、Varnish工作原理
- Receive状态:请求处理入口状态,根据VCL规则判断该请求应该Pass或Pipe,还是进入Lookup(本地查询)
- Lookup状态:进入此状态后,会在hash表中查找数据,若找到则进入Hit状态,否则进入Miss状态
- Fetch状态:在Fetch状态下,对请求进行后端获取、发送请求、获得数据,并进行本地存储
- Deliver状态:将获取到的数据发送给客户端,然后完成本次请求
- Pipe状态:不通过varnish,开通“管道”,直接有后端真实的web 节点回复客户端请求
三、部署Varnish负载均衡高可用群集
主机 | 系统 | IP | 网卡 | 软件 |
---|---|---|---|---|
Varnish | Centos 6.7 64Bit | 192.168.1.10 | vmnet1 | varnish |
Web1(Apache) | Centos 6.7 64Bit | 192.168.1.100 | vmnet1 | httpd |
Web2(Apache) | Centos 6.7 64Bit | 192.168.1.200 | vmnet1 | httpd |
Varnish
1.环境准备
vim /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0 //网卡名称
TYPE=Ethernet //网卡类型为以太网
ONBOOT=yes //开机自启该网卡
NM_CONTROLLED=no //关闭NetworkManager
BOOTPROTO=static //网卡设置为静态方式
IPADDR=192.168.1.10 //IP地址配置
NETMASK=255.255.255.0 //子网掩码配置
/etc/init.d/network restart
2.安装Varnish
yum -y install libtool ncurses-devel pcre-devel libxslt groff pkgconfig gcc gcc-c++
//安装varnish依赖的开发环境
rpm -ivh libedit-devel-2.11-4.20080712cvs.1.el6.x86_64.rpm
rpm -ivh python-imaging-1.1.6-19.el6.x86_64.rpm
rpm -ivh python-docutils-0.6-1.el6.noarch.rpm //安装rpm依赖包
tar -zxvf varnish-4.0.1.tgz -C /usr/src/
cd /usr/src/varnish-4.0.1/
./autogen.sh //运行varnish脚本,会自动设置libtool变量等信息
./configure --prefix=/usr/local/varnish --enable-debugging-symbols --enable-developer-warnings
选项
--enable-debugging-symbols:开启调试,调试一些bug信息的标志,默认为“NO”
--enable-developer-warnings:启用提示警告,默认为"NO"
make && make install
echo "PATH=$PATH:/usr/local/varnish/bin:/usr/local/varnish/sbin">>/etc/profile
//将varnish命令路径加入PATH变量,这时在任意位置都可使用varnish相关命令
source /etc/profile //立即生效该PATH变量
3.配置Varnish
cp /usr/local/varnish/share/doc/varnish/example.vcl /usr/local/varnish/default.vcl
//拷贝默认提供的varnish配置文件到varnish目录下
vim /usr/local/varnish/default.vcl
import directors; //加载directors模块,提供负载均衡
backend web1 { //定义后端服务器的标识名称
.host = "192.168.1.100"; //定义后端服务器的IP
.port = "80"; //定义后端服务器监听端口
.probe = { //开启健康检查
.url = "/"; //检查请求的URL(请求服务器的网页根目录)
.interval = 5s; //查询的间隔时长(每隔几秒检测一次)
.timeout = 1s; //超时时间,即等待后端1s都无响应即为故障
.window = 5; //判断健康状态时,依最近多少次的检测作为依据
.threshold = 3; //.window指定次数中,3次成功,才代表后端健康
}
}
backend web2 {
.host = "192.168.1.200";
.port = "80";
.probe = {
.url = "/";
.interval = 5s;
.timeout = 1s;
.window = 5;
.threshold = 3;
}
}
sub vcl_init { //VCL初始化VMODs模块,定义director
new bar = directors.round_robin(); //定义调度算法,该处为加权轮询
bar.add_backend(web1); //添加标识名称为web1的加入director
bar.add_backend(web2); //添加标识名称为web2的加入director
}
sub vcl_recv {
set req.backend_hint = bar.backend(); //将所有的流量转发给dictctors
}
varnishd -C -f /usr/local/varnish/default.vcl
//检测VCL配置是否有误,如输出一系列的内置配置,即无问题,反之
varnishd -f /usr/local/varnish/default.vcl -a 0.0.0.0:80
//启动varnish,并监听当前服务器的80端口
-f /usr/local/etc/varnish/default.vcl
这个 –f 选项指定varnishd使用哪个配置文件。
-s malloc,1G
这个 –s 选项用来确定varnish使用的存储类型和存储容量,我使用的是malloc类型(malloc是一个C函数,用于分配内存空间), 1G 定义多少内存被malloced,1G = 1gigabyte。
-T 127.0.0.1:2000
Varnish有一个基于文本的管理接口,启动它的话可以在不停止varnish的情况下来管理varnish。您可以指定管理软件监听哪个接口。当然您不能让全世界的人都能访问您的varnish管理接口,因为他们可以很轻松的通过访问varnish管理接口来获得您的root访问权限。我推荐只让它监听本机端口。如果您的系统里有您不完全信任的用户,您可以通过防火墙规则来限制他访问varnish的管理端口。
-a 0.0.0.0:8080
这一句的意思是制定varnish监听所有IP发给8080端口的http请求,如果在生产环境下,您应该让varnish监听80,这也是默认的。
vcl配置文件的介绍请执行如何命令查看:
man /usr/local/varnish/share/man/man7/vcl.7
netstat -utpln | grep varnish
varnishlog //动态输出varnish的缓存及客户端访问完整情况
varnish 命令参数
-f:指定varnish服务器的配置文件
-aaddress:port:表示varnish对httpd的监听地址及端口
-Taddress:port:设定varnish的 telnet管理地址及端口
-baddress:port:表示后端服务器的地址及端口
-d:表示使用debug调试模式
-Pfile:varnish进程PID文件存放路径
-s:varnish缓存文件位置与大小(-s file,文件路径,大小)
-w:最小,最大线程和超时时间(例:-w 1200,5 1200 10)
Web1
vim /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0 //网卡名称
TYPE=Ethernet //网卡类型为以太网
ONBOOT=yes //开机自启该网卡
NM_CONTROLLED=no //关闭NetworkManager
BOOTPROTO=static //网卡设置为静态方式
IPADDR=192.168.1.100 //IP地址配置
NETMASK=255.255.255.0 //子网掩码配置
/etc/init.d/network restart
yum -y install httpd //安装apache服务
echo "This is Web1">/var/www/html/index.html
//给第一台Web服务器编写测试页面
/etc/init.d/httpd start && chkconfig --level 35 httpd on
//启动httpd服务并设置为开机自启
Web2
vim /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0 //网卡名称
TYPE=Ethernet //网卡类型为以太网
ONBOOT=yes //开机自启该网卡
NM_CONTROLLED=no //关闭NetworkManager
BOOTPROTO=static //网卡设置为静态方式
IPADDR=192.168.1.200 //IP地址配置
NETMASK=255.255.255.0 //子网掩码配置
/etc/init.d/network restart
yum -y install httpd //安装apache服务
echo "This is Web2">/var/www/html/index.html
//给第二台Web服务器编写测试页面
/etc/init.d/httpd start && chkconfig --level 35 httpd on
//启动httpd服务并设置为开机自启
测试
IE --> http://192.168.1.10(Varnish服务器IP)
测试负载均衡
注:测试负载均衡时,由于采用加权轮询算法,因此有可能刷新几次都在Web1服务器上,可多刷新几次
测试高可用
ifdown eth0 //在Web1上输入,模拟Web1故障
注:测试高可用时,由于Varnish强大的缓存能力,Web1的页面会缓存,因此当将Web1停止时,可以还可以访问到Web1,这是等待一会,让Varnish自动清空缓存即可
以上是关于Varnish高性能缓存服务器的主要内容,如果未能解决你的问题,请参考以下文章