首页 > 代码库 > varnish详解与实际应用案例
varnish详解与实际应用案例
varnish是一款高性能且开源的反向代理服务器和Http加速器,开发者Poulhenning Kamp,其也是FreeBSD核心的开发人员之一,比较有名的应用安全当数,挪威最大的在线报纸Verdens Gang(vg.no)使用3台varnish代替了原有的12台squid,而且性能比以前更好,(思密达,google时都有此说明)可以运行于多种平台,如FreeBSD6.0,7.0 Solaris和Linux 2.6内核及以上版本的运行
一、原理概念介绍
1、varnish系统架构
varnish主要运行两个进程: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的一些特点:
基于内存进行缓存,速度快但服务重启数据将消失的缺点
由于基于内存进行缓存,其I/O性能相当的好
支持设置0到60秒的精确缓存时间
VCL(varnish configure language)配置管理灵活易懂
varnish,squid二者的对比,如下
说到varnish 就不得不提及同样是高性能的代理缓存功能的squid软件,
相同点:
都是反向代理软件
都是开源软件
不同点:
在完成同样负荷的工作下,quid服务器故障的发生机率要高于varnish,原因是squid有时要经常重启
varnish访问速度更快,其基于内存进行数据读取,而squid缓存代理的数据是存放在硬盘中的,要从硬盘读取数据到内存再响应用户的请求
varnish对于TCP的连接释放要比squid快,因此在高并发连接情况下可以支持更多的TCP连接
删除缓存方面,varnish可以通过管理端口,使用正则表达式批量删除部分缓存,而squid没有这项功能
当然varnish也有缺点:
varnish在高并发状态下CPU,I/O和内存等相关资源开销都要高于squid
varnish高并发状态下,进程一旦挂起,崩溃或重启,内存中的缓存数据则会完全释放,且此时大量的用户请求会发送到upstream server,这样会造成upstream server很大的压力,
3、VCL
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命令完成。
VCL用于让管理员定义缓存策略,而定义好的策略将由varnish的management进程分析、转换成C代码、编译成二进制程序并连接至child进程。varnish内部有几个所谓的状态(state),在这些状态上可以附加通过VCL定义的策略以完成相应的缓存处理机制,因此VCL也经常被称作“域专用”语言或状态引擎,“域专用”指的是有些数据仅出现于特定的状态中。
VCL状态引擎
在VCL状态引擎中,状态之间具有相关性,但彼此间互相隔离,每个引擎使用return(x)来退出当前状态并指示varnish进入下一个状态。
varnish开始处理一个请求时,首先需要分析HTTP请求本身,比如从首部获取请求方法、验正其是否为一个合法的HTT请求等。当这些基本分析结束后就需要做出第一个决策,即varnish是否从缓存中查找请求的资源。这个决定的实现则需要由VCL来完成,简单来说,要由vcl_recv方法来完成。如果管理员没有自定义vcl_recv函数,varnish将会执行默认的vcl_recv函数。然而,即便管理员自定义了vcl_recv,但如果没有为自定义的vcl_recv函数指定其终止操作(terminating),其仍将执行默认的vcl_recv函数。事实上,varnish官方强烈建议让varnish执行默认的vcl_recv以便处理自定义vcl_recv函数中的可能出现的漏洞。
VCL语法
VCL的设计参考了C和Perl语言,因此,对有着C或Perl编程经验者来说,其非常易于理解。其基本语法说明如下:
(1)//、#或/* comment */用于注释
(2)sub $name 定义函数
(3)不支持循环,有内置变量
(4)使用终止语句,没有返回值
(5)域专用
(6)操作符:=(赋值)、==(等值比较)、~(模式匹配)、!(取反)、&&(逻辑与)、||(逻辑或)
VCL的函数不接受参数并且没有返回值,因此,其并非真正意义上的函数,这也限定了VCL内部的数据传递只能隐藏在HTTP首部内部进行。VCL的return语句用于将控制权从VCL状态引擎返回给Varnish,而非默认函数,这就是为什么VCL只有终止语句而没有返回值的原因。同时,对于每个“域”来说,可以定义一个或多个终止语句,以告诉Varnish下一步采取何种操作,如查询缓存或不查询缓存等。
二、具体应用与设置
1,一张图介绍varnish作为代理时,用户请求时的数据处理策略
2,此次实验的具体架构
上图简单描述:
对于用户不同的请求,varnish代理至不同的服务器,请求图片,静态页面时转到web1,请求动态页面时转到web2
以下为各配置文件具体配置
varnish的安装与配置:
##实验环境安装的包,centos6.5 64bits rpm -ivh varnish-3.0.4-1.el6.x86_64.rpm varnish-docs-3.0.4-1.el6.x86_64.rpm varnish-libs-3.0.4-1.el6.x86_64.rpm
安装后的文件及相关说明
具体配置文件/etc/sysconfig/varnish (只解释操作中用到的相关参数配置)
NFILES=131072 MEMLOCK=82000 NPROCS="unlimited" RELOAD_VCL=1 VARNISH_VCL_CONF=/etc/varnish/my.vcl VARNISH_LISTEN_PORT=80 VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1 VARNISH_ADMIN_LISTEN_PORT=6082 VARNISH_SECRET_FILE=/etc/varnish/secret VARNISH_MIN_THREADS=50 VARNISH_MAX_THREADS=1000 VARNISH_THREAD_TIMEOUT=120 VARNISH_STORAGE_FILE=/var/lib/varnish/varnish_storage.bin VARNISH_STORAGE_SIZE=1G VARNISH_STORAGE="malloc,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}"
配置文件/etc/varnish/my.vcl (自定义的文件只解释操作中用到的相关参数配置)
##/etc/varnish/my.vcl ################################### backend web1 { .host = "172.15.251.23"; .port = "80"; } backend web2 { .host = "172.15.251.24"; .port = "80"; } director webservs random { { .backend=web1; .weight = 10; } { .backend=web2; .weight = 2; } } acl purgers { "127.0.0.1"; "172.15.0.0"/16;} sub vcl_recv { if(req.url ~ "\.(html|js|css|png)$") { set req.backend = web1; } else { set req.backend = web2; } set req.request = webservs; if (req.request == "PURGE") { if (!client.ip ~ purgers) { error 405 "Method not allowed.";} } return(lookup); } sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "HIT from" + server.hostname; } else { set resp.http.X-Cache = "MISS";} }
到此varnish相关配置完成
配置静态文件服务器(images,html等静态文件 172.16.251.23)
yum install -y httpd
复制1.png文件,新建index.html到目录/var/www/html,如下图:
网页index.html内容如下
[root@node3 html]# pwd /var/www/html [root@node3 html]# ls 1.png index.html [root@node3 html]# cat index.html <h1><center>Hi,this is real server 23</h1> [root@node3 html]#
配置动态web服务器(以tomcat jsp测试环境为例 172.16.251.24)
安装Tomcat并配置文件路径,如下图:
[root@node4 software]# tar -xf apache-tomcat-7.0.42.tar.gz -C /usr/local/ [root@node4 software]# cd /usr/local/ [root@node4 local]# ln -sv apache-tomcat-7.0.42 tomcat [root@node4 local]# cat /etc/profile.d/tomcat.sh export CATALINA_HOME=/usr/local/tomcat export PATH=$CATALINA_HOME/bin:$PATH [root@node4 local]# source /etc/profile.d/tomcat.sh [root@node4 local]#
注:由于tomcat启动默认监听8080端口,要修改为80,具体如下:
找文件/usr/local/tomcat/conf/server.xml 中port="8080" 修改为port="80",重新启动tomcat即可
为tomcat增加启动服务
增加tomcat 服务启动脚本,如下:
#!/bin/sh # Tomcat init script for Linux. # # chkconfig: 2345 96 14 # description: The Apache Tomcat servlet/JSP container. # JAVA_OPTS=‘-Xms64m -Xmx128m‘ JAVA_HOME=/usr/java/lastest CATALINA_HOME=/usr/local/tomcat export JAVA_HOME CATALINA_HOME case $1 in start) exec $CATALINA_HOME/bin/catalina.sh start ;; stop) exec $CATALINA_HOME/bin/catalina.sh stop;; restart) $CATALINA_HOME/bin/catalina.sh stop sleep 2 exec $CATALINA_HOME/bin/catalina.sh start ;; *) echo "Usage: `basename $0` {start|stop|restart}" exit 1 ;; esac
安装JDK,如下图:
[root@node4 software]# rpm -ivh jdk-7u9-linux-x64.rpm [root@node4 software]# cat /etc/profile.d/java.sh export JAVA_HOME=/usr/java/latest export PATH=$JAVA_HOME/bin:$PATH [root@node4 software]# source /etc/profile.d/java.sh [root@node4 software]#
Tomcat环境测试安装成功,如下图:
万事倶备,只差进行varnish动静分离测试(思密达)。。。。。。。。。。。
三 varnish 测试
启动varnish
service varnish start
查看监听的商品:80 web反向代理服务端口,6082管理端口
登陆管理控制台(交互式命令行)并查看帮助
启用策略文件/etc/varnish/my.vcl
动静资源回顾:
172.16.251.23服务器上的为images,html等
172.16.251.24服务器上的为JSP、do动态网页文件等
通过访问http://172.16.251.25/1.png 、http://172.16.251.25/index.html varnish直接代理至后端realserver 172.15.251.23
通过访问http://172.16.251.25/index.jsp varnish直接代理至后端realserver 172.15.251.24
后记:随堂学习感觉是喝凉水,但自己动手还是感觉在吃硬馒头,长篇大论了好几页,感觉重点的还是没有提到,后续工作还有很多,如静态文件的存储方案,高可用可扩展的地方,先这么多