首页 > 代码库 > 高性能Web服务之varnish应用详解及实战应用

高性能Web服务之varnish应用详解及实战应用

  Varnish是一款开源的反向代理软件和HTTP加速器,也称为带缓存反向代理服务,与传统的Squid相比,Varnish具有性能更高、速度更快、管理更方便等诸多优点,很多大型的运营网站都开始尝试使用Varnish来替换Squid,这也是促使Varnish迅速发展起来的原因。



  Varnish同时也可作为Web缓存服务器,Web缓存(web cache)到底是是什么?Web缓存是指一个Web资源(如html页面,图片,js,数据等)存在与Web服务器和客户端(浏览器)直接的副本。缓存会根据进来的请求保存输出内容的副本;当下一个请求到来的时候,如果是相同的URL,缓存会根据缓存机制决定是直接使用副本响应访问请求还是向源服务器再次发送请求。有效减少web服务器压力及性能,实现客户快速访问web服务。


  上面我们说到Varnish也是缓存服务器,为什么需要缓存: 当今的Web网站,特别是电商及流量的大论坛站点,时常承受着高并发访问,前期我了解过使用负载均衡解决方案可以将用户的请求调度到后端不同的服务器上,解决单台服务器不能承载高并发访问的情况,如果我们将用户的请求的URL所有返回的页及内容以特定的存储方式存储在特定的前端服务器上,当用户再次请求相同类型的资源时,直接通过前端服务器响应给客户端用户,有效的减少后端服务器的响应压力次数,提升后端服务器性能有效性。


Varnish程序架构如下:

技术分享

(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日志管理

  为了与系统的其它部分进行交互,Child进程使用了可以通过文件系统接口进行访问的共享内存日志(shared memory log),因此,如果某线程需要记录信息,其仅需要持有一个锁,而后向共享内存中的某内存区域写入数据,再释放持有的锁即可。而为了减少竞争,每个worker线程都使用了日志数据缓存。

   共享内存日志大小一般为90M,其分为两部分,前一部分为计数器,后半部分为客户端请求的数据。varnish提供了多个不同的工具如varnishlog、varnishncsa或varnishstat等来分析共享内存日志中的信息并能够以指定的方式进行显示。


(3) Varnish 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命令完成。


(4) Varnish的后端存储
  Varnish支持多种不同类型的后端存储,这可以在varnishd启动时使用-s选项指定。后端存储的类型包括:
(1)file:使用特定的文件存储全部的缓存数据,并通过操作系统的mmap()系统调用将整个缓存文件映射至内存区域(如果条件允许);
(2)malloc:使用malloc()库调用在varnish启动时向操作系统申请指定大小的内存空间以存储缓存对象;
(3)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) VCL内置函数和处理(状态引擎):

技术分享


VCL内置函数应用如下所示:

(1)vcl_recv:用于接收和处理请求。当请求到达并被成功接收调用,通过判断请求的数据来决定如果处理请求。例如:应该如何响应、通过什么方式响应、调度使用哪个后端服务器。

作用应用如下:

vcl_recv是在Varnish完成对请求报文的解码为基本数据结构后第一个要执行的子例程,它通常有四个主要用途:

(1)修改客户端数据以减少缓存对象差异性;比如删除URL中的www.等字符;
(2)基于客户端数据选用缓存策略;比如仅缓存特定的URL请求、不缓存POST请求等;
(3)为某web应用程序执行URL重写规则;
(4)挑选合适的后端Web服务器;

可以使用下面的终止语句,即通过return()向Varnish返回的指示操作:

pass:绕过缓存,即不从缓存中查询内容或不将内容存储至缓存中;

pipe:不对客户端进行检查或做出任何操作,而是在客户端与后端服务器之间建立专用“管道”,
并直接将数据在二者之间进行传送;此时,keep-alive连接中后续传送的数据也都将通过此管道进行
直接传送,并不会出现在任何日志中;

lookup:在缓存中查找用户请求的对象,如果缓存中没有其请求的对象,后续操作很可能会将其请求的
对象进行缓存;

error:由Varnish自己合成一个响应报文,一般是响应一个错误类信息、重定向类信息或负载均衡器
返回的后端web服务器健康状态检查类信息;

vcl_recv也可以通过精巧的策略完成一定意义上的安全功能,以将某些特定的攻击扼杀于摇篮中。同时,它也可以检查出一些拼写类的错误并将其进行修正等。


Varnish默认的vcl_recv专门设计用来实现安全的缓存策略,它主要完成两种功能:

(1)仅处理可以识别的HTTP方法,并且只缓存GET和HEAD方法;
(2)不缓存任何用户特有的数据;

安全起见,一般在自定义的vcl_recv中不要使用return()终止语句,而是再由默认vcl_recv进行处理,并由其做出相应的处理决策。


(2)vcl_fetch:相对于vcl_recv是根据客户端的请求作出缓存决策来说,vcl_fetch则是根据服务器端的响应作出缓存决策。在任何VCL状态引擎中返回的pass操作都将由vcl_fetch进行后续处理。vcl_fetch中有许多可用的内置变量,比如最常用的用于定义某对象缓存时长的beresp.ttl变量。通过return()返回给Varnish的操作指示有:

(1)deliver:缓存此对象,并将其发送给客户端(经由vcl_deliver);
(2)hit_for_pass:不缓存此对象,但可以导致后续对此对象的请求直接送达到vcl_pass进行处理;
(3)restart:重启整个VCL,并增加重启计数;超出max_restarts限定的最大重启次数后将会返回错误信息;
(4)error code [reason]:返回指定的错误代码给客户端并丢弃此请求;

默认的vcl_fetch放弃了缓存任何使用了Set-Cookie首部的响应。


(3)vcl_pipe:此函数在进入pipe模式时被调用,用于将请求直接传递至后端主机,在请求和返回内容没有改变的情况下,将不变的内容返回给客户端,直到整个连接被关闭。

此函数一般以如下几个关键字结束:

** error code[reason]
** pipe


(4)vcl_pass:此函数在进入pass模式时被调用,用于将请求直接传递至后端主机,后端主机在应答数据后将应答数据发送给客户端,但不进行任何缓存,在当前连接下每次都返回最新的内容。

此函数一般以如下几个关键字结束:

** error code[reason]
** pass


(5)lookup:此模式表示在缓存中查找被请求的对象,并且根据查找的结果交给vcl_hash进行计算,最后把控制权交给函数vcl_hist或函数vcl_miss。


(6)vcl_hash:此函数在进入lookup模式时被调用,在vcl_recv调用后为请求创建一个hash值时,调用此函数;此hash值将作为varnish中搜索缓存对象的key;

此函数一般以如下几个关键字结束:

** error code[reason]
** hash


(7)vcl_hit:在执行lookup指令后,在缓存中找到请求的内容后将自动调用该函数。

此函数一般以如下几个关键字结束:

** deliver: 表示将找到的内容发送给客户端,并把控制权交给函数vcl_deliver.
** error code[reason]
** pass


(8)vcl_miss:在执行lookup指令后,在缓存中没有找到请求的内容时将自动调用该函数方法,此函数可用于判断是否需要从后端服务器获取内容。

此函数一般以如下几个关键字结束:

** fetch: 表示从后端获取请求的内容,并把控制权交给vcl_fetch函数
** error code[reason]
** pass

(9)vcl_deliver:将在缓存中找到请求的内容发送给客户端前调用此函数方法。

此函数一般以如下几个关键字结束:

** error code[reason]
** deliver

Varnish处理HTTP请求的过程大致分为以下几个步骤:

(1).Receive状态。也就是请求处理的入口状态,根据VCL规则判断该请求应该Pass或Pipe,还是进入Lookup(本地查询)

(2).Lookup状态。进入此状态后,会在hash表中查找数据,若找到,则进入Hit状态,否则进入Miss状态

(3)Pass状态。在此状态下,会进入后端请求,即进入Fetch状态。

(4)Fetch状态。在Fetch状态下,对请求进行后端获取,发送请求,获得数据,并进行本地存储。

(5)Deliver状态。将获取到的数据发送给客户端,然后完成本次请求。


Varnish VCL使用说明:

  VCL用于让管理员定义缓存策略,而定义好的策略将由varnish的management进程分析、转换成C代码、编译成二进制程序并连接至child进程。varnish内部有几个所谓的状态(state),在这些状态上可以附加通过VCL定义的策略以完成相应的缓存处理机制,因此VCL也经常被称作“域专用”语言或状态引擎,“域专用”指的是有些数据仅出现于特定的状态中。
    
(1)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函数中的可能出现的漏洞。

(2)VCL语法
  VCL的设计参考了C和Perl语言,因此,对有着C或Perl编程经验者来说,其非常易于理解。其基本语法说明如下:

(1)//、#或/* comment */用于注释
(2)sub $name 定义函数
(3)不支持循环,有内置变量
(4)使用终止语句,没有返回值
(5)域专用
(6)操作符:=(赋值)、==(等值比较)、~(模式匹配)、!(取反)、&&(逻辑与)、||(逻辑或)

(3)内置公用变量

请求到达后可以使用的VCL内置的公用变量:

公用变量名称
含义
req.backend
指定对应的后端主机
server.ip
表示服务器端IP
client.ip
表示客户端IP
req.request
指定请求的类型,例如:GET HEAD POST等
req.url
指定请求的地址
req.proto
表示客户端发起请求的HTTP协议版本
req.http.header
表示对用请求中的HTTP头部信息
req.restarts
表示请求重启的次数,默认最大值为4


Varnish在向后端主机请求时,可以使用的公用变量:

公用变量名称含义
beresp.request
指定请求类型,例如GET和HEAD等
beresp.url
指定请求的地址
beresp.proto
表示客户端发起的请求的HTTP协议版本
beresp.http.header
表示对应请求中的HTTP头部信息
beresp.ttl
表示缓存的生存周期,也就是cache保留多长时间,单位为秒


从cache或后端主机获取内容后,可以使用的公用变量:

公用变量名称含义
obj.status
表示返回内容的请求状态代码,例如200、302和504等
obj.cacheable
表示返回的内容是否可以缓存,也就是说,如果HTTP返回的是202、203、300、301、302、404或410等,并且有非0的生存期,则可以缓存。
obj.valid
表示是否有效的HTTP应答
obj.response
表示返回内容的请求状态信息
obj.proto
表示返回内容的HTTP协议版本
obj.ttl
表示返回内容的生存周期,也就是缓存时间,单位为秒
obj.lastuse
表示返回上一次请求到现在的间隔时间,单位为秒


对客户端应答时,可以使用的公用变量:

公用变量名称含义
resp.status
表示返回给客户端的HTTP状态代码
resp.proto
表示返回给客户端的HTTP协议版本
resp.http.header
表示返回给客户端的HTTP头部信息
resp.response
表示返回给客户端的HTTP状态信息


Varnish简单实例配置--实现单台主机服务配置案例

实验环境如下:

主机
IP
服务功能
Varnish
eth0:172.16.100.1/16  eth1:192.168.56.10/24
Varnish Server
web1
eth0:192.168.56.11/24
httpd server
web2
eth0:192.168.56.12/24httpd server

配置后端服务器web1、web2主机:

--安装httpd php php-mysql服务
# yum -y install httpd php php-mysql

--编辑配置文件配置httpd端口为5656
# vim /etc/httpd/conf/httpd.conf 
Listen 5656

--配置主页文件
# echo "<h1>Test Web1 Node</h1>" > /var/www/html/index.html
# service httpd start


安装配置Varnish服务器

--安装varnish服务
# yum -y install varnish

--配置varnish服务配置文件
# vim /etc/sysconfig/varnish 
NFILES=131072    --定义可以打开的最大文件数量
MEMLOCK=82000    --定义log信息使用多大的内容空间
RELOAD_VCL=1
VARNISH_VCL_CONF=/etc/varnish/default.vcl    --定义VCL主配置文件
VARNISH_LISTEN_PORT=80                        --定义监听端口,默认为6081
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1        --管理varnish监听地址
VARNISH_ADMIN_LISTEN_PORT=6082                --管理varnish的监听端口
VARNISH_SECRET_FILE=/etc/varnish/secret       --varnish加密文件
VARNISH_MIN_THREADS=50                        --varnish最小进程数
VARNISH_MAX_THREADS=1000                      --varnish最大进程数
VARNISH_THREAD_TIMEOUT=120                    --varnish工作进程超时时长
VARNISH_STORAGE_FILE=/var/lib/varnish/varnish_storage.bin    --缓存文件存储类型,可以定义使用内存存储
VARNISH_STORAGE_SIZE=1G
#VARNISH_STORAGE="file,${VARNISH_STORAGE_FILE},${VARNISH_STORAGE_SIZE}"    --定义存储属性
VARNISH_STORAGE="malloc,256M"
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}"
             
--启动varnish服务
# service varnish start


配置Varnish VCL策略配置文件,实现添加响应报文首部

# vim /etc/varnish/test.vcl 
backend web1 {    --定义后端主机
  .host = "192.168.56.11";    --后端主机地址
  .port = "5656";             --定义后端主机监听端口
}

sub vcl_deliver {        --在vcl_deliver状态引擎中定义
     if (obj.hits > 0) {    --如果缓存命中次数大于0,则添加响应首部X-Cache;设置值为HIT server.ip
       set resp.http.X-Cache = "HIT " + server.ip;
     } else {
       set resp.http.X-Cache = "MISS " + server.ip; --否则,设置值为MISS server.ip
     }
       return (deliver);    --定义返回状态
}

应用test.vcl策略配置:

# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
varnish> vcl.load test1 /etc/varnish/test.vcl  \\载入策略配置文件      
varnish> vcl.use test1  \\应用配置文件
varnish> vcl.list
200 47      
available       0 boot
active          3 test1

使用命令行测试如下所示:

技术分享

使用浏览器测试如下所示:

技术分享

技术分享



配置Varnish VCL策略配置文件,设置缓存时长

# vim /etc/varnish/test.vcl 
backend web1 {    --定义后端主机
  .host = "192.168.56.11";    --后端主机地址
  .port = "5656";             --定义后端主机监听端口
}

sub vcl_fetch {               --在vcl.fetch状态引擎定义
  if (bereq.http.Set-Cookie) { --如果varnish请求有cookies信息
     unset bereq.http.Set-Cookie; --则将cookie信息清除
     set beresp.ttl = 120s;        --设置缓存时长为120s
  }
  return (deliver);                --定义返回状态
}

sub vcl_deliver {        --在vcl_deliver状态引擎中定义
     if (obj.hits > 0) {    --如果缓存命中次数大于0,则添加响应首部X-Cache;设置值为HIT server.ip
       set resp.http.X-Cache = "HIT " + server.ip;
     } else {
       set resp.http.X-Cache = "MISS " + server.ip; --否则,设置值为MISS server.ip
     }
       return (deliver);    --定义返回状态
}

应用test.vcl策略配置:

# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
varnish> vcl.load test2 /etc/varnish/test.vcl  \\载入策略配置文件      
varnish> vcl.use test2  \\应用配置文件
varnish> vcl.list
200 71      
available       0 boot
available       0 test1
active          3 test2

使用命令行测试如下所示:

技术分享


使用浏览器访问测试如下所示:

技术分享

技术分享



配置Varnish VCL策略配置文件,利用varnish自带着函数(purge)清空缓存

# vim /etc/varnish/test.vcl 
backend web1 {    --定义后端主机
  .host = "192.168.56.11";    --后端主机地址
  .port = "5656";             --定义后端主机监听端口
}

acl purge {            --定义ACL访问名称
  "localhost";         --授权本地主机允许访问
  "127.0.0.1";         --授权127.0.0.1允许访问
  "172.16.0.0"/16;     --授权172.16.0.0/16内主机访问
}

--以下设定,当发送PURGE请求的客户端不是在acl中设定的地址时,将返回405状态代码,提示Not allowed.
--当请求的URL是以.php和.cgi结尾时,则交给后端服务器处理响应
sub vcl_recv {
  if (req.request == "PURGE") {
      if (!client.ip ~ purge) {
      error 405 "Not allowed.";
   }
      elseif(req.url ~ "\.(php|cgi($|\?))"){
      return (pass);
   }
      else {
      return (lookup);
   }
  }
}

sub vcl_hit {                    --在vcl_hit状态引擎中定义策略
  if (req.request == "PURGE") {  --如果缓存命中且请求方法为"PURGE"
   purge;                        --执行内置函数purge
   error 200 "Purged";           --返回信息及状态码
 } 
}

sub vcl_miss {                    --在vcl_miss中定义策略
  if (req.request == "PURGE") {   --如果请求方法"PURGE"没有命中
   purge;                         --执行内置函数purge
   error 200 "no cache.";         --返回信息及状态码
  }
}

sub vcl_pass {                            --在vcl_pass中定义策略
  if (req.request == "PURGE") {
   error 502 "Purged on a passed object.";
 }
}

sub vcl_fetch {               --在vcl.fetch状态引擎定义
  if (bereq.http.Set-Cookie) { --如果varnish请求有cookies信息
     unset bereq.http.Set-Cookie; --则将cookie信息清除
     set beresp.ttl = 120s;        --设置缓存时长为120s
  }
  return (deliver);                --定义返回状态
}

sub vcl_deliver {        --在vcl_deliver状态引擎中定义
     if (obj.hits > 0) {    --如果缓存命中次数大于0,则添加响应首部X-Cache;设置值为HIT server.ip
       set resp.http.X-Cache = "HIT " + server.ip;
     } else {
       set resp.http.X-Cache = "MISS " + server.ip; --否则,设置值为MISS server.ip
     }
       return (deliver);    --定义返回状态
}

应用test.vcl策略配置:

# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
varnish> vcl.load test3 /etc/varnish/test.vcl  \\载入策略配置文件      
varnish> vcl.use test3  \\应用配置文件
varnish> vcl.list
200 71      
available       0 boot
available       0 test1
available       0 test2
active          3 test3

测试如下所示:

技术分享


=============================================================

Varnish应用案例之对应单台主机实现web缓存应用

VCL策略配置文件如下所示:

# cat /etc/varnish/cache_1.vcl 
backend webserver1 {
  .host = "192.168.56.11";
  .port = "5656";
}

sub vcl_recv {
       if (req.http.x-forwarded-for) {
          set req.http.X-Forwarded-For =
         req.http.X-Forwarded-For + ", " + client.ip;
       } else {
           set req.http.X-Forwarded-For = client.ip;
       }
       if (req.request != "GET" &&
          req.request != "HEAD" &&
          req.request != "PUT" &&
          req.request != "POST" &&
          req.request != "TRACE" &&
          req.request != "OPTIONS" &&
          req.request != "DELETE") {
          return (pipe);
       }

       if (req.request != "GET" && req.request != "HEAD") {
           return (pass);
       }

       if (req.http.host ~ "^(.*).samlee.net" || req.http.host ~ "^(.*).samlee.com") {
           set req.backend = webserver1;
       }
       
       if (req.url ~ "\.(jsp|do)($|\?)") {
              return (pass);
       } else {
       return (lookup);
       }

}


sub vcl_pipe {
    return (pipe);
}

sub vcl_pass {
    return (pass);
}

sub vcl_hash {
     hash_data(req.url);
     if (req.http.host) {
         hash_data(req.http.host);
     } else {
         hash_data(server.ip);
     }
     return (hash);
}

sub vcl_hit {
    return (deliver);
}
 
sub vcl_miss {
     return (fetch);
}

sub vcl_fetch {
    if (req.request == "GET" && req.url ~ "/upload(.*)$") {
        set beresp.ttl = 300s;
    }

    if (req.request == "GET" && req.url ~ "\.(png|xsl|xml|pdf|ppt|doc|docx|chm|rar|zip|bmp|jpeg|swf|ico|mp3|mp4|rmvb|ogg|mov|avi|wmv|swf|txt|png|gif|jpg|css|js|html|htm)$") {
        set beresp.ttl = 600s;
    }
    return (deliver);
}

sub vcl_deliver {
    if (obj.hits > 0) {
        set resp.http.X-Cache = "HIT " + "--" + server.ip + "--" +  client.ip;
    } else {
        set resp.http.X-Cache = "MISS " + "--" + server.ip + "--" + client.ip;
    }
    return (deliver);
}

=============================================================

Varnish应用案例之对应多台主机实现web动静分离

案例演示如下所示:

以下操作在web1下进行

# yum -y install httpd  php    --安装httpd和php
# vim /etc/httpd/conf/httpd.conf  --修改监听端口为5656
Listen 5656

# vim /var/www/html/index.php    --创建动态网页文件
<html>
   <body>
   <img src="http://www.mamicode.com/1.png"/>
   <h1>
   <font size="12px" color="red">This is Index on node1 dynamic Test</font>
   </h1>
   <?php
        echo "This is PHP Index Page!!!";
   ?>
 </body>
</html>
     
# service httpd start   --重启httpd


以下操作在web2下进行

# yum -y install httpd 
# vim /etc/httpd/conf/httpd.conf  --修改监听端口为5656
Listen 5656

# echo "<h1>Test Web2 Node</h1>" > /var/www/html/index.html    --创建静态网页文件

# ls  #我们从本地上传了一张png图
1.png  index.html
# service httpd start --启动httpd
# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
varnish> vcl.load test4 /etc/varnish/test.vcl  \\载入策略配置文件      
varnish> vcl.use test4  \\应用配置文件
varnish> vcl.list
200 71      
available       0 boot
available       0 test1
available       0 test2
available       0 test3
active          3 test4

以上应用VCL策略配置。

测试如下:

访问http:172.16.100.1/index.html 如下所示:

技术分享

技术分享

VCL策略配置如下所示:

# vim /etc/varnish/test.vcl
backend webserver1 {
  .host = "192.168.56.11";
  .port = "5656";
}
backend webserver2 {
  .host = "192.168.56.12";
  .port = "5656";
}

sub vcl_recv {
       if (req.url ~ "(php|php5)$") {
           set req.backend = webserver1;
       } else {
           set req.backend = webserver2;
       }
   
       if (req.url ~ "(php|php5)$") {
           return (pass);
       }

       if (req.http.x-forwarded-for) {
          set req.http.X-Forwarded-For =
         req.http.X-Forwarded-For + ", " + client.ip;
       } else {
           set req.http.X-Forwarded-For = client.ip;
       }
       if (req.request != "GET" &&
          req.request != "HEAD" &&
          req.request != "PUT" &&
          req.request != "POST" &&
          req.request != "TRACE" &&
          req.request != "OPTIONS" &&
          req.request != "DELETE") {
          return (pipe);
       }

       if (req.request != "GET" && req.request != "HEAD") {
           return (pass);
       }

       if (req.http.host ~ "^(.*).samlee.net" || req.http.host ~ "^(.*).samlee.com") {
           set req.backend = webserver1;
       }
       
       if (req.url ~ "\.(jsp|do)($|\?)") {
              return (pass);
       } else {
       return (lookup);
       }

}


sub vcl_pipe {
    return (pipe);
}

sub vcl_pass {
    return (pass);
}

sub vcl_hash {
     hash_data(req.url);
     if (req.http.host) {
         hash_data(req.http.host);
     } else {
         hash_data(server.ip);
     }
     return (hash);
}

sub vcl_hit {
    return (deliver);
}
 
sub vcl_miss {
     return (fetch);
}

sub vcl_fetch {
    if (req.request == "GET" && req.url ~ "/upload(.*)$") {
        set beresp.ttl = 300s;
    }

    if (req.request == "GET" && req.url ~ "\.(png|xsl|xml|pdf|ppt|doc|docx|chm|rar|zip|bmp|jpeg|swf|ico|mp3|mp4|rmvb|ogg|mov|avi|wmv|swf|txt|png|gif|jpg|css|js|html|htm)$") {
        set beresp.ttl = 600s;
    }
    return (deliver);
}

sub vcl_deliver {
    if (obj.hits > 0) {
        set resp.http.X-Cache = "HIT " + "--" + server.ip + "--" +  client.ip;
    } else {
        set resp.http.X-Cache = "MISS " + "--" + server.ip + "--" + client.ip;
    }
    return (deliver);
}

以上Varnish缓存应用基本所有内容。

本文出自 “Opensamlee” 博客,请务必保留此出处http://gzsamlee.blog.51cto.com/9976612/1856067

高性能Web服务之varnish应用详解及实战应用