目录html
知识来源为官方文档:
《Varnish用户指南》
《Varnish4.0电子书》前端
经过对varnish原理的学习,咱们知道varnish缓存策略是基于VCL语言实现,处理逻辑是编写在.vcl
配置文件中。
涉及的总要知识点有如下几个:web
varnish 4.0版本开始,vcl拥有本身的默认规则,它不可移除,老是追加在自定义的规则以后。正则表达式
//
or#
or/* foo */
;VCL4相比VCL3语法的改变点:express
sub subroutine { ... }
if CONDITION { ... } else { ... }
return() # Functions hash_data() # Functions
= 赋值 == 等于 ~ 匹配,能够与正则表达式或ACL一块儿使用。同时注意匹配的规则若是是字符串,则须要 " " 引发。 ! 逻辑非 && 逻辑与 || 逻辑或
子例程:
子例程用于对代码进行分组以提升可读性或可重用性,例:后端
sub pipe_if_local { if (client.ip ~ localnetwork) { return (pipe); } }
VCL中的子例程
不带参数,也不返回值。内置子例程
的名称均以vcl_
开头。
要调用子例程,请使用call关键字,后跟子例程的名称:缓存
sub vcl_recv { call pipe_if_local; }
Varnish具备许多内置的子例程,这些子例程在每次事务流经Varnish时都会被调用。这些内置的子例程都名为vcl_*。您本身的子例程不能以vcl_开头其名称。服务器
Return:
当执行return(action)
语句时,正在进行的vcl_ *子例程执行结束。
该操做指定执行的方式。上下文定义了可用的动做。cookie
call subroutine, return(action),new,set,unset
Varnish 处理 client 的请求和后端服务器的响应时,会调用多个内置的 subroutines 进行处理。经过 CLI 执行 vcl.load 和 vcl.discard 时,也会调用内置的 subroutines。ide
下面对前端(client-side)和后端(backend-side)的处理分别进行介绍:
在请求开始时调用,在接收并解析完整的请求以后调用,在从新启动以后调用,或者做为ESI include的结果调用。
它的目的是决定是否为请求服务,可能会修改它,并决定如何进一步处理它。能够将后端提示设置为后端处理端默认设置。
vcl_recv 子例程可以使用 return() 结合下面的其中一个关键字进行终止:
hash 请求的对象被认为是一个可能被缓存的对象,将继续对其进行处理。将控制权转交给 vcl_hash 子例程。 pass 转换至 pass 模式。控制权最终交给 vcl_pass 子例程。 pipe 转换至 pipe 模式。控制权最终交给 vcl_pipe 子例程。 synth(status code, reason) 转移到 vcl_synth 子例程,synth() 的参数值被预置为 resp.status 和 resp.reason purge 清除请求的对象,以及它的变量(variants)。控制权先交给 vcl_hash,最终交给 vcl_purge
进入 pipe 模式时,vcl_pipe 子例程将被调用。在这个模式中,请求将被传递给后端服务器,这时 Varnish 会降级成为一个 TCP 代理,只充当一个数据流的通道,不会对数据进行任何修改,当 client 或 server 端决定关闭链接时,该模式结束。在调用 vcl_pipe 以后,对于一个处于 pipe 模式的链接,其余任何的 VCL 子例程都不会被调用。
vcl_pipe 子例程可以使用 return() 结合下面的其中一个关键字进行终止:
pipe 继续以 pipe mode 运行 synth(status code, reason) 转移到 vcl_synth 子例程,synth() 的参数值被预置为 resp.status 和 resp.reason
在进入 pass 模式时,vcl_pass 将被调用,请求被转发给后端服务器,后端服务器的响应被转发给 client,可是响应不会被缓存。来自该 client 链接的后续请求,将被正常处理。
vcl_pass 子例程可以使用 return() 结合下面的其中一个关键字进行终止:
fetch 继续以 pass mode 运行 - 发起一个对后端服务器的请求 restart 重启该 transaction。增长 restart 计数器的计数。若是计数超过了 max_restarts,Varnish 发出一个错误:guru meditation error. synth(status code, reason) 转移到 vcl_synth 子例程,synth() 的参数值被预置为 resp.status 和 resp.reason
当缓存查找成功,vcl_hit 将被调用。缓存对象可能会过时,其 ttl 可能为 0 或者负数,with only grace or keep time left.
vcl_hit 子例程可以使用 return() 结合下面的其中一个关键字进行终止:
deliver 发送该对象。若是该对象过时,将触发一个 fetch 调用,更新该对象。 fetch 尽管缓存命中,可是会同步地从后端服务器更新缓存对象。控制权最终转交给 vcl_miss。 pass 转换至 pass 模式。控制权最终交给 vcl_pass 子例程。 restart 重启该 transaction。增长 restart 计数器的计数。若是计数超过了 max_restarts,Varnish 发出一个错误:guru meditation error. synth(status code, reason) 转移到 vcl_synth 子例程,synth() 的参数值被预置为 resp.status 和 resp.reason
当缓存查找失败,或者当 vcl_hit 返回一个 fetch 时,调用 vcl_miss。
vcl_miss 用于决定是否尝试从后端服务器获取文件。
vcl_miss 子例程可以使用 return() 结合下面的其中一个关键字进行终止:
fetch 从后端服务器获取请求的对象。控制权最终转交给 vcl_backend_fetch。 pass 转换至 pass 模式。控制权最终交给 vcl_pass 子例程。 restart 重启该 transaction。增长 restart 计数器的计数。若是计数超过了 max_restarts,Varnish 发出一个错误:guru meditation error. synth(status code, reason) 转移到 vcl_synth 子例程,synth() 的参数值被预置为 resp.status 和 resp.reason
当 vcl_recv 为请求建立了一个 hash 值时被调用。使用该值做为 key 进行缓存查找。
vcl_hash 子例程只能以 return(lookup) 终止:
lookup 在缓存中查找请求的对象。若是从 vcl_recv 返回 return(purge),控制权转交给 vcl_purge。 不然,若是缓存查找的结果是 hit,控制权转交给 vcl_hit;若是缓存查找的结果是 miss,控制权转交给 vcl_miss; 若是缓存查找的结果是 hit on a hit-for-pass 对象 (object with obj.uncacheable == true),控制权转交给 vcl_pass。
执行 purge 以后,vcl_purge 被调用,缓存对象被清除(失效),其全部变量(variants)将被回避。
vcl_purge 子例程可以使用 return() 结合下面的其中一个关键字进行终止:
restart 重启该 transaction。增长 restart 计数器的计数。若是计数超过了 max_restarts,Varnish 发出一个错误:guru meditation error. synth(status code, reason) 转移到 vcl_synth 子例程,synth() 的参数值被预置为 resp.status 和 resp.reason
发送对象给客户端前调用,除了将一个 vcl_synth 结果发送给客户端时不会调用。
vcl_deliver 子例程可以使用 return() 结合下面的其中一个关键字进行终止:
deliver 发送对象给 client restart 重启该 transaction。增长 restart 计数器的计数。若是计数超过了 max_restarts,Varnish 发出一个错误:guru meditation error. synth(status code, reason) 转移到 vcl_synth 子例程,synth() 的参数值被预置为 resp.status 和 resp.reason
调用 vcl_synth 能够发送一个 synthetic 对象给客户端。synthetic 对象由 VCL 生成,不是从后端获取的。可以使用 synthetic() 函数构造 synthetic 对象。
vcl_synth 定义了一个对象,该对象不会被缓存,与其相反,vcl_backend_error 所定义的对象可能最终被缓存。
vcl_synth 子例程可以使用 return() 结合下面的其中一个关键字进行终止:
deliver 直接将 vcl_synth 定义的对象发送给客户端,不调用 vcl_deliver restart 重启该 transaction。增长 restart 计数器的计数。若是计数超过了 max_restarts, Varnish 发出一个错误:guru meditation error.
对后端服务器发送请求时调用 vcl_backend_fetch。在这个子例程中,咱们通常会修改请求,而后才发送给后端服务器。
vcl_backend_fetch 子例程可以使用 return() 结合下面的其中一个关键字进行终止:
fetch 从后端服务器获取对象 abandon 放弃对后端发起请求。除非后端请求是一个 background fetch,不然控制权将被转交给 client-side 的 vcl_synth, 其 resp.status 被设置为 503。
当成功从后端服务器获取到 response headers 时,调用 vcl_backend_response。
vcl_backend_response 子例程可以使用 return() 结合下面的其中一个关键字进行终止:
deliver 对于一个 304 响应,建立一个更新的缓存对象。不然,从后端获取对象的 body,而后发起 delevery 返回给客户端。 极可能是并行的(streaming) abandon 放弃对后端发起请求。除非后端请求是一个 background fetch,不然控制权将被转交给 client-side 的 vcl_synth, 其 resp.status 被设置为 503。 retry 重试发起 backend transaction。增长重试计数,若是重试次数超过 max_retries,控制权转交给 vcl_backend_error
当尝试从后端获取对象失败,或则重试次数超过 max_retries 时,vcl_backend_error 将被调用。
VCL 生成一个 synthetic 对象,可以使用 synthetic() 函数构造 synthetic 对象的 body。
vcl_backend_error 子例程可以使用 return() 结合下面的其中一个关键字进行终止:
deliver 发送 vcl_backend_error 定义的对象,可能的话,缓存该对象。就如同该对象是从后端获取的通常。这也被称为 "backend synth"。 retry 重试发起 backend transaction。增长重试计数,若是重试次数超过 max_retries,调用 client-side 的 vcl_synth, 其 resp.status 被设置为 503。
当加载 VCL 以后,vcl_init 被调用。通常用于初始化 VMODs。
vcl_init 子例程可以使用 return() 结合下面的其中一个关键字进行终止:
ok 正常返回,VCL 继续加载 fail 中止加载这个 VCL
当一个 VCL 被废弃,当该 VCL 处理完全部请求,调用 vcl_fini。通常用于清除 VMODs。
vcl_fini 子例程可以使用 return() 结合下面的其中一个关键字进行终止:
ok 正常返回,VCL 将被废弃。
VCL中有些须要你注意的重要对象。这些对象能够在VCL被使用和操做
---req 请求对象。当vanish接收到请求后,req对象被建立和生成。你能够在vcl_recv中使用req对象作不少事。 ---bereq The backend request object. Varnish contructs this before sending it to the backend. It is based on the req object. 后端请求对象。varnish在发送请求到后端以前构建这个对象。它基于req对象。 ---beresp 后端响应对象。它包含在从后端响应对象的头里。若是你想修改后端server返回的响应信息,你能够在vcl_backend_response中修改beresp对象。 ---resp 传递给客户端响应以前的response对象。一般在vcl_deliver中修改。 ---obj The object as it is stored in cache. Read only. 存储在缓存中的对象。 只读。
actions 是在终止一个内置子例程时,配合 return() 使用的,如 return(pass),最经常使用的 actions 是这些:
---pass 当你在子程序中return(pass)请求和随后的响应将被传递到后端server和从后端server回传回来。响应将不会被缓存。pass能够从vcl_recv中返回。 ---hash 在*vcl_recv*中return(hash),通知varnish从cache查找请求内容,除非这个请求不被标示,那么请求应当被pass。 ---pipe .. XXX:What is pipe? benc 若是从 vcl_recv 返回 pipe,将会进入 pipe 模式,Varnish 将前端与客户端的链接,以及与后端服务器的链接合并成一个数据流的通道,Varnish 不对数据作任何修改,只是将数据在两端发送,因此你的日志是不完整的。 pipe也能够在*vcl_recv*中返回,return(pipe)。 ---deliver 传递对象给客户端。一般在vcl_backend_response中return。 ---restart Restart processing of the request. You can restart the processing of the whole transaction. Changes to the req object are retained. 从新对请求进行处理。你能够在整个请求处理的阶段重启。更改过的req对象将被保留。 ---retry Retry the request against the backend. This can be returned from vcl_backend_response or vcl_backend_error if you don't like the response that the backend delivered . 重启指向后端的请求。若是你不想从后端得到响应,你能够在vcl_backend_response 或者vcl_backend_error 中return。
hash_data():指明哈希计算的数据;减小差别,以提高命中率; regsub(str,regex,sub):把str中被regex第一次匹配到字符串替换为sub;主要用于URL Rewrite regsuball(str,regex,sub):把str中被regex每一次匹配到字符串均替换为sub; return():当某VCL域运行结束时将控制权返回给Varnish,并指示Varnish如何进行后续的动做;其能够返回的指令包括:lookup、hash、hit、miss、pass、pipe、hit_for_pass、purge等;但某特定域可能仅能返回某些特定的指令,而非前面列出的所有指令; return(restart):从新运行整个VCL,即从新从vcl_recv开始进行处理;每一次重启都会增长req.restarts变量中的值,而max_restarts参数则用于限定最大重启次数。 ban(expression):清除能被表达式匹配的全部缓存对象 ban_url(regex):Bans全部的其URL能够被此处的regex匹配到的缓存对象; synth(status,"STRING"):purge操做;
↓
内建变量:
req.*:request,表示由客户端发来的请求报文相关; req.http.* *能够是http请求报文的任意首部的名称,表明引用http的某个请求首部 req.http.User-Agent, req.http.Referer, ... req.http.host req.method 表示客户端的请求方法 req.url 表示客户端请求的url bereq.*:varnish主机在向后端真实服务器发送http请求报文时的相关变量。 如:能够将真实的客户端地址传递给后端真实web服务器,以便于后端真实服务器记录客户端的真实IP,而不是varnish的IP bereq.http.* 表明varnish发日后端的真实的web服务器的相关的请求报文中的首部 beresp.*:由后端真实服务器发来的http响应报文中的某些首部信息相关的变量,通常是在vcl_backend_response或vcl_backend_fenth引擎中调用 beresp.http.* resp.*:由varnish响应给客户端的响应报文相关的变量; 通常用在vcl_deliver引擎中进行调用,由于deliver引擎是用于给客户端构建响应报文,发送响应报文 resp.http.: 能够是响应报文中的任意首部的名称,表明引用某个响应报文的值,可用于设定、添加、修改响应给客户端的响应报文中的响应首部的值 obj.*:对存储在缓存空间中的缓存对象属性的引用变量;只读; obj.hits: 某个缓存对象的缓存的命中次数 client.,server.,storage.*:可用在全部面向客户端一侧的引擎中,也就是vcl_recv、vcl_pipe、vcl_hash、vcl_pass、vcl_purge、vcl_miss、vcl_hit、vcl_deliver、vcl_synth中: client.ip 表明客户端的IP地址 server.ip 表明当前varnish的IP地址 client.port 表明客户端的端口 server.port 表明当前varnish的端口 用户自定义变量 可用set,来设定某个用户自定义变量或现有变量的值 可用unset,来取消某个用户自定义变量,或删除现有变量
经常使用内建变量说明:
bereq.*
bereq.http.HEADERS: 表示varnish发日后端真实web服务器的请求报文中的某个首部
bereq.request: 表示varnish发日后端真实web服务器的请求报文的请求方法(4.0版本的varnish改成了bereq.method)
bereq.url:表示varnish发日后端真实web服务器的请求报文的请求的url
bereq.proto:表示varnish发日后端真实web服务器的请求报文的http协议的协议版本
bereq.backend:表示要varnish发送请求到后端真实web服务器时,后端服务器不止一台时,所调用的后端主机
beresp.*
beresp.http.HEADERS:表示后端真实web服务器发给varnish的http响应报文的某个首部的信息
beresp.proto:表示后端真实web服务器发给varnish的http响应报文的http协议版本
beresp.status:表示后端真实web服务器发给varnish的http响应报文的响应状态码
beresp.backend.name:表示后端真实web服务器发给varnish的http响应报文的后端主机的名称
beresp.ttl:后端服务器响应中的内容的余下的生存时长
obj.*
obj.hit 此对象在缓存中命中的次数
obj.ttl 此对象的ttl值,也就是其缓存时长
server.*
server.ip 当前varnish的IP
server.hostname 当前varnish的主机名
req.*
req.http.HEADERS: 表示客户端发送给varnish的请求报文中的某个首部
req.request: 表示客户端发送给varnish的请求报文的请求方法(4.0版本的varnish改成了req.method)
req.url:表示客户端发送给varnish的请求报文的请求的url
req.proto:表示客户端发送给varnish的请求报文的http协议的协议版本
resp.*
resp.http.HEADERS:表示varnish发送给客户端的响应报文的某个首部的信息
resp.proto:表示varnish发送给客户端的http响应报文的http协议版本
resp.status:表示varnish发送给客户端的http响应报文的响应状态码
自定义变量:可用set 变量名= 值 来设定变量。例:
set resp.http.X-Cache = "HIT"
表示设定响应给客户端的响应报文中设定X-Cache首部的值为HIT
set resp.http.IS-Cache = "YES"+" "server.ip
表示设定响应给客户端的响应报文中的IS-Cache首部的值为"YES
varnish服务器IP",多个元素之间要用+加号链接,若是要输出空格,须要用""引号引发来
取消某变量:用unset 变量名。例:
unset req.http.cookie
表示取消客户端请求报文中http的cookie首部信息
unset beresp.http.Set-cookie
表示取消后端服务器发送到varnish上的响应报文http首部中的Set-cookie首部
同时注意变量是受状态限制的,下图为可用表:
[sleepy↓]