GRACE
如果后端需要很长时间来生成一个对象,这里有一个线程堆积的风险。为了避免这
种情况,你可以使用
Grace
。他可以让
varnish
提供一个存在的版本,然后从后端生成新
的目标版本。
下面的
VCL
代码将
varnish
为客户端提供过期目标,所有对象被保持
2
分钟,在他们失效前新的目标会被制造:
sub vcl_recv {
set req.grace = 2m;
}
sub vcl_fetch {
set beresp.grace = 2m;
}
FUNCTIONS
下面这些内置的函数可以使用的:
Regsub
(
str
,
regex
,
sub
)
返回一个第一次匹配
regex
表达式的
str
的复制,使用
sub
代替它,
sub,0
就是替换
所有满足条件的字符串。
Regsuball
(
str
,
regex
,
sub
)
替换所有发现的目标
Purge_url
(
regex
)
清楚所有
cache
中的匹配
regex
的
URLS
目标。
Subroutines
一个子程序就是一串可读和可用的代码。
sub pipe_if_local {
if (client.ip ~ local) {
pipe;
}
}
子程序在
VCL
中没有参数,也没有返回值。
调用一个子程序,使用子程序的关键字名字:
call pipe_if_local
;
这里有很多子程序和
varnish
的工作流程相关。这些子程序会检查和操作
http
头文
件和各种各样的请求。决定哪个哪些请求被使用。
Vcl_recv
在请求开始的时候被调用,当一个完整的请求被接受到,并被解析,它的作用就是
是否给这个请求提供服务,怎么服务,如果服务,哪个后端会被选取
vcl_recv
子程序以下面的关键字结束:
error code [reason] \\
返回规定的代码给客户端,并终止请求。
pass \\
转换到
pass
模式,控制权会传递给
vcl_pass
。
pipe \\
转换到
pipe
模式,控制权会传递给
vcl_pipe
。
lookup \\
在
cache
中查找请求目标,控制权最终会传递给
vcl_hit
或者
vcl_miss
,取决于目标是否在
cache
中。
vcl_pipe
请求进入
pipe
模式的时候被调用,在这个模式,请求会被
passed
到后端服务器,
在连接关闭前,无论是这个客户端还是对应的后端服务器的数据,都会进入
pass
模式。
vcl_pipe
子程序以下面的关键字结束:
error code [reason] \\
返回规定的代码给客户端,并终止请求。
pipe \\
继续进入
pipe
模式。
vcl_pass
请求进入
pass
模式的时候被调用,在这个模式,请求会被
passed
到后端服务器,
后端服务器的应答会被
passed
给客户端,但是不会被缓存。相同客户端的随后的请求
正常处理。
Vcl_pass
子程序以下面的关键字结束:
error code [reason] \\
返回规定的代码给客户端,并终止请求。
pass \\
继续进入
pass
模式。
vcl_hash
使用
req.hash += req.http.Cookie
或者
HTTP
头文件包含的
cookie
生成
hash
字符串。
vcl_hash
将以下面的关键字结束:
hash \\
继续进入
hash
模式
vcl_hit
当一个请求从
cache
中命中需要的内容,
vcl_hit
子程序以下面关键字结束:
error code [reason] \\
返回规定的代码给客户端,并终止请求。
pass \\
继续进入
pass
模式,控制权转交
vcl_pass
子程序。
deliver \\
提交命中的目标给客户端,控制权转交
vcl_deliver
子程序。
vcl_miss
当需要的内容没有在缓存中命中的时候被调用,决定是否尝试到后端服务器查找目
标,从哪个后端服务器查找目标?
vcl_miss
子程序以下面的关键字结束:
error code [reason] \\
返回规定的代码给客户端,并终止请求。
pass \\
进入
pass
模式,控制权转交给
vcl_pass
fetch \\
从后端服务器获得请求目标,控制权转交给
vcl_fetch
。
vcl_fetch
目标成功从后端服务器中获取的时候被调用
vcl_fetch
子程序以下面的关键字结束:
error code [reason] \\
返回规定的代码给客户端,并终止请求。
pass \\
进入
pass
模式,控制权转交给
vcl_pass
deliver \\
可能把找到的目标插入缓存中,然后发送给客户端,控制权转交给
vcl_deliver
esi \\ ESI-process the document which has just been fetched
vcl_deliver
当一个没有被
cached
内容交付给客户端的时候被调用
vcl_deliver
子程序以西面关键字结束:
error code [reason] \\
返回规定的代码给客户端,并终止请求。
pass \\
进入
pass
模式,控制权转交给
vcl_pass
deliver \\
交付目标给客户端
如果这些子程序没有被定义,或者没有完成预定的处理而被终止,控制权将被转交给系统默认的子程序。查看
EXAMPLES
章节查看默认的代码。
Multiple subroutines
(更多的子程序)
如果多个子程序被定义成相同的名字,
they are concatenated in the order in which the appear in the source
。
示例:
# in file "main.vcl"
include "backends.vcl";
include "purge.vcl";
# in file "backends.vcl"
sub vcl_recv {
if (req.http.host ~ "example.com") {
set req.backend = foo;
} elsif (req.http.host ~ "example.org") {
set req.backend = bar;
}
}
# in file "purge.vcl"
sub vcl_recv {
if (client.ip ~ admin_network) {
if (req.http.Cache-Control ~ "no-cache") {
purge_url(req.url);
}
}
}
内置的子程序会暗中的附加在里面。
Variables
(变量)
虽然子程序没有参数,子进程必须的信息通过全局变量来处理。
以下变量是可用的变量:
now \\
当前时间
下面的变量在
backend
申明中有效:
.host \\
一个
backend
的主机名或者
IP
地址
.port \\
一个
backend
的服务名字或者端口号
下面的变量在处理请求时有效:
client.ip \\
客户端
IP
server.hostname \\server
的主机名
server.identity \\server
的身份,使用
-i
参数设置,如果
�CI
参数没有传递给
varnishd
,
server.identity
将给
varnishd
实例设置名字。设置详细的信息使用
�Cn
参数。
server.ip \\
客户端连接上
socket
,接收到的
IP
地址
server.port \\
客户端连接上
socket
,接收到的端口号
req.request \\
请求类型,例如
”GET”,”HEAD”
req.url \\
请求的
URL
req.proto \\
客户端使用的
HTTP
的协议版本
req.backend \\
使用哪个后端服务器为这个请求提供服务
req.backend.healthy \\
后端服务器是否健康
req.http.header \\
对应的
HTTP
头
bereq.connect_timeout \\
等待后端服务器响应的时间
bereq.first_byte_timeout \\
等待接收第一个字节的等待时间,
pipe
模式中无
效。
bereq.between_bytes_timeout \\
短时间内,两次从后端服务器接收到字节的间
隔,
pipe
模式无效。
下面这些变量在请求目标被成功的从后端服务器或者缓存中获得后有效
obj.proto \\
返回请求目标的
HTTP
版本
obj.status \\
服务器返回的
HTTP
状态码
obj.response \\
服务器返回的
HTTP
状态信息
obj.cacheable \\
如果返回的结果是可以缓存的,而且
HTTP
状态码必须是
200, 03, 300, 301, 302, 404
和
410.
obj.ttl \\
目标的剩余生存时间,以秒为单位。
obj.lastuse \\
最后一个请求后,过去的时间,以秒为单位。
obj.hits \\
大概的交付次数,如果为
0
,表明缓存出错。
下面这些变量在目标
hash key
以后有效
req.hash \\hash key
和缓存中的目标相关,在读出和写入缓存时使用。
下面这些变量在准备回应客户端时使用
resp.proto \\
准备响应的
HTTP
协议版本
resp.status \\
返回客户端的
HTTP
状态码
resp.response \\
返回客户端的
HTTP
状态信息
resp.http.header \\
通信的
HTTP
头
使用
SET
关键字,把值分配给变量:
sub vcl_recv {
# Normalize the Host: header
if (req.http.host ~ "^(www.)?example.com$") {
set req.http.host = "www.example.com";
}
}
可以使用
remove
关键字把
HTTP
头彻底的删除:
sub vcl_fetch {
# Don't cache cookies
remove obj.http.Set-Cookie;
}