varnish04-varnish如何使用VCL
1、VCL基础
- Varnish Configuration Language (VCL)是一种特定于领域的语言,可以用于描述Varnish Cache服务如何处理请求和缓存策略。当加载新配置时,由Manager进程创建的VCC进程将VCL代码转换为C。该C代码通常由gcc编译为共享对象,然后将共享对象加载到缓存进程中。
- varnish说明:http://book.varnish-software.com/4.0/chapters/VCL_Basics.html#subroutines-legal-returns-client
1.1、Varnish是有限状态机
- VCL工作流被看作是一个有限状态机,如图所示:
- 该图显示了Varnish有限状态机的简化版本,没有列出所有的可能转换,只是其中的一个典型集合

- varnish中的子程序以vcl_开头,例如sub vcl_recv。
- Return(action)终止子程序,其中action是指示下一步操作的关键字。
1、VCL有限状态机
- (1)每个请求都单独处理。
- (2)每个请求在任意时间都独立于其他请求。
- (3)状态是相关的,但又是孤立的。(相关是指一个状态到另一个状态,孤立是指状态之间互不影响)
- (4)return(action)。退出当期状态并指示请求进入到下一个状态。
- (5)内置的VCL代码始终存在,并附加在自定义(您自己)的VCL代码下面。即内置的VCL代码是默认配置。
2、VCL4.0架构原理
- VCL有多个子程序,每个子程序之间存在相关性,但子程序又彼此间互相隔离。每个子程序可使用Return(action)指明关联至哪个下一级子程序。每个子程序对应于vcl文件中的一个配置段,即为subroutine(子程序)。
- 例如,vcl_hash --> return(hit) --> vcl_hit
(1)前端状态可分为四个阶段
第一阶段: vcl_recv #接受客户端请求,对请求方法进行判断 第二阶段: vcl_hash #进行hash计算,不进行处理,计算之后送往各个第三阶段子程序中 第三阶段: vcl_hit #缓存命中,到此处理 vcl_pass #缓存跳过 vcl_miss #缓存未命中 vcl_purge #清理缓存 vcl_pipe #对于无法识别的http请求方法直接送入管道,交由后端处理不再处理 第四阶段: vcl_deliver #大部分响应客户端的请求由此发送回去 vcl_synth #接受来自vcl_purge的任务,对指定的缓存,进行删除处理
(2)后端状态分为两阶段
第一阶段: vcl_backend_fetch #接受来自前端状态vcl_pass或vcl_miss 的任务,向后端主机请求 第二阶段: vcl_backend_response #接受到后端返回正常状态报文,进行是否缓存检查,需要缓存的响应将其缓存,不需要则不缓存,最后送到vcl_deliver vcl_backend_error #后端主机错误,返回错误响应
(3)两个特殊的子程序
- vcl_init:在处理任何请求之前要执行的vcl代码。主要用于初始化VMODs。
- vcl_fini:所有的请求都已经结束,在vcl配置被丢弃时调用。主要用于清理VMODs。
1.2、VCL语法
1、VCL的基本语法
- (1)vcl配置文件以"vcl 4.0"开头。
- (2)使用C语言的注释风格://、#和/* foo */
- (3)子程序使用sub关键字声明, 例如sub vcl_recv { ...}。
- (4)不支持循环,有状态限制的变量。(变量和子程序相关,即一个变量只能用在某些子程序中)
- (5)每一个子程序都使用return(action)结束,并指明下一个子程序,action为关键字。例如,return(pass)
- (6)区域专用,所有的配置都只用于一个域
- (7)引用VCL配置文件。例如,include "foo.vcl";
- (8)加载varnish模块(VMODs)。例如,import foo;
2、VCL配置文件
- 从Varnish 4.0开始,每个VCL文件必须以"VCL 4.0"开头(在文件顶部)。
- 块由花括号分隔,语句以分号结束。
- VCL中的子程序既不接受参数,也不返回值。VCL中的子程序只能通过HTTP报头交换数据。
- VCL有终止语句,而不是传统的返回值。子程序在执行return(*action*)语句时结束执行。动作告诉Varnish下一步要做什么。例如,“在缓存中查找这个”,“不要在缓存中查找这个”,或者“生成一个错误消息”。
- VCL有两个指令来引用另一个文件的内容。即include和import,用于不同的目的。
3、VCL中的三种语句
//声明一个子函数
sub subroutine {
...
}
//结束子函数,并指定下一步
return()
//判断语句
if CONDITION {
...
} else {
...
}
1.3、VCL的内置函数、关键字和操作符
- 内置函数:允许修改字符串、添加禁令、重新启动VCL状态引擎并将控制返回到Varnish运行时(VRT)环境。
- regsub(str, regex, sub):以字符串str作为输入,用正则表达式regex匹配它,并用另一个字符串替换它,只更改第一个匹配项。
- regsuball(str, regex, sub):以字符串str作为输入,用正则表达式regex匹配它,并用另一个字符串替换它,更改所有匹配项。
- ban(boolean expression):将使缓存中与布尔表达式匹配的所有对象失效。
- hash_data(input):指定哈希计算的数据。减少差异,以提升命中率。
- synthetic(str)
- 所有的函数在所有子程序中都是可用的,除了下表中列出的函数。

- 关键字:
- call subroutine
- return(action)
- new
- set
- unset
- 操作符:
- 比较操作符:==、!=、>、>=、<、<=
- 逻辑操作符:&&、||、!
- 正则匹配:~
- (?i)表示忽略大小写
- 字符串需要使用双引号""
- 变量赋值:=
示例:
//obj.hits是内建变量,用于保存某缓存项的从缓存中命中的次数;
if (obj.hits>0) {
set resp.http.X-Cache = "HIT via " + server.ip;
} else {
set resp.http.X-Cache = "MISS via " + server.ip;
}
1.4、子程序可以使用的动作(Action)
- 子程序的return中可以使用的动作(Action)有:lookup、synth、purge、pass、pipe、fetch、deliver、hash、restart、retry和abandon。
- VCL的frontend子程序可以使用的动作(Action)

- VCL的backend子程序可以使用的动作(Action)

1.5、VCL子程序中的变量

- 内置变量:
- req.*:request,由客户端发送到varnish的请求报文。
- req.http.*
- req.http.User-Agent、req.http.Referer、...
- bereq.*:由varnish发往后端服务器的请求报文。
- bereq.http.*
- beresp.*:由后端服务器响应给varnish的响应报文。
- beresp.http.*
- resp.*:由varnish响应给客户端的响应报文
- obj.*:存储在缓存空间中的缓存对象的属性(只读)。
- req.*:request,由客户端发送到varnish的请求报文。
- 常用内置变量:
- bereq.*和req.*:
- bereq.http.HEADERS:请求头
- bereq.request:请求方法。
- bereq.url:请求的url。
- bereq.proto:请求的协议版本。
- bereq.backend:指明要调用的后端主机。
- req.http.Cookie:客户端的请求报文中Cookie的值(req专用)
- req.http.User-Agent:浏览器类型(req专用)
- beresp.*和resp.*:
- beresp.http.HEADERS:响应头。
- beresp.status:响应的状态码。
- beresp.proto:协议版本。
- beresp.backend.name:BE主机的主机名。
- beresp.ttl:BE主机响应的内容的余下的可缓存时长。
- obj.*:
- obj.hits:此对象从缓存中命中的次数。
- obj.ttl:对象的ttl值,缓存时长。
- obj.grace:缓存宽限时间。
- server.*:
- server.ip:varnish自己的ip地址。
- server.hostname:varnish自己的主机名。
- server.port:varnish自己的端口。
- client.*:
- client.ip
- client.hostname
- client.port
- bereq.*和req.*:
- 用户自定义变量:
- set
- unset
- VCL子程序中的变量可用性

- 请求(req.)变量的值自动分配给后端请求(bereq.)变量。但是,这些值可能略有不同,因为Varnish可能会修改客户端请求。例如,来自客户端的HEAD请求可以转换为对后端的GET请求。
- 后端响应(beresp.)变量的更改会影响响应(resp.)和对象(obj.)变量。obj变量赋值给resp变量,可以将obj变量发送给客户端。
2、VCL子程序
- VCL子程序的特性:
- 可定制的VCL子程序有:vcl_recv、vcl_pass、vcl_backend_fetch、vcl_backend_response、vcl_hash、vcl_hit、vcl_miss、vcl_deliver和vcl_synth。
- 如果自定义VCL子程序没有return,则跳过内置VCL子程序。
- 内置VCL子程序总是附加到自定义VCL子程序中。
- 可以在VCL子程序中自定义Varnish的行为。
- 例如,添加自定义报头、更改Varnish错误消息的外观、在Varnish中添加HTTP重定向功能、清除内容以及定义缓存对象的哪些部分是唯一的。
- 注意,只要可能,强烈建议使用默认的内置子程序。内置子程序在设计时考虑到了安全性,这通常意味着它们能够以合理的方式处理VCL代码中的任何缺陷。
- 处理客户端请求的流程图:

- 将请求发送到后端服务器的流程图:

2.1、vcl_recv子程序
- vcl_recv是在Varnish将客户端请求解析为其基本数据结构之后执行的第一个VCL子程序。
- vcl_recv子程序的特性:
- 规范化客户端输入
- 重写的客户端数据
- 修复错误。例如,index.htlm -> index.html
- 根据客户端输入决定缓存策略
- 为请求选择一个后端服务器
- 访问控制列表(ACL)
- 安全屏障,如SQL注入攻击
- vcl_recv有四个主要用途:
- 修改客户端数据以减少缓存多样性。例如,删除Host头中的“www.”。
- 决定使用哪个web服务器。
- 根据客户端数据确定缓存策略。例如,不缓存POST请求,但缓存特定的url。
- 执行特定web应用程序所需的重写规则。
- vcl_recv中的return可以使用的动作(action):
- pass:会跳过缓存查找(lookup),但会执行Varnish后续的工作流程,且不会缓存后端服务器的响应。
- pass适用于处理静态页面,如GET/HEAD请求等。POST请求一般用于处理动态数据,不适用pass处理策略。
- pipe:会创建一个全双工管道,将客户端请求直接转发到后端服务器,Varnish不会检查该请求,也不会对其进行处理。后端服务器的响应也直接被转发到客户端上,且不会缓存后端服务器的响应。由于Varnish不再尝试将内容映射到请求,因此通过同一个keep-alive连接发送的任何后续请求也将通过管道传输。管道请求不会出现在任何日志中。
- pipe不缓存数据,适用于请求类型,即通过POST类型进行文件上传、下载等操作,还适用于变更频率较大的数据,如热点数据等。
- hash:在缓存中查找请求。
- purge:在缓存中查找请求,以便删除其缓存。
- synth:Varnish直接生成一个响应报文,并响应给客户端。这种响应通常是一个带有错误消息的网页。Synth也可以用来重定向客户端请求。
- pass:会跳过缓存查找(lookup),但会执行Varnish后续的工作流程,且不会缓存后端服务器的响应。
示例1:
- 内置的vcl_recv
sub vcl_recv {
if (req.method == "PRI") {
/* We do not support SPDY or HTTP/2.0 */
return (synth(405));
}
if (req.method != "GET" &&
req.method != "HEAD" &&
req.method != "PUT" &&
req.method != "POST" &&
req.method != "TRACE" &&
req.method != "OPTIONS" &&
req.method != "DELETE") {
/* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
if (req.method != "GET" && req.method != "HEAD") {
/* We only deal with GET and HEAD by default */
return (pass);
}
if (req.http.Authorization || req.http.Cookie) {
/* Not cacheable by default */
return (pass);
}
return (hash);
}
示例2:
- 为移动设备和桌面浏览器提供不同内容的一种方法是在User-Agent报头上运行一些简单的解析。下面的VCL代码是创建自定义标头的示例。这些自定义头将移动设备与桌面计算机区别开来。
sub vcl_recv {
if (req.http.User-Agent ~ "iPad" ||
req.http.User-Agent ~ "iPhone" ||
req.http.User-Agent ~ "Android") {
set req.http.X-Device = "mobile";
} else {
set req.http.X-Device = "desktop";
}
}
示例3:
- 重写URL和主机报头字段
sub vcl_recv {
set req.http.x-host = req.http.host;
set req.http.x-url = req.url;
#删除域名中的前缀"www."
set req.http.host = regsub(req.http.host, "^www\.", "");
#删除域名中的前缀"sport.",并重写uri。例如http://sport.example.com/index.html --> http://example.com/sport/index.html
if (req.http.host == "sport.example.com") {
set req.http.host = "example.com";
set req.url = "/sport" + req.url;
}
##删除域名中的前缀"sport.",并重写uri。
if (req.http.host ~ "^sport\.") {
set req.http.host = regsub(req.http.host,"^sport\.", "");
set req.url = regsub(req.url, "^", "/sport");
}
}
2.2、vcl_pass子程序
- vcl_pass子程序被return(pass)调用。并将请求设置为通过模式。vcl_pass通常是在vcl_hit和vcl_miss中被调用。
- vcl_pass中的return可以使用的动作(action):fetch、synth和restart
- fetch:将当前请求以pass模式继续。从pass模式的请求中获取的对象不会被缓存,而是传递给客户端。
- synth和restart:调用它们相应的子程序。
- hit-for-pass:当一个对象不应该被缓存时,应该使用Hit-for-pass对象,而不是fetch对象。hit-for-pass对象有有TTL。
- 一些请求的对象(响应报文)不应该被缓存。一个典型的例子是当被请求的页面包含Set-Cookie响应头时,必须将它只被传递给请求它的客户端。在这种情况下,可以创建一个hit-for-pass对象并将其存储在缓存中,而不是存储所获取的对象(响应报文)。后续请求以pass模式处理。
- 当一个对象(响应报文)不应该被缓存时,beresp.uncacheable变量被设置为true。因此,缓存进程保持对hit-for-pass对象的哈希引用。通过这种方式,转换到该散列的请求的查找操作会找到一个hit-for-pass对象。这样的请求被移交给vcl_pass子程序,并以pass模式进行。
- 与任何其他缓存对象一样,hit-for-pass对象也有一个TTL。一旦对象的TTL结束,就会从缓存中删除。
示例:
- 内置的vcl_pass
sub vcl_pass {
return (fetch);
}
2.3、vcl_backend_fetch子程序
- vcl_backend_fetch可以从vcl_miss或vcl_pass调用。
- 如果从vcl_miss调用vcl_backend_fetch,所获取的对象(响应报文)可能会被缓存。
- 如果从vcl_pass调用vcl_backend_fetch,即使obj.ttl或obj.keep变量大于0,所获取的对象(响应报文)也不会被缓存。
- 一个相关的变量是bereq.uncacheable。此变量指示从后端请求的对象(响应报文)是否可以缓存。但是,不管bereq.uncacheable是什么,响应pass请求的所有对象(响应报文)都不会被缓存。
- vcl_backend_fetch中的return可以使用的动作(action):fetch和abandon
- fetch:将请求发送到后端,而放弃调用vcl_synth子程序。
- 后端响应由vcl_backend_response或vcl_backend_error处理,具体取决于来自服务器的响应。如果Varnish收到一个语法正确的HTTP响应,Varnish将控制权传递给vcl_backend_response。语法正确的HTTP响应包括HTTP 5xx错误代码。如果Varnish没有收到HTTP响应,它将控制权传递给vcl_backend_error。
示例:
- 内置的vcl_backend_fetch
sub vcl_backend_fetch {
return (fetch);
}
2.4、vcl_hash子程序
- vcl_hash总是在vcl_recv之后或当另一个子程序的return(hash)调用。
- vcl_hash创建用于缓存对象的hash键。hash键可以区分不同的缓存对象。vcl_hash的默认VCL将主机名或IP地址以及请求的URL添加到缓存散列中。
- vcl_hash中的return可以使用的动作(action):lookup
- lookup是一种查找操作,而不是子程序。vcl_hash之后要访问哪一个子程序取决于lookup在缓存中找到的内容。
- lookup操作的结果有四种可能:hit、miss、hit-for-pass和busy
- 当lookup操作匹配不到任何hash键时,它会创建一个带有busy(繁忙)标志的对象,并将其插入缓存中。然后,请求被发送到vcl_miss子程序。一旦处理了请求,busy标志将被删除,对象将使用后端响应进行更新。
- 随后遇到busy标记对象的类似请求被发送到等待列表。此等待列表旨在提高响应性能,它将解释等待状态部分。
示例:
- 内置的vcl_hash
sub vcl_hash {
hash_data(req.url);
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
return (lookup);
}
2.5、vcl_hit子程序
- lookup操作(vcl_hash中的lookup)找到请求的对象时,调用的vcl_hit子程序。
- vcl_hit中的return通常使用的动作(action)有:deliver、restart和synth
- deliver:如果对象的"TTL + 宽限期"还没有过去,return(deliver)会调用vcl_deliver。如果经过的时间大于TTL,但小于"TTL + 宽限时间",则将从后端服务器获取响应,然后调用vcl_deliver。(即vcl_hit{} --> BGFETCH --> vcl_deliver{})
- Restart:重新启动事务,并增加重新启动计数器。如果重启次数高于max_restart计数器,vrnish会报出异常。
- synth(status code, reason):返回指定的状态码给客户端,并放弃请求。
示例:
- 内置的vcl_hit
sub vcl_hit {
if (obj.ttl >= 0s) {
// A pure unadultered hit, deliver it
return (deliver);
}
if (obj.ttl + obj.grace > 0s) {
// Object is in grace, deliver it
// Automatically triggers a background fetch
return (deliver);
}
// fetch & deliver once we get the result
return (fetch);
}
2.6、vcl_miss子程序
- lookup操作(vcl_hash中的lookup)没有找到请求的对象时,调用的vcl_miss子程序。
- vcl_miss子程序可以用于决定是否尝试从后端检索文档,以及使用哪个后端。
- vcl_hit和vcl_miss是密切相关。
- 很少定制它们,因为HTTP请求头的修改通常在vcl_recv中完成。然而,如果不希望将X-Varnish头发送到后端服务器,可以在vcl_miss或vcl_pass中删除它。例如,"unset bereq.http.x-varnish;"。
示例:
- 内置的vcl_miss
sub vcl_miss {
return (fetch);
}
2.7、vcl_deliver子程序
- vcl_deliver是所有请求工作流的公共最后出口点,通过vcl_pipe的请求除外。通常用于添加和删除调试用的header头(debug-headers)。
- vcl_deliver中最有用和最常修改的变量是:
- resp.http.*
- resp.status
- resp.reason:返回给客户端的HTTP状态消息。
- obj.hits
- req.restarts:VCL中发出的重启次数。如果没有发生则为0。
示例:
- 内置的vcl_deliver
sub vcl_deliver {
return (deliver);
}
2.8、vcl_synth子程序
- varnish直接生成响应报文,并响应给客户端。
- synth()函数必须携带状态代码和原因参数,以传递给vcl_synth。在resp.http可以设置响应报文的header头。
- vcl_synth定义的对象永远不会存储在缓存中,与vcl_backend_error定义的对象相反,vcl_backend_error定义的对象可能最终存储在缓存中。vcl_synth和vcl_backend_error替换Varnish 3中的vcl_error。
示例:
- 内置的vcl_synth
sub vcl_synth {
set resp.http.Content-Type = "text/html; charset=utf-8";
set resp.http.Retry-After = "5";
synthetic( {"<!DOCTYPE html>
<html>
<head>
<title>"} + resp.status + " " + resp.reason + {"</title>
</head>
<body>
<h1>Error "} + resp.status + " " + resp.reason + {"</h1>
<p>"} + resp.reason + {"</p>
<h3>Guru Meditation:</h3>
<p>XID: "} + req.xid + {"</p>
<hr>
<p>Varnish cache server</p>
</body>
</html>
"} );
return (deliver);
}
示例2:
sub vcl_recv {
if (req.http.host == "www.example.com") {
set req.http.location = "http://example.com" + req.url;
return (synth(750, "Permanently moved"));
}
}
sub vcl_synth {
if (resp.status == 750) {
set resp.http.location = req.http.location;
set resp.status = 301;
return (deliver);
}
}
3、VCL配置示例
- 重新加载VCL配置文件的两种方法:
//方法一,使用varnish_reload_vcl命令 ]# varnish_reload_vcl //方法二,varnishadm命令 ]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 varnish> vcl.load test1 default.vcl #重新加载vcl,并指定一个命名test1。如果返回状态码是200,则语法正确,编译通过 varnish> vcl.use test1 #使用名为test1的VCL配置 varnish> vcl.list #查看所有的VCL配置,可以看到当期使用的是test1,其状态是active 200 available 0 boot active 0 test1
3.1、为响应报文增加一个header头
//为响应报文增加一个header头"X-cache",表示是否使用缓存(cache)。HIT是命中缓存,MISS是没有命中缓存。
sub vcl_deliver {
if (obj.hits>0) {
set resp.http.X-cache = "HIT via " + server.ip;
} else {
set resp.http.X-cache = "MISS form "+ server.ip;
}
}
3.2、对特定资源的请求不检查缓存
//如果uri以"/login"或"/admin"开头,则不检查缓存
sub vcl_recv {
if (req.url ~ "(?i)^/(login|admin)") {
return(pass);
}
}
3.3、对特定资源的请求,取消cookie
//对特定的资源的请求,取消其私有标识cookie,并设定其可以由varnish缓存的时长。例如公开的图片等。
sub vcl_backend_response {
if (beresp.http.cache-control !~ "s-maxage") {
if (bereq.url ~ "(?i)\.(jpg|jpeg|png|gif|css|js)$") {
unset beresp.http.Set-Cookie;
set beresp.ttl = 3600s;
}
}
}
3.4、将client的IP传给后端服务器
//将client的IP传给后端服务器,client可能是nginx调度器
sub vcl_recv {
if (req.restarts == 0) {
#只给变量。如果其值是字符串,则非空为真。如果其值是数值型,则非零为真。
if (req.http.X-Fowarded-For) {
set req.http.X-Forwarded-For = req.http.X-Forwarded-For + "," + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
}
}
3.5、禁止使用curl命令
sub vcl_recv {
if (req.http.User-Agent ~ "(?i)curl") {
return(synth(403));
}
}
3.6、清理缓存对象
- 清理缓存对象有两种方法:
- purge:使用purge方法请求一个url,只要该utl被命中,该缓存就会被删除。一次清理一个url的缓存。
- ban:可以使用正则表达式去匹配url,所有被匹配到的url的缓存都会被删。批量清理缓存。
- varnish说明:http://book.varnish-software.com/4.0/chapters/Cache_Invalidation.html
1、purge方法
(1)创建一个能执行purge操作的子函数
sub vcl_purge {
return(synth(200,"Purged"));
}
(2)调用vcl_purge,执行purge操作
sub vcl_recv {
if (req.method == "PURGE") {
return(purge);
}
}
(3)测试
curl -I http://10.1.1.11:8080/index.html curl -X PURGE http://10.1.1.11:8080/index.html
(4)为purge添加访问控制法则
//定义一个子函数(先定义后使用)。注意,地址要加引号,掩码在外面
acl purgers {
"127.0.0.0"/8;
"10.1.1.0"/16;
}
//调用purgers子函数
sub vcl_recv {
if (req.method == "PURGE") {
#调用acl的purgers
if (!client.ip ~ purgers) {
return(synth(405,"Purging not allowed for " + client.ip));
}
return(purge);
}
}
2、ban方法
- 方法一:在varnishadm命令行中使用,直接批量清理缓存,只要url被匹配到就会清理掉
ban <field> <operator> <arg> [&& <field> <oper> <arg>]... //测试 ban req.url ~ ^/javascripts ban req.url ~ .js$ #点不用转义
- 方法二:在配置文件中vcl_recv定义,使用ban()函数(只能对特定资源执行ban)
//调用ban子函数
sub vcl_recv {
if (req.method == "BAN") {
ban("req.http.host == " + req.http.host + " && req.url == " + req.url);
return(synth(200, "Ban added"));
}
}
//测试
ban req.http.host == 10.1.1.11 && req.url == /javascripts/
ban req.url == / && req.http.host ~ “ilinux.io”
curl -I http://10.1.1.11:8080/javascripts/
curl -X BAN http://10.1.1.11:8080/index.html
3.7、定义多个后端服务器
- varnish说明:http://book.varnish-software.com/4.0/chapters/Saving_a_Request.html
1、定义多个后端服务器
#(1)导入模块
import directors;
#(2)定义后端服务器
backend hh1 {
.host = "10.1.1.12";
.port = "80";
}
backend hh2 {
.host = "10.1.1.13";
.port = "80";
}
#(3)定义后端服务器组(round_robin和random)
sub vcl_init {
new hh_group1 = directors.round_robin();
hh_group1.add_backend(hh1);
hh_group1.add_backend(hh2);
new hh_group2 = directors.random();
hh_group2.add_backend(hh1, 10);
hh_group2.add_backend(hh2, 5);
}
#(4)通过调用后端服务器组来调用后端服务器
sub vcl_recv {
set req.backend_hint = hh_group1.backend();
}
2、实现动静分离
sub vcl_recv {
if (req.url ~ "(?i)\.php$") {
set req.backend_hint = hh_group1.backend();;
} else {
set req.backend_hint = hh_group2.backend();;
}
}
3、基于cookie实现会话粘性
sub vcl_init {
new h = directors.hash();
h.add_backend(hh1, 1);
h.add_backend(hh2, 1);
}
sub vcl_recv {
#根据客户端的cookie头选择一个后端
set req.backend_hint = h.backend(req.http.cookie);
}
3.8、后端服务器的健康状态检测
- varnish说明:http://book.varnish-software.com/4.0/chapters/Saving_a_Request.html
1、健康状态检测的两种配置方法
方法一:probe单独定义,在backend中调用
probe PB_NAME {
...
}
backend NAME {
.probe = PB_NAME;
...
}
方法二:probe直接定义在backend中
backend NAME {
.probe = {
...
}
}
2、健康状态检测的基本指令
backend server1 {
.host = "server1.example.com";
.port = "80";
.probe = { #定义健康状态检测的方式
.url = "/healthtest"; #对uri进行健康状态检测,默认为"/"
.timeout = 1s; #超时时长;
.interval = 4s; #健康状态检测的时间间隔
.window = 5; #基于最近的多少次检查来判断其健康状态
.threshold = 3; #.window中定义的检查次数中至少有.threshold定义的次数是成功的,才认为后端服务器是可用的
}
}
- probe其他可用指令:
- .request:发出的具体请求。.request和.url用其一即可。
- .expected_response:期望的响应码,默认为200。
.request =
"GET /.healthtest.html HTTP/1.1"
"Host: www.hengha.com"
"Connection: close"
3、手动设置健康状态
backend.set_health hh1 sick #不健康 backend.set_health hh1 healthy #健康 backend.set_health hh1 auto #自动检测
3.9、设置后端服务器的属性
backend default {
.host = "localhost";
.port = "80";
.connect_timeout = 0.5s; #连接后端主机的超时时间
.first_byte_timeout = 20s; #第一个字节的超时
.between_bytes_timeout = 5s; #字节之间的超时
.max_connections = 50; #后端打开的最大连接数。达到后,varnish将连接失败。
}
1
# #

浙公网安备 33010602011771号