首页 > 代码库 > 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作为代理时,用户请求时的数据处理策略


wKioL1NtosPhoMDxAAG7K6AUHlc188.jpg

   2,此次实验的具体架构

wKioL1Ntp7eyWXM2AAEVX8YTMCg466.jpg

上图简单描述:

   对于用户不同的请求,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

   安装后的文件及相关说明

wKioL1NtwaChYk5NAALiwg2s5Vg073.jpg

具体配置文件/etc/sysconfig/varnish (只解释操作中用到的相关参数配置)

wKioL1Ntws6QDEjUAAXKoDCBOGg690.jpg

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 (自定义的文件只解释操作中用到的相关参数配置)

wKioL1NtySPQGHBNAARlRGYKdJA897.jpg

##/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,如下图:

wKiom1NtyvGxrcFzAACRQXBkwsE091.jpg

网页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并配置文件路径,如下图:

wKioL1Ntzh-hrnTpAAGI_EWcuEw687.jpg

[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增加启动服务

wKioL1Nt0bPi0LL9AAH1CYlVmqM011.jpg

   增加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,如下图:

wKiom1Ntzq7DaMWOAADtdeSA8I4161.jpg

[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环境测试安装成功,如下图:

wKiom1Nt1JiTC8zvAANwOCSgLPc130.jpg

   万事倶备,只差进行varnish动静分离测试(思密达)。。。。。。。。。。。

三 varnish 测试

   启动varnish

       service varnish start

   查看监听的商品:80 web反向代理服务端口,6082管理端口

wKioL1Nt1b7zgQx8AAEAGA6qdTU421.jpg

   登陆管理控制台(交互式命令行)并查看帮助

wKioL1Nt1k3QpeTUAAOTrNEUqAw556.jpg

启用策略文件/etc/varnish/my.vcl

wKioL1Nt2arC72H9AAMP9qJqIOg048.jpg

动静资源回顾:

   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

后记:随堂学习感觉是喝凉水,但自己动手还是感觉在吃硬馒头,长篇大论了好几页,感觉重点的还是没有提到,后续工作还有很多,如静态文件的存储方案,高可用可扩展的地方,先这么多