Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4562434
  • 博文数量: 1214
  • 博客积分: 13195
  • 博客等级: 上将
  • 技术积分: 9105
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-19 14:41
个人简介

C++,python,热爱算法和机器学习

文章分类

全部博文(1214)

文章存档

2021年(13)

2020年(49)

2019年(14)

2018年(27)

2017年(69)

2016年(100)

2015年(106)

2014年(240)

2013年(5)

2012年(193)

2011年(155)

2010年(93)

2009年(62)

2008年(51)

2007年(37)

分类: 系统运维

2016-09-17 20:43:03

原文地址:http://blog.csdn.net/keda8997110/article/details/8777153
 Varnish配置文件详解

既然Varnish需要在多台服务器上缓存数据,就需要Varnish映射所有的URL到一台单独的主机。


  1. backend webserver {  
  2. .host = "127.0.0.1";  
  3. .port = "80";  
  4. .connect_timeout = 4s;  
  5. .first_byte_timeout = 5s;  
  6. .between_bytes_timeout = 20s;  
  7. }  

该块配置用于定义一台Varnish默认访问的后端服务器,当Varnish需要从后端服务器获取数据时,就会访问自己的80端口。

当然Varnish也可以定义多台后端服务器实现负载均衡的目的。

.connect_timeout定义的是等待连接后端的时间

.first_byte_timeout定义的是等待从backend传输过来的第一个字节的时间

.between_bytes_timeout 定义的是两个字节的间隔时间

当然还可以增加一个backend,用于访问本机的8090端口,假设通过该端口提供图片服务。


  1. backend img {  
  2. .host = "127.0.0.1";  
  3. .port = "8090";  
  4. }  

 

当匹配img的URL时,需把请求发送到上面定义的backend img,其他的请求发送到backend webserver。

  1. sub vcl_recv {  
  2. if (req.url ~ "^/img/") {  
  3. set req.backend = img;  
  4. } else {  
  5. set req.backend = webserver.  
  6. }  
  7. }  

 

Varnish不仅仅可以定义多个backend,还可以把多个backend合成一个组,使用循环的方式把请求分配给组中的backends。并且Varnish会根据健康检查情况来判断后端服务器是否正常提供服务。

Varnish使用区域语言VCL来管理定义Varnish的存取策略。VCL语法简单,跟Perl比较相似,可以使用多种运算符如"="、"=="、"!,&&,!!"等形式;也可以使用正则表达式来进行匹配,还可以使用"set"来指定变量。当执行VCL时,Varnish会先把VCL转换成二进制代码。

有一点要注意,"\"字符在VCL里没有什么特别的含义,这点和其他语言不同。另外,VCL只是配置语言,并不是真正的编程语言,所以没有循环和自定义变量。

为了可以更好地对Varnish进行配置调整,需要了解Varnish的配置语法,也就是VCL语言。下面对VCL常用的一些函数和变量进行介绍。

(1)vcl_recv模块

用于接收和处理请求。当请求成功被调用后,Varnish通过判断请求的数据来决定如何处理请求。此模块一般以如下几个关键字结束。

pass:表示进入pass模式,把请求交给vcl_pass模块处理。

pipe:表示进入pipe模式,把请求交给vcl_pipe模块处理。

error code [reason]:表示把错误标识返回给客户端,并放弃处理该请求。错误标识包括200、405等。"reason"是对错误的提示信息。

(2)vcl_pipe模块

此模块在请求进入pipe模式时被调用,用于将请求直接传递至后端主机,在请求和返回的内容没有改变的情况下,也就是在当前连接未关闭时,服务器将不变的内容返回给客户端,直到该连接被关闭。

(3)vcl_pass模块

此模块表示当请求被pass后,用于将请求直接传递至后端应用服务器。后端应用服务器在接收请求后将数据发送给客户端,但不进行任何数据的缓存,在当前连接下每次都返回最新的内容。

(4)lookup


一个请求在vcl_recv中被lookup后,Varnish将在缓存中提取数据。如果缓存中有相应的数据,就把控制权交给vcl_hit模块;如果缓存中没有相应的数据,请求将被设置为pass并将其交给vcl_miss模块。

(5)vcl_hit模块

执行lookup指令后,Varnish在缓存中找到请求的内容后将自动调用该模块。

在此模块中,deliver表示将找到的数据发送给客户端,并把控制权交给vcl_deliver模块。

(6)vcl_miss模块

执行lookup后,Varnish在缓存中没有找到请求的内容时会自动调用该方法。此模块可以用于判断是否需要从后端服务器获取内容。

在此模块中,fetch表示从后端获取请求的数据,并把控制权交给vcl_fetch模块。

(7)vcl_fetch模块

在后端主机更新缓存并且获取内容后调用该方法,接着,通过判断获取的内容来决定是将内容放入缓存,还是直接返回给客户端。

(8)vcl_deliver模块

当一个没有被缓存的数据交付给客户端的时候被调用。

(9)vcl_timeout 模块

在缓存数据到期前调用此模块。

在此模块中,discard表示从缓存中清除到期数据。

(10)vcl_discard模块

在缓存数据到期后或缓存空间不够时,自动调用该模块。

在此模块中keep表示将数据继续保留在缓存中。


  1. acl purge {  
  2.        "localhost";  
  3.        "127.0.0.1";  
  4.        "18.81.12.10";  
  5. }  
  6.  
  7.  
  8.        if (req.request == "PURGE") {  
  9.                if (!client.ip ~ purge) {  
  10.                        error 405 "Not allowed.";  
  11.                }  
  12.                return(lookup);  
  13.        }  



这两个规则定义了允许哪些主机通过HTTP来执行PURG进行缓存删除。如果不是指定的IP,就会出现HTTP 405错误,提示Not allowed错误字样。

  1. if (req.http.host ~ "^(read)?.aaa.com$") {  
  2.              set req.backend = webserver;   
  3.              if (req.request != "GET" && req.request != "HEAD") {  
  4.                      return(pipe);  
  5.              }  
  6.              else {  
  7.                      return(lookup);  
  8.              }  
  9.      }  
  10.      else {  
  11.              error 404 " Cache Server";   
  12.              return(lookup);  
  13.      }  


这段条件判断用于对aaa.com域名进行缓存加速,aaa.com是泛指概念,也就是说所有以aaa.com结尾的域名都进行缓存。而if (req.request != "GET" && req.request != "HEAD") 表示"如果请求的类型不是GET与HEAD",则返回错误码404。

  1. if (req.url ~ "^/images") {  
  2.   unset req.http.cookie;  
  3.  }  

这条规则的意思是清除服务器上/images目录下的所有缓存,当这个请求在后端服务器生效时,如果访问的URL匹配这个规则,那么头信息中的cookie就会被删除。



  1. if (req.request == "GET" && req.url ~ "\. (png|swf|txt|png|gif|jpg|css|js|htm| html)$") {  
  2.   unset req.http.cookie;  
  3.  }  
  4.  
  5.  
  6. if (req.http.x-forwarded-for) {   
  7.         set reqreq.http.X-Forwarded-For =   
  8.                 req.http.X-Forwarded-For ", " client.ip; }   
  9. else { set req.http.X-Forwarded-For = client.ip; }  


因为Squid、Varnish都会把客户端的IP地址放在HTTP_X_FORWARDED_FOR里面传给后端的Web服务器,所以后端的Web程序都要对其进行调用。

  1. if (req.request != "GET" &&  
  2.     req.request != "HEAD" &&  
  3.     req.request != "PUT" &&  
  4.     req.request != "POST" &&  
  5.     req.request != "TRACE" &&  
  6.     req.request != "OPTIONS" &&  
  7.     req.request != "DELETE") {  
  8.   return (pipe);  
  9.  }  


该if判断表示如果请求的类型不是GET、HEAD、PUT、POST、TRACE、OPTIONS、DELETE时,则进入pipe模式。注意这里的"&&"是与的关系。

  1. if (req.request == "GET" && req.url ~ "\. (png|swf|txt|png|gif|jpg|css|js|htm| html)") {  
  2.                set beresp.ttl = 180s;  
  3.        }  
  4.        else {  
  5.                set beresp.ttl = 30d;  
  6.        }  
  7.         return (deliver);  
  8. }  

 

该if判断用于对请求类型是GET,并且请求的URL以png、swf、txt、gif、css、js等结尾时,则进行缓存,缓存时间为180秒。其他缓存为30天。

  1. sub vcl_deliver {  
  2.  set resp.http.x-hits = obj.hits ;  
  3.  if (obj.hits > 0) {  
  4.   set resp.http.X-Cache = "HIT read.easouu.com";  
  5.  }  
  6.  else {  
  7.       set resp.http.X-Cache = "MISS read.easou.com";  
  8.  }  

 

这个模块定义的是添加一个Header标识,以判断缓存是否命中。

  1. sub vcl_error {  
  2.  set obj.http.Content-Type = "text/html; charset=utf-8";  
  3.  synthetic {"  
  4. xml version="1.0" encoding="utf-8"?> 
  5. > 
  6. <html> 
  7.    <head> 
  8.       <title>"} obj.status " " obj.response {"title> 
  9.    head> 
  10.    <body> 
  11.       <h1>Error "} obj.status " " obj.response {"h1> 
  12.       <p>"} obj.response {"p> 
  13.       <h3>Guru Meditation:h3> 
  14.       <p>XID: "} req.xid {"p> 
  15.       <hr> 
  16.       <address> 
  17.          <a href="">read.easou.coma> 
  18.       address> 
  19.    body> 
  20. html> 
  21. "};  
  22.  return (deliver);  
  23. }  

最后这个模块定义了访问错误页面时的返回信息。

现在varnish配置基本完成,可以在8080端口上启动varnish,并进行一些基本的测试。


Varnish缓存的配置

简单的配置文件内容如下:


  1. [html] view plain copy
    1. backend webserver {    
    2. .host = "127.0.0.1";    
    3. .port = "8090";    
    4. .connect_timeout = 4s;    
    5. .first_byte_timeout = 5s;    
    6. .between_bytes_timeout = 20s;    
    7. }    
    8. acl purge {    
    9.        "localhost";    
    10.        "127.0.0.1";    
    11.        "18.81.12.10";    
    12. }    
    13.    
    14. sub vcl_recv {    
    15.    
    16.        if (req.request == "PURGE") {    
    17.                if (!client.ip ~ purge) {    
    18.                        error 405 "Not allowed.";    
    19.                }    
    20.                return(lookup);    
    21.        }    
    22.    
    23.        if (req.http.host ~ "^(read)?.easou.com$") {    
    24.                set req.backend = webserver;     
    25.                if (req.request != "GET" && req.request != "HEAD") {    
    26.                        return(pipe);    
    27.                }    
    28.                else {    
    29.                        return(lookup);    
    30.                }    
    31.        }    
    32.        else {    
    33.                error 404 " Cache Server";     
    34.                return(lookup);    
    35.        }    
    36.    
    37.  if (req.request == "GET" && req.url ~ "\.(png|swf|txt|png|gif|jpg|css|js| htm|html)$") {    
    38.   unset req.http.cookie;    
    39.  }    
    40.    
    41.  if (req.url ~ "^/images") {    
    42.   unset req.http.cookie;    
    43.  }    
    44.    
    45.      if (req.http.Cache-Control ~ "(no-cache|max-age=0)") {    
    46.         purge_url(req.url);     
    47.      }     
    48.      return (lookup);    
    49.    
    50. if (req.http.x-forwarded-for) {     
    51.         set reqreq.http.X-Forwarded-For =     
    52.                 req.http.X-Forwarded-For ", " client.ip; }     
    53. else { set req.http.X-Forwarded-For = client.ip; }    
    54.    
    55.    
    56. if (req.request != "GET" &&    
    57.     req.request != "HEAD" &&    
    58.     req.request != "PUT" &&    
    59.     req.request != "POST" &&    
    60.     req.request != "TRACE" &&    
    61.     req.request != "OPTIONS" &&    
    62.     req.request != "DELETE") {    
    63.   return (pipe);    
    64.  }    
    65.    
    66.  if (req.request != "GET" && req.request != "HEAD") {    
    67.   return (pass);    
    68.  }     
    69.    
    70.  if (req.http.Authorization || req.http.Cookie) {    
    71.   return (pass);    
    72.  }    
    73. }    
    74.  sub vcl_pipe {    
    75.       # set req.http.connection = "close";    
    76.      return (pipe);}    
    77.  sub vcl_hit {    
    78.  if (!obj.cacheable) {    
    79.   return (pass);    
    80.  }    
    81.  if (req.request == "PURGE") {    
    82.          set obj.ttl = 0s;    
    83.          error 200 "Purged.";    
    84.       }    
    85.  return (deliver);    
    86. }    
    87.    
    88. sub vcl_miss {    
    89.  return (fetch);    
    90. }    
    91.    
    92.    
    93. sub vcl_fetch {    
    94.    
    95. if (!beresp.cacheable) {    
    96.  return (pass);    
    97.  }    
    98.  if (beresp.http.Set-Cookie) {    
    99.   return (pass);    
    100.  }    
    101.    
    102.  if (beresp.http.Pragma ~ "no-cache" ||    
    103.      beresp.http.Cache-Control ~ "no-cache" ||    
    104.             beresp.http.Cache-Control ~ "private") {    
    105.   return (pass);    
    106.       }    
    107.    
    108. if (req.url ~ "^/cover/") {    
    109.                set beresp.ttl = 1800s;    
    110.        }    
    111.        else {    
    112.                set beresp.ttl = 30d;    
    113.        }    
    114.          return (deliver);    
    115.    
    116.           
    117. #       if (req.request == "GET" && req.url ~ "\.(png|swf|txt|png|gif|jpg|css|js| htm|html|jsp)") {    
    118. #               set beresp.ttl = 180s;    
    119. #       }    
    120. #       else {    
    121. #               set beresp.ttl = 30d;    
    122. #       }    
    123. #        return (deliver);    
    124. }    
    125.    
    126. sub vcl_deliver {    
    127.  set resp.http.x-hits = obj.hits ;    
    128.  if (obj.hits > 0) {    
    129.   set resp.http.X-Cache = "HIT read.easouu.com";    
    130.  }    
    131.  else {    
    132.       set resp.http.X-Cache = "MISS read.easou.com";    
    133.  }    
    134. }    
    135. sub vcl_error {    
    136.  set obj.http.Content-Type = "text/html; charset=utf-8";    
    137.  synthetic {"    
    138. xml version="1.0" encoding="utf-8"?>   
    139. >   
    140. <html>   
    141.    <head>   
    142.       <title>"} obj.status " " obj.response {"title>   
    143.    head>   
    144.    <body>   
    145.       <h1>Error "} obj.status " " obj.response {"h1>   
    146.       <p>"} obj.response {"p>   
    147.       <h3>Guru Meditation:h3>   
    148.       <p>XID: "} req.xid {"p>   
    149.       <hr>   
    150.       <address>   
    151.          <a href="">read.easou.coma>   
    152.       address>   
    153.    body>   
    154. html>   
    155. "};    
    156.  return (deliver);    
    157. }    

    Varnish 简介

    Varnish 是一款高性能且开源的反向代理服务器和 HTTP 加速器,其采用全新的软件体系机构,和现在的硬件体系紧密配合,与传统的 squid 相比,varnish 具有性能更高、速度更快、管理更加方便等诸多优点,很多大型的网站都开始尝试使用 varnish 来替换 squid,这些都促进 varnish 迅速发展起来。

    挪威的最大的在线报纸 Verdens Gang(vg.no) 使用 3 台 Varnish 代替了原来的 12 台 Squid,性能比以前更好,这是 Varnish 最成功的应用案例。

    Varnish 文件缓存的工作流程

    Varnish 与一般服务器软件类似,分为 master 进程和 child 进程。Master 进程读入存储配置文件,调用合适的存储类型,然后创建 / 读入相应大小的缓存文件,接着 master 初始化管理该存储空间的结构体,然后 fork 并监控 child 进程。Child 进程在主线程的初始化的过程中,将前面打开的存储文件整个 mmap 到内存中,此时创建并初始化空闲结构体,挂到存储管理结构体,以待分配。Child 进程分配若干线程进行工作,主要包括一些管理线程和很多 worker 线程。

    接着,开始真正的工作,varnish 的某个负责接收新 HTTP 连接线程开始等待用户,如果有新的 HTTP 连接过来,它总负责接收,然后唤醒某个等待中的线程,并把具体的处理过程交给它。Worker 线程读入 HTTP 请求的 URI,查找已有的 object,如果命中则直接返回并回复用户。如果没有命中,则需要将所请求的内容,从后端服务器中取过来,存到缓存中,然后再回复。

    分配缓存的过程是这样的:它根据所读到 object 的大小,创建相应大小的缓存文件。为了读写方便,程序会把每个 object 的大小变为最接近其大小的内存页面倍数。然后从现有的空闲存储结构体中查找,找到最合适的大小的空闲存储块,分配给它。如果空闲块没有用完,就把多余的内存另外组成一个空闲存储块,挂到管理结构体上。如果缓存已满,就根据 LRU 机制,把最旧的 object 释放掉。

    释放缓存的过程是这样的:有一个超时线程,检测缓存中所有 object 的生存期,如果超初设定的 TTL(Time To Live)没有被访问,就删除之,并且释放相应的结构体及存储内存。注意释放时会检查该存储内存块前面或后面的空闲内存块,如果前面或后面的空闲内存和该释放内存是连续的,就将它们合并成更大一块内存。

    整个文件缓存的管理,没有考虑文件与内存的关系,实际上是将所有的 object 都考虑是在内存中,如果系统内存不足,系统会自动将其换到 swap 空间,而不需要 varnish 程序去控制。

    Varnish 安装

    下载 varnish 安装包

    建议下载最新稳定版本(现在最新 varnish 版本为 3.0.2),varnish 提供源代码安装包和可执行程序安装包,按照您的习惯下载适合您平台的任一安装包即可。

    安装 varnish

    源代码安装包安装

    首先安装 pcre 库,pcre 库是为兼容正则表达式,如果不安装,在安装 varnish2.0 版本以上时,会提示找不到 pcre 库。以下是 pcre 的安装过程,其代码如清单 1 所示:


    清单 1. pcre 库安装代码
    				
         tar zxvf pcre.tar.gz 
         cd pcre/ 
         ./configure --prefix=/usr/local/pcre/ 
         Make && make install 
    

    安装 varnish,其代码如清单 2 所示:


    清单 2. varnish 安装代码
    				
            tar xzvf varnish-3.0.2.tar.gz 
            cd varnish-3.0.2 
            export PKG_CONFIG_PATH =/usr/local/pcre/lib/pkgconfig 
            ./configure --prefix=/usr/local/varnish  	
            make 
            make install 
    

    可执行程序安装包安装

    RedHat 系统环境下的安装 varnish,您需要安装以下软件:automake、autoconf、libtool、ncurses-devel、libxslt、groff、pcre-devel、pkgconfig,然后进行 varnish 的安装,安装代码如清单 3 所示:


    清单 3. varnish 安装代码
    				
     rpm -i varnish-2.1.4-2.el5.x86_64.rpm 
    

    启动 varnish


    清单 4. varnish 启动代码
    				
     varnishd -f /etc/varnish/default.vcl -s file,/var/varnish_cache,1G \
     -T 127.0.0.1:2000 -a 0.0.0.0:9082
    

    各参数的含义如下:

    -f 指定 varnish 的配置文件位置

    -s 指定 varnish 缓存存放的方式,常用的方式有:“-s file,,”。

    -T address:port 设定 varnish 的 telnet 管理地址及其端口

    -a address:port 表示 varnish 对 http 的监听地址及其端口

    Varnish 配置

    VCL 简介

    VCL(varnish configuration language)是 varnish 配置语言,其用来定义 varnish 的存取策略。VCL 语法比较简单,跟 C 和 Perl 比较相似。主要有以下几点:

    • 块是由花括号分隔,语句以分号结束,使用‘ # ’符号可以添加注释。
    • VCL 使用指定运算符“=”、比较运算符“==”、逻辑运算符“!,&&,!!”等形式,还支持正则表达式和用“~”进行 ACL 匹配运算。
    • VCL 没有用户自己定义的变量,你可以在 backend、request 或 object 上设置变量值,采用 set 关键字进行设置。例如 set req.backend = director_employeeui;
    • 两个字符串的连接,他们之间没有任何运算符。代码如清单 5 所示:

    清单 5. 字符串连接代码
    				
     set req.http.X-hit = " hit" "it"; 
    

    • \”字符在 VCL 里没有特别的含义,这点与其他语言略有不同。
    • VCL 可以使用 set 关键字设置任何 HTTP 头,可以使用 remove 或是 unset 关键字移除 HTTP 头。
    • VCL 有 if/else 的判断语句,但是没有循环语句。

    VCL backend

    声明并初始化一个后端对象,代码如清单 6 所示


    清单 6. backend 声明代码
    				
    	 backend www { 
    	   .host = ""; 
    	   .port = "9082"; 
    	 } 
    

    后端对象的使用,代码如清单 7 所示


    清单 7. backend 的使用代码
    				
    	 if (req.http.host ~ "^(www.)?example.com$") { 
    	    set req.backend = www; 
    	 } 
    

    VCL 后端的集合 director

    VCL 可以把多个 backends 聚合成一个组,这些组被叫做 director,这样可以增强性能和弹力,当组里一个 backend 挂掉后,可以选择另一个健康的 backend。VCL 有多种 director,不同的 director 采用不同的算法选择 backend,主要有以下几种:

    • The random director

    Random director 会根据所设置的权值(weight)来选择 backend,.retries 参数表示尝试找到一个 backend 的最大次数,.weight 参数表示权值

    • The round-robin director

    Round-robin director 在选择 backend 时,会采用循环的方式依次选择。

    • The client director

    Client director 根据 client.identity 来选择 backend,您可以设置 client.identity 的值为 session cookie 来标识 backend。

    backend probes

    VCL 可以设置 probe 来检测一个 backend 是否健康,定义一个 backend probes 代码如清单 8 所示:


    清单 8. 定义 backend probes 代码
    				
    	 backend www { 
    	  .host = ""; 
    	  .port = "9082"; 
    	  .probe = { 
    	    .url = "/test.jpg";// 哪个 url 需要 varnish 请求
    	    .timeout = 1 s;// 等待多长时间超时
    	    .interval = 5s// 检查的时间间隔
                 .window = 5;// 维持 5 个 sliding window 的结果
    	    .threshold = 3;// 至少有三次 window 是成功的,就宣告 backend 健康
    	  } 
    	 } 
    

    ACL

    ACL 可创建一个客户端的访问控制列表,你可以使用 ACL 控制哪些客户端可以访问,哪些客户端禁止访问。定义 ACL 代码如清单 9 所示:


    清单 9. ACL 定义代码
    				
    	 Acl local{ 
    	   "localhost"; 
    	   "192.0.2.0"/24; 
    	   !"192.0.2.23";// 除去该 IP 
    	 } 
    

    VCL 内置函数

    vcl_recv 函数

    用于接收和处理请求。当请求到达并成功接收后被调用,通过判断请求的数据来决定如何处理请求。例如如何响应、怎么响应、使用哪个后端服务器等。

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

    pass:表示进入 pass 模式,把请求控制权交给 vcl_pass 函数。

    pipe:表示进入 pipe 模式,把请求控制权交给 vcl_pipe 函数。

    lookup:表示进入 lookup 模式,把请求控制权交给 lookup 指令处理,在缓存中查找被请求的对象,并且根据查找的结果把控制权交给函数 vcl_hit 或函数 vcl_miss。

    error code [reason]:表示返回“code”给客户端,并放弃处理该请求。“code”是错误标识,例如 200 和 405 等。“reason”是错误提示信息。

    vcl_pipe 函数

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

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

    error code [reason]。

    pipe。

    vcl_pass 函数

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

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

    error code [reason]。

    pass。

    restart 重新启动流程,增加启动次数,如果重新启动次数高于 max_restarts 发出一个错误警告

    vcl_hash

    当您想把一个数据添加到 hash 上时,调用此函数。

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

    Hash。

    vcl_hit 函数

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

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

    deliver:表示将找到的内容发送给客户端,并把控制权交给函数 vcl_deliver。

    error code [reason] 。

    pass。

    restart 重新启动流程,增加启动次数,如果重新启动次数高于 max_restarts 发出一个错误警告

    vcl_miss 函数

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

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

    fetch:表示从后端获取请求的内容,并把控制权交给 vcl_fetch 函数。

    error code [reason] 。

    pass。

    vcl_fetch 函数

    在后端主机更新缓存并且获取内容后调用该方法,接着,通过判断获取的内容来决定是将内容放入缓存,还是直接返回给客户端。

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

    error code [reason]。

    pass。

    deliver。

    esi。

    restart 重新启动流程,增加启动次数,如果重新启动次数高于 max_restarts 发出一个错误警告

    vcl_deliver 函数

    将在缓存中找到请求的内容发送给客户端前调用此方法。

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

    error code [reason]。

    deliver。

    restart 重新启动流程,增加启动次数,如果重新启动次数高于 max_restarts 发出一个错误警告

    vcl_error

    出现错误时调用此函数。

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

    deliver。

    restart。

    VCL 处理流程

    VCL 处理的流程图如图 1 所示


    图 1.VCL 处理流程
    图 1.VCL 处理流程 

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

    • Receive 状态(vcl_recv)。也就是请求处理的入口状态,根据 VCL 规则判断该请求应该 pass(vcl_pass)或是 pipe(vcl_pipe),还是进入 lookup(本地查询)。
    • Lookup 状态。进入该状态后,会在 hash 表中查找数据,若找到,则进入 hit(vcl_hit)状态,否则进入 miss(vcl_miss)状态。
    • Pass(vcl_pass)状态。在此状态下,会直接进入后端请求,即进入 fetch(vcl_fetch)状态
    • Fetch(vcl_fetch)状态。在 fetch 状态下,对请求进行后端获取,发送请求,获得数据,并根据设置进行本地存储。
    • Deliver(vcl_deliver)状态。将获取到的数据发给客户端,然后完成本次请求。

    VCL 内置公共变量

    VCL 内置的公共变量可以用在不同的 VCL 函数中,下面根据使用的不同阶段进行介绍

    当请求到达时,可以使用的公共变量表 1 所示


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

    Varnish 在向后端主机请求时,可是用的公共变量如表 2 所示


    表 2. 向后端主机请求时可用公共变量
    公共变量名 含义
    beresp.requset 指定请求类型,例如 GET、HEAD 等
    beresp.url 表示请求地址
    beresp.proto 表示客户端发起请求的 HTTP 协议版本
    beresp.http.header 表示对应请求中 HTTP 头部信息
    beresp.ttl 表示缓存的生存周期,cache 保留时间(s)

    从 cache 或是后端主机获取内容后,可以使用的公共变量如表 3 所示


    表 3. 后端主机获取内容时可使用公共变量
    公共变量名 含义
    obj.status 返回内容的请求状态码,例如 200、302、504 等
    obj.cacheable 返回的内容是否可以缓存
    obj.valid 是否有效的 HTTP 请求
    obj.response 返回内容的请求状态信息
    obj.proto 返回内容的 HTTP 版本
    obj.ttl 返回内容的生存周期,也就是缓存时间,单位秒
    obj.lastuse 返回上一次请求到现在的时间间隔,单位秒

    对客户端应答时,可以使用的公共变量如表 4 所示


    表 4. 对客户端相应时可使用公共变量
    公共变量名称 含义
    resp.status 返回给客户端的 HTTP 代码状态
    resp.proto 返回给客户端的 HTTP 协议版本
    resp.http.header 返回给客户端的 HTTP 头部消息
    resp.response 返回给客户端的 HTTP 头部状态

    VCL 调试

    VCL 为配置文件语言,无法像 c/c++ 那样进行单步调试,当 VCL 运行的效果和预期效果不一样时,很难发现哪出现逻辑错误,这时除了查看代码查找错误外,我们还可以采用内置 C 语言和浏览器查看返回对象中的状态来查找逻辑的错误。

    我们可以采用内置 C 语言来打印相应的信息,例如我们可以在相应的地方打印信息,来查看 VCL 流程的执行是否正确。内置 C 语言打印信息代码如清单 10 所示:


    清单 10. 打印信息代码
    				
          C{ 
    	    #include// 首先要包含头文件
          }C 
          C{ 
    	    Syslog(LOG_INFO,"VCL run here in function xxx in line xxx"); 
          }C 
    

    启动 varnish 后,我们可以采用 tail -f /var/log/messages 命令在 /var/log/messages 中查看相应的打印信息。查看的打印信息如图 2 所示:


    图 2. varnish 打印信息
    图 2. varnish 打印信息 

    我们还可以将某些变量的值设置到返回给浏览器的对象上,然后在浏览器中查看该变量的值。设置变量值代码如清单 11 所示:


    清单 11. varnish 变量设置代码
    				
     set beresp.http.X-Cookie-Debug-req-cookie = req.http.Cookie; 
    

    在 chrome 浏览器中查看 beresp.http.X-Cookie-Debug-req-cookie 的值,结果如图 3 所示:


    图 3. 在浏览器中查看 varnish 变量的值
    图 3. 在浏览器中查看 varnish 变量的值 

    varnish 配置文件代码

阅读(722) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~