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高性能缓存服务器
Varnish高性能缓存服务器

二、Varnish工作原理


Varnish高性能缓存服务器

  • Receive状态:请求处理入口状态,根据VCL规则判断该请求应该Pass或Pipe,还是进入Lookup(本地查询)
  • Lookup状态:进入此状态后,会在hash表中查找数据,若找到则进入Hit状态,否则进入Miss状态
  • Fetch状态:在Fetch状态下,对请求进行后端获取、发送请求、获得数据,并进行本地存储
  • Deliver状态:将获取到的数据发送给客户端,然后完成本次请求
  • Pipe状态:不通过varnish,开通“管道”,直接有后端真实的web 节点回复客户端请求

三、部署Varnish负载均衡高可用群集


Varnish高性能缓存服务器

主机系统IP网卡软件
VarnishCentos 6.7 64Bit192.168.1.10vmnet1varnish
Web1(Apache)Centos 6.7 64Bit192.168.1.100vmnet1httpd
Web2(Apache)Centos 6.7 64Bit192.168.1.200vmnet1httpd

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自动清空缓存即可

转载于:https://blog.51cto.com/13770206/2163917

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值