注册 登录
LinuxTone | 运维专家网论坛 - 最棒的Linux运维与开源架构技术交流社区! 返回首页

yonchin_great的个人空间 http://bbs.linuxtone.org/?18303 [收藏] [复制] [分享] [RSS]

日志

Varnish之VCL——参考手册

热度 1已有 2732 次阅读2013-7-26 22:41 | varnish

说明,因网上的关于varnish的中文资料 实在是太少,因此本人不才更加官方文档翻译了VCL学习手册。
注:本人英语水平有限,翻译不当处,还请大家指出来,原文链接是https://www.varnish-cache.org/docs/3.0/reference/index.html

1.描述:
VCL语言是一种被设计用来为varnish来定义请求处理和文档缓存策略的语言。
当配置文件加载时,varnishd会把VCL代码转换为C代码,再将C语言编译为共享对象,然后将它们动态链接进服务进程。

2.VCL语法非常简单,类似于C和Perl。不同的代码块使用大括号分割,每个语句以分号结束,注释的话则可以写成C,C++,或Perl语言的形式。
  2.1. 赋值运算符是=,
  2.2. 比较运算符是==,!=,
  2.3. 布尔运算符是!,&&,||。
  2.4. 同时VCL也支持正则表达式和ACL匹配操作符~,!~。
  2.5. 字符串使用双引号“...”,但不包括新行。
  2.6. 要是想包含新行则需要在双引号外面再加上大括号,如{“...”}。
  2.7.反斜杠\字符没有任何的含义,可以随意的使用
  2.8. 多个字符串要连接在一起,使用加号+
 
  赋值运算符使用set关键字声明。用户不能自定义变量。被赋值的变量必须隶属于后端服务器、请求或者文档对象。
  你可以使用set关键字来任意设置HTTP头部信息。你也可以使用remove或unset关键字来删除头部信息。
  你可以使用rollback关键字来恢复你任意时间对req所做的任意改变。
  这synthetic关键字则被用来在vcl_error子程序中产生一个合并的相应体。它以一个单一的字符串来作为参数。
  你可以使用panic关键字来强制使client进程崩溃。panic也是以一个字符串作为参数。
  return(action)关键字用来结束子程序。其中,action可是:
 deliver
 error
  fetch
 hash
 hit_for_pass
 lookup
 ok
 pass
 pipe
 restart
其中的任何一个。
  其他的VCL文件中的内容,可以使用include关键字来包含进来。

3. 后端服务器的声明
  3.1. 使用一个名为backend的对象来声明后端服务器。例如:
 backend www {
      .host = "www.example.com";
    .port = "http";
 }
 
  3.2. backend对象常被用来在请求发来时,如何选择后端服务器。例如:
 if (req.http.host ~ "(?i)(www.)?example.com$") {
  set req.backend = www; 
 }
  3.3. 为了避免后台服务器超载,.max_connections 参数可以用来限制并发连接的数量。
  3.4. 一些超时的设置参数可以放在后端服务器的声明中。超时参数 .connect_timeout表示等待连接后端服务器的时间;.fist_byte_timeout表示等待来自后端服务器的首字节到达的时间;.between_bytes_timeout表示前一个字节到达后,等待下一个字节所用的时间。以上这些参数都可以设置在后端服务器的声明之中,例如:
 backend www {
    .host = "www.example.com";
   .port = "http";
    .connect_timeout = 1s;
  .first_byte_timeout = 5s;
    .between_bytes_timeout = 2s;
 }
  当所有的条目被添加到saintmode模式列表后,就会将后端服务器标记为不可用。参数 .saintmode_threshold 可以把saintmode列表设置为最大。如果设置为0,就表示对于那个后端服务器来说,就完全禁用了saint模式。如果在后端服务器的声明中,设置了此参数,那么就以声明中的参数为准。


4. Directors
  一个director是为了冗余的目的(说白了,就是实现高可用),将多个后端服务器聚合在一起而形成的一个逻辑组。和LVS中的director的含义差不多。
  director分好几种类型。不同的类型使用不同的算法来选择使用哪台后端服务器。
  director的配置,可以按如下方式:
 director b2 random {
    .retries = 5;
    {
      // 直接引用之前声明的backend对象的名称,如b1。
      .backend = b1;
      .weight  = 7;
    }
    {
      // 或者是直接在参数 .backend后面声明
      .backend  = {
         .host = "fs2";
       }
    .weight         = 3;
    }
 }
   4.1. random类型的director,又分为三种:random director、client director、hash director。之所以它们都属于random,是因为他们使用的内在逻辑都是相同的,在分发流量给后端服务器中都是随机分发的。random director使用一个随机数作为分发种子,client director以客户端身份标识作为分发种子,hash director以缓存的hash值作为分发的种子。虽然,看上去分发种子各不同,但实际上他们所使用的初始分发种子是相同的。
   在director中的设置后端服务器都需要设置一个 .weight(即权值)的选项,此选项可以控制后端服务器所能负载的流量。权值相同的,表示接收的流量相同。权值小的,接收的流量也就相应的减少。
   选项 .retries表示如果第一次查找后端服务器失败,则就尝试.retries次去查找可用的服务器。每次尝试都是以迭代的方式,重用前一次的分发种子。其中,对于random director的实现细节并不重要,因为它每次返回的结果都是不同的;而对于hash和client director来说,则意味着同一个URL或同一个client在连接同一台服务器时,始终都会是失败的。它的默认值等于在director中所包含的服务器的数量。
    4.1.1. The random director
 它使用一个随机数作为分发种子来选择后端服务器。
    4.1.2. The client director
 它是基于客户端的身份标识来选择后端服务器的。你可设置VCL变量 client.identity来识别客户端。为什么设置此变量就可识别客户端,是因为设置此变量之后,varnish就可以通过取出一个缓存会话的值或者类似的值,进而可以识别客户端了。
    4.1.3. The hash director
 它是通过URL哈希值来选择一个后端服务器的。
 因为缓存对象不会在不同的缓存服务器之间进行复制。所以使用它作为其他Varnish和web加速器的前端负载均衡器是非常有用的。
 它使用的req.hash的值。
 
  4.2.
The round-robin director
     The round-robin director 不带任何的选项。第一次请求使用的第一个后端服务器,第二个请求使用第二个后端服务器等等以此类推,查找到最后一个后在从头开始轮询。
     如果一个后端服务器不可用或者varnish链接它失败,那么这个不可用的服务器会直接被跳过。在放弃之前,所有的后端服务器都会被尝试去连接。
  4.3. The DNS director
     The DNS director 使用后端服务器有两种不同的放置。既可以像random director也可以像round-robin director。或者使用 .list选项,例如:
 director directorname dns {
         .list = {
                 .host_header = "www.example.com";
                 .port = "80";
                 .connect_timeout = 0.4s;
                 "192.168.15.0"/24;
                 "192.168.16.128"/25;
         }
         .ttl = 5m;
         .suffix = "internal.example.net";
 }

上面的例子中,指定了384个后端服务器,所有的都是使用的80端口,连接超时时间是0.4s。所有在.list语句里的的选项必须定义在ip列表之前。.list方法不支持IPv6。它不是一个白名单,它只是一个在varnish内部创建的实际的后端服务器列表。定义的子网越大开销越大。
  .ttl定义DNS查询的缓存时间。
  .suffix表示把其后面的值,追加到客户端提供的Host Header中。
  此director不支持健康检测。支持DNS轮询负载均衡。如果主机名解析后对应多个后端服务器,那么这director将以轮询的方式分派流量。
  4.4. The fallback director
      The fallback director选择第一个可用的后端服务器。它是以服务器定义的顺序依次进行选择的。如果第一个服务器可用,它不会再去尝试连接第二个服务器,除非第一个服务器不可用了。后面的以此类推。
     The fallback director不带任何的选项,例如:

 director b3 fallback {
    { .backend = www1; }
    { .backend = www2; } // will only be used if www1 is unhealthy.
    { .backend = www3; } // will only be used if both www1 and www2
                       // are unhealthy.
 }
    
5. 后端服务器探测
 后端服务器可以通过req.backend.healthy变量返回的探测状态来判断是否可用。
 探测器可以跟的参数有:
  .url 表示指定一个发送到后端服务器的URL请求,默认值是“/”。
  .request 表示指定一个完整的多字符串的HTTP请求,每个字符串后面都会自动的插入\r\n 回车换行符。它的优先级比.url高。
  .window 表示我们要检查确定后端服务器的可用性,所要进行探测的次数。默认是8次。
  .threshold 表示在选项.window中,要成功的探测多少次我们才认为后端服务器可用。默认是3次。
  .initial 表示当varnish启动的时候,要探测多少次后则认为服务器可用。默认值和选项.threshold的值的相同。
  .expected_response 表示你期望后端所返回的HTTP响应代码。默认是200
  .interval 表示每隔多少秒探测一次。默认是每5秒探测一次。
  .timeout 表示每次探测所使用的时间,如果超过设定的时间,就表示此次才探测超时,也就表示此次探测失败。默认是2秒。
  
 要对一个后端进行探测,在定义的时候可以和在定义backend或director的时候一起使用,例如:
  backend www {
   .host = "www.example.com";
   .port = "http";
   .probe = {
   .url = "/test.jpg";
   .timeout = 0.3 s;
   .window = 8;
   .threshold = 3;
   .initial = 3;
    }
  }
 或者,可以单独的定义,然后在进行引用,例如:
  probe healthcheck {
     .url = "/status.cgi";
     .interval = 60s;
     .timeout = 0.3 s;
     .window = 8;
     .threshold = 3;
     .initial = 3;
     .expected_response = 200;
  }

  backend www {
    .host = "www.example.com";
    .port = "http";
    .probe = healthcheck;
  }
 如果有很多后端,那么使用引用的方式会是配置简化许多。
 
 当然,也可指定一个原始的HTTP请求,例如:
  probe rawprobe {
   # NB: \r\n automatically inserted after each string!
   .request =
     "GET / HTTP/1.1"
     "Host: www.foo.bar"
     "Connection: close";
  }

6. ACLs
 通过ACL的声明可以创建并初始化以指定名称的访问控制列表。这个访问控制列表是被用来匹配客户端的地址的,例如:
  acl local {
    "localhost";         // myself
    "192.0.2.0"/24;      // and everyone on the local network
    ! "192.0.2.23";      // except for the dialin router
  } 
 如果ACL的一条记录指定了一个Varnish不能解析的主机名的话,那么它将与它比较的任何地址来进行匹配。如果这个地址以逻辑非符号!开头的话,那么它将会拒绝与它比较的任何地址来匹配。如果这条记录使用圆括号括起来,那么这条记录就被忽略了。
  如果要匹配ACL列表中的IP地址,只需使用匹配操作符即可:
   if (client.ip ~ local) {
    return (pipe);
   }
7. Regular Expressions (正则表达式)
 Varnish使用PCRE(即,兼容Perl的正则表达式)。如果要发送标记给PCRE引擎,比如要打开不区分大小写功能,可以在一个圆括号中使用一个问号标记,就像这个样子:
  # If host is NOT example dot com..
  if (req.http.host !~ "(?i)example.com$") {
    ...
  }

8. Functions (函数)
 可用的内嵌函数有:
  hash_data(str):表示添加一个字符串作为hash输入。在default.vcl文件中,hash_data()的调用主要是在host和URL的请求上。
   
  regsub(str,regex,sub): 表示在字符串str中,使用sub来替换正则表达式首次匹配的字符。在sub里,\0(也可写为\&)表示替换整个匹配的字符串。\n表示替换匹配的正则表达式中的第n个分组字符串。
  regsuball(str,regex,sub):它和regsub()一样,但是替换的不是首次出现的而是所有的匹配内容。
  
  ban(ban expression):禁止所有缓存中匹配表达式的对象。
  
  ban_url(regex):禁止所有缓存中配正则表达式的URLs。
  
9. Subroutines(子程序)
 子程序可以将代码分组,这样可以提高代码的可读性或重复利用性,例如:
 sub pipe_if_local {
   if (client.ip ~ local) {
  return (pipe);
   }
 }
 在VCL中的子程序既不带参数,也不返回值。可以通过使用call关键字后跟子层序的名称来调用子程序,例如:
 call pipe_if_local;
 
 在Varnish中,有一些特殊的子程序(其实它们属于varnish内嵌的子程序)是和Varnish的工作流程相挂钩的。这些子程序可以检查和操作HTTP头部、每个请求的其他的不同检查、和在一定能的程度上决定请求应该如何被处理。每个子程序的结束可以通过调用少量关键字(按照你的期望输出的结果来选择关键字)中的一个来实现。这些特殊的子程序有:
  vcl_init:
   它是当VCL加载,任何请求通过它之前调用的。通常用于初始化VMODs。
   return()的返回值有:
    ok,表示正常返回,VCL将继续加载。
  vcl_recv:
  它是在一个请求开始,完整的请求被接收和解析后调用。它的目的是判定是否要为这个请求提供服务,应该如何处理它,如果可以处理它,又该为它选择哪个后端服务器。
  它结束时,可以通过return()调用的关键字有:
   error code[reason]:表示将指定的错误代码返回给客户端,并丢弃请求。
   pass:表示切换到pass模式。最终,将控制权转交给vcl_pass。
   pipe:表示切换到pipe模式。最终,将控制权转交给vcl_pipe。
   lookup: 表示在缓存中查找请求对象。最终,控制权将转交给vcl_hit或vcl_miss,具体转交给谁,这要取决于对象是否在缓存中。此时,变量bereq.request的值将被设置为GET方法,而不管req.request的值是什么样。
  vcl_pipe:
   它是在要求进入pipe模式的时候调用。在这种模式里,请求会被传递到后端服务器,并且不管后来的数据是来自客户端还是服务器都会不做任何改变的传送,一直到连接到关闭。
   它结束时,可以通过return()调用的关键字有:
    error code[reason]:表示将指定的错误代码返回给客户端,并丢弃请求
    pipe:表示使用pipe模式进行处理。
  vcl_pass:
   它是在进入pass模式的时候调用。在这种模式里,请求会被直接发送给后端服务器,后端服务器的响应也会直接传递给客户端,但是请求的数据和响应的数据都不会进入缓存。后续的由同一客户端提交的请求连接会正常被处理。
   它结束时,可以通过return()调用的关键字有:
    error code[reason]:表示将指定的错误代码返回给客户端,并丢弃请求
    pass:表示使用pass模式处理。
    restart:表示重启事务。设置此值可以使重启计数器的计数增加。如果重启的次数高于变量 max_restarts的次数,Varnish将会发出一个错误。
  vcl_hash:
   可在在此调用内嵌函数hash_data(),来对你想要添加哈希值的数据来添加hash值。
   它结束时,可以通过return()调用的关键字有:
    hash:表示进行哈希处理。
  vcl_hit:
   它是在所请求的文档在缓存中查找到之后调用的。
   它结束时,可以通过return()调用的关键字有:
    deliver:表示也许会先将对象插入到缓存中,然后在将它投递给客户端。控制权最终会转交给vcl_deliver。
    error code[reason]:表示将指定的错误代码返回给客户端,并丢弃请求
    pass:表示切换至pass模式,控制权最终会转交给vcl_pass。
    restart:表示重启事务。设置此值可以使重启计数器的计数增加。如果重启的次数高于变量 max_restarts的次数,Varnish将会发出一个错误。
  vcl_miss:
   它是在所请求的文档在缓存中没有查找到之后调用的。它的目的是决定是否要尝试重新从后端服务器取回所请求的文档,并决定从哪个后端服务器取回。
   它结束时,可以通过return()调用的关键字有:
    error code[reason]:表示将指定的错误代码返回给客户端,并丢弃请求
    pass:表示切换至pass模式,控制权最终会转交给vcl_pass。
    fetch:表示重新从后端服务器取回所请求的对象。控制权最终转交给vcl_fetch。   
   
  vcl_fetch:
   它是在一个文档成功的从后端获取后调用。
   它结束时,可以通过return()调用的关键字有:
    error code[reason]:表示将指定的错误代码返回给客户端,并丢弃请求
    deliver:表示也许会先将对象插入到缓存中,然后在将它投递给客户端。控制权最终会转交给vcl_deliver。
    hit_for_pass:表示传递从后端取回的数据。使用此返回值将会创建hit_for_pass对象。需要注意的是hit_for_pass对象的TTL值是被设置为beresp.ttl的当前值。当前的请求将会由vcl_deliver处理,但是后续的基于hit_for_pass对象的请求将会直接由vcl_pass来处理。
    restart:表示重启事务。设置此值可以使重启计数器的计数增加。如果重启的次数高于变量 max_restarts的次数,Varnish将会发出一个错误。
  vcl_deliver:
   它是在缓存对象都递给客户端之前调用。
   它结束时,可以通过return()调用的关键字有:
    deliver:表示投递对象到客户端。
    restart:表示重启事务。设置此值可以使重启计数器的计数增加。如果重启的次数高于变量 max_restarts的次数,Varnish将会发出一个错误。
  vcl_error:
   它是在当遇到一个错误的时候调用,这个错误时既可能明确是由于后端服务器引起的,也可能是由于varnish内部引起的不明显的错误。
   它结束时,可以通过return()调用的关键字有:
    deliver:表示投递错误对象给客户端。
    restart:表示重启事务。设置此值可以使重启计数器的计数增加。如果重启的次数高于变量 max_restarts的次数,Varnish将会发出一个错误。
  vcl_fini:
   它是仅在所有的请求退出VCL之后,VCL取消时调用。通常用于清理VMODs。
   return()的返回值有:
    ok,表示正常返回,VCL将被取消。
  如果以上这些子程序中有一个被遗漏而未定义的话,或者结束的时候没有最终的处理。那么控制权将转交给内置的默认代码。
  
10. Multiple subroutines
 如果在主vcl配置文件中,可能会有include指令包含进来的多个子vcl配置文件。这样就会出现一种情况就是不同子vcl配置文件中的内嵌子程序代码会出现多次。这些名称重复的子程序代码,处理的顺序是以它们代码出现的先后顺序来处理的。例如:
  # in file "main.vcl"
  include "backends.vcl";
  include "ban.vcl";

  # in file "backends.vcl"
  sub vcl_recv {
    if (req.http.host ~ "(?i)example.com") {
   set req.backend = foo;
    } elsif (req.http.host ~ "(?i)example.org") {
   set req.backend = bar;
    }
  }

  # in file "ban.vcl"
  sub vcl_recv {
    if (client.ip ~ admin_network) {
   if (req.http.Cache-Control ~ "no-cache") {
     ban_url(req.url);
   }
    }
  }
11. Variables(变量)
 虽然子程序不带参数,但是通过全局变量对子程序的一些必要信息的处理还是非常有用的。
 其中可用的变量有:
  now:表示当前的时间,以秒为单位,时间的计算是从epoch开始的。当在字符串的上下文中使用时,它返回一个格式化后的字符串。

 以下的变量在backend的声明中是可用的:
  .host:后端服务器的主机名或IP地址。
  .port:后端服务器的服务名称或端口号
 以下的变量在处理一个请求的时候可用:
  client.ip: 表示客户端的IP地址。
  client.identity: 表示客户端识别,常被用于client director的负载均衡。
  server.hostname:表示服务器的主机名。
  server.identity:表示服务器的身份标识,可以通过-i参数来设置。如果没有将-i参数传递给varnishd,那么变量server.identity参数将被设置为由-n参数指定的的实例名称。
  server.ip:表示接收客户端连接的socket里的ip地址。
  server.port: 表示接收客户端连接的socket里的port。
  req.request:表示请求的类型(例如,GET, HEAD)
  req.url:表示所请求的URL。
  req.proto:表示客户端使用的HTTP协议的版本。
  req.backend:表示要为请求提供服务所使用的后端服务器,它的值一般是声明backend时所用的名字。
  req.backend.healthy:表示后端服务器是否健康可用。要使用此变量,则需要在backend段的配置中,配置一个活动探测器。
  req.http.header:表示各个相对应的HTTP头部变量,例如,req.http.host、req.http.Accept-Encoding等等。只需将hearder换成对应的头部信息即可。
  req.hash_always_miss:表示强制清除这个请求的缓存。如果将它的值设置为true,则varnish将忽略已存在的任何缓存对象,直接从后端服务器来取数据。
  req.hash_ignore_busy:表示忽略所有在缓存查找期间处于繁忙状态的对象。如果你开启了两个varnish服务进程并且它们彼此之间都在相互查找数据,那么就可以通过设置此变量来避免可能出现的死锁现象。
  req.can_gzip:表示客户端可以接收gzip传输编码。
  req.restarts:表示请求被重新启动的次数。
  req.esi:它的值是布尔值。如果设置为false,那么将会禁用ESI处理而不管beresp.do_esi变量所这设置的值。默认值是true,此值在以后的版本中会改变,因此应该避免使用此值。
  req.esi_level:表示当前ESI请求所处的级别。
  req.grace:表示设置启用grace的周期。
  req.xid:表示请求的唯一ID。
 
 以下变量是当varnish向后端服务器发送请求时可用,(要发送请求的情况有缓存丢失miss模式或pass模式或pipe模式):
  bereq.request:表示请求的类型(例如,GET,HEAD)
  bereq.url:表示要请求的URL
  bereq.proto:表示varnish服务器所使用的HTTP协议的版本。
  bereq.http.header:表示相应的HTTP头信息变量。
  bereq.connect_timeout:表示和后端服务器连接所要等待的时间,单位是秒。
  bereq.first_byte_timeout:表示后端服务器来的第一个字节到达varnish所要等待的时间,单位是秒。此变量在pipe模式中不可用。
  bereq.between_bytes_timeout:表示第一个字节到达后,等待之后的每个字节之间所要等待的时间,单位是秒。
 
 以下的变量在所请求的对象从后端服务器接收以后,放入缓存之前可用。也就是说,它们在内嵌子程序vcl_fetch中可用:
  beresp.do_stream:表示在没有把取回整个对象到varnish的情况下,就可以直接把已接收到的对象投递给客户端。
  beresp.do_esi:它的值是布尔值。表示在取回对象后,对此对象进行ESI处理。默认值是false。如果设置为true,则ESI指令会对对象进行解析。不过只有req.esi设置为true时,它才有意义。
  beresp.do_gzip:它的值是布尔值。表示在存储对象之前先对其进行gzip压缩。默认是false。
  beresp.do_gunzip:它的值是布尔值。表示在存储对象到缓存之前,先对其进行解压缩。默认是值是false。
  beresp.http.header:表示对应的响应的HTTP头信息。
  beresp.proto:表示后端服务器响应时所使用的HTTP的协议版本。
  beresp.status:表示被后端服务器所返回的HTTP状态码。
  beresp.response:表示被后端服务器所返回的HTTP状态信息。
  beresp.ttl:表示对象的存活时间,单位是秒,此变量是可写的。
  beresp.grace:表示设置启用grace的周期。
  beresp.saintmode:表示设置启用saint模式的周期。
  beresp.backend.name:表示取回响应的后端服务器的主机名。
  beresp.backend.ip:表示取回响应的后端服务器的IP地址。
  beresp.backend.port:表示取回响应的后端服务器的端口号。
  beresp.storage:表示强制varnish保存这个对象到一个特殊的存储后端服务器。
 
 在对象进入缓存后,以下的变量(大多数是只读的)当对象已位于缓存的时候是可用的,通常用在内嵌函数vcl_hit中或者是当在vcl_error中构建synthetic回复时:
  obj.proto:表示当重新取回对象时所使用的HTTP协议的版本。
  obj.status:表示被varnish服务器所返回的HTTP状态码。
  obj.response:表示被varnish服务器所返回的HTTP状态信息。
  obj.ttl:表示对象的存活时间,单位是秒,此变量是可写的。
  obj.lastuse:表示自从上次请求以来,所过去的大概时间,单位是秒。此变量在vcl_deliver中也是可用的。
  obj.hits:表示对象已经被投递的大概次数。它的值若为0,则表明缓存丢失了。此变量在vcl_deliver中也是可用的。
  obj.grace:表示对象的宽限时间,单位是秒。此变量是可写的。
  obj.http.header:表示对应的HTTP头部。
  
 以下变量,在要判定对象hash键值时可用:
  req.hash:表示一个缓存中经常被使用的对象的hash值。它可用在从缓存中读取或写入缓存中时。
  
 以下变量,当在准备响应客户端时可用:
  resp.proto:表示响应所使用的HTTP协议版本。
  resp.status:表示返回给客户端的HTTP状态码。
  resp.response:表示返回给客户端的HTTP状态信息。
  resp.http.header:表示对应的HTTP头信息。
 
 在要给以上所有变量分配值的时候,使用set关键字,例如:
  sub vcl_recv {
   if(req.http.host ~ "(?i)(www.)?example.com#") {
    set req.http.host = "www.example.com";
   }
  }
 HTTP的头部信息可以使用remove关键字来完全的删除,例如:
  sub vcl_fetch {
   remove beresp.http.Set-Cookie;
  }

12. Grace and saint mode(grace 和 saint模式)
 如果后端服务器生成一个对象需要很长时间的话,那么就会产生线程堆积的风险。为了避免这种情况的发生,你可以启用grace。它允许varnish在后端服务器在生成新对象的过程中,提供一个过期版本的对象。
 
 以下的vcl代码将会让varnish提供一个过期的对象。所有的对象在过期后或者新对象生成后,将会被保留两分钟:
  sub vcl_recv {
    set req.grace = 2m;
  }
  sub vcl_fetch {
    set beresp.grace = 2m;
  }
 
 saint模式类似于grace模式,它们依赖于相同的基础架构,但功能却不同。你可以向vcl_fetch中添加VCL代码来查看来自后端服务器的响应是否是你想要的。如果你发现响应并不是你想要的,那么你可以通过beresp.saintmode变量设置一个时间期限并调用restart。然后,varnish将会重新连接其他的后端服务器来尝试再取回想要的对象。
 
 如果没有多台后端服务器或者restart的次数已经达到max_restarts的设置值,并且还存有一个比beresp.saintmode变量设置的时间还要新的对象,那么varnish将要提供这个对象,即使它比较陈旧。

13. Examples (例子)
 以下的代码就相当于默认的配置。只不过使用的后端服务器地址是"backend.example.com",没有指定后端服务器端口号:
 
 backend default {
  .host = "backend.example.com";
  .port = "http";
 }
 
 sub vcl_recv {
  if (req.restarts == 0) {
   if (req.http.x-forwarded-for) {
    set req.http.X-Forwarded-For = req.http.X-Forward-For + ",“ + client.ip;
   } else {
    set req.http.X-Forwarded-For = client.ip;
   }
  }
  /*表示如果是非标准的请求方法或是一些很怪的方法那么就直接交由后端服务器处理*/
  if (req.request != "GET" &&
   req.requesq != "HEAD" &&
   req.requesq != "PUT" &&
   req.requesq != "POST" &&
   req.requesq != "TRACE" &&
   req.requesq != "OPTIONS" &&
   req.requesq != "DELETE" &&
  ) {
   return (pipe);
  }
  /*表示varnish服务器之处里GET和HEAD方法,其他的交由后端服务器处理*/
  if (req.requesq != "GET" && req.requesq != "HEAD") {
   return (pass);
  }
  if (req.http.Authorization || req.http.Cookie) {
   return (pass);
  }
  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 (beresp.ttl <= 0s ||
   beresp.http.Set-Cookie ||
   beresp.http.Vary == ”*“ ) {
    set beresp.ttl = 120s;
    return (hit_for_pass);
  }
  return (deliver);
 }
 
 sub vcl_error {
  set obj.http.Content-Type = "text/html; charset=utf-8";
  set obj.http.Retry-After = "5";
  synthetic {"
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
  <head>
    <title>"} + obj.status + " " + obj.response + {"</title>
  </head>
  <body>
    <h1>Error "} + obj.status + " " + obj.response + {"</h1>
   

"} + obj.response + {"


    <h3>Guru Meditation:</h3>
   

XID: "} + req.xid + {"


    <hr>
   

Varnish cache server


  </body>
</html>
"};
    return (deliver);
 }
 sub vcl_init {
  return (ok);
 }
 sub vcl_fini {
  return (ok);
 }
下面的例子显示了在同一个varnish配置文件中,如何去支持运行在不同后端服务器的多个站点,选择后端服务器的方式是基于请求的URL:
 backend www {
  .host = "www.example.com";
  .port = "80";
 }
 backend images {
  .host = "images.example.com";
  .port = "80";
 }
 sub vcl_recv {
  if (req.http.host ~ "(?i)^(www.)?example.com") {
   set req.http.host = "www.example.com";
   set req.backend = www;
  } elsif (req.http.host ~ "(?i)^images.example.com$") {
   set req.backend = images;
  } else {
   error 404 "Unknown virtual host";
  }
 }
下面的一小段示例代码,显示如何对所有的文档强制使用一个最小的TTL。需要注意的是这个桶default_ttl参数是不一样的。因为它只对那些后端服务器没有指定TTL的文档有影响:
 import std; #此处导入的是std.log
 sub vcl_fetch {
  if (beresp.ttl < 120s) {
   std.log(”Adjusting TTL“);
   set beresp.ttl = 120s;
  }
 }
下面的代码示例,显示如何强制Varnish缓存文档,即使当cookie存在的时候:
 sub vcl_recv {
  if (req.request == "GET" && req.http.cookie) {
   return(lookup);
  }
 }
 sub vcl_fetch {
  if (beresp.http.Set-Cookie) {
   return(deliver);
  }
 }
下面的代码实现了HTTP PURGE的方法,来使对象失效,此方法和在Squid中所使用的一样。
 acl purge {
  "localhost";
  "192.0.2.1"/24;
 }
 sub vcl_recv {
  if (req.request == "PURGE") {
   if (!client.ip ~ purge) {
    error 405 "Not allowed.";
   }
   return (lookup);
  }
 }
 sub vcl_hit {
  if (req.request == "PURGE") {
   purge;
   error 200 "Purged.";
  }
 }
 sub vcl_miss {
   if (req.request == "PURGE") {
  purge;
  error 200 "Purged.";
   }
 }

 


路过

鸡蛋

鲜花

握手

雷人

发表评论 评论 (4 个评论)

回复 syflove2008 2013-7-31 17:20
辛苦了~~~
回复 syflove2008 2013-7-31 17:20
不知为什么Varnish使用的就是少,这么好用的程序为什么比不上Squid呢~~~
回复 yonchin_great 2013-8-2 12:46
syflove2008: 不知为什么Varnish使用的就是少,这么好用的程序为什么比不上Squid呢~~~
这只是时间的问题,过不多久varnish定能逐渐取代squid,
因为在现在高性能的硬件和系统上,squid已经无法发挥它们的优势,定会逐渐被淘汰,所以越早学好varnish对我们来说还是有优势的。
回复 syflove2008 2013-8-4 10:34
  

facelist

您需要登录后才可以评论 登录 | 注册

Archiver|手机版|感谢所有关心和支持过LinuxTone的朋友们 转载本站内容请注明原作者名及出处 ( 京ICP备08103151 )   |

GMT+8, 2019-6-20 06:55 , Processed in 0.009755 second(s), 10 queries , Apc On.

Powered by Discuz! X2 Licensed

© 2001-2011 Comsenz Inc.

回顶部