Varnish 缓存策略


default.vcl


子进程工作流程图示
Varnish 缓存策略_第1张图片
image.png
在子进程 VCL 中的可用变量

Varnish 缓存策略_第2张图片
image.png

VCL (Varnish Configuaration Language)


vcl的语法格式
  • VCL files start with “vcl 4.0;”
  • //, # and /* foo */ for comments;
  • Subroutines are declared with the sub keyword; 例如sub vcl_recv { ...};
  • No loops, state-limited variables(受限于引擎的内建变量);
  • Terminating statements with a keyword for next action as argument of the return() function, i.e.: return(action); # 用于实现状态引擎转换
  • Domain-specific;

三类主要语法
sub subroutine {
    ...
}
            
if CONDITION {
    ...
} else {    
    ...
}
            
return(), hash_data()

VCL Built-in Functions and Keywords
  • 函数
regsub(str, regex, sub)
regsuball(str, regex, sub)
ban(boolean expression)
hash_data(input)
synthetic(str)
  • Keywords
call subroutine, return(action),new,                

set,unset 
  • 操作符
==, !=, ~, >, >=, <, <=
逻辑操作符:&&, ||, !
变量赋值:=
  • 示例
if (obj.hits>0) {
    set resp.http.X-Cache = "HIT via" + " " + server.ip;
} else {
    set resp.http.X-Cache = "MISS from " + server.ip;
}

变量类型
  • 内建变量
req.*   # request,表示由客户端发来的请求报文相关;
    req.http.*
        req.http.User-Agent, req.http.Referer, ...
bereq.*   # 由 varnish 发往 BE 主机的 httpd 请求相关;
    bereq.http.*
beresp.*   # 由 BE 主机响应给 varnish 的响应报文相关;
    beresp.http.*
resp.*   # 由 varnish 响应给 client 相关;
obj.*   # 存储在缓存空间中的缓存对象的属性;只读;
  • 常用变量
bereq.*, req.*
    bereq.http.HEADERS, req.http.HEADERS
    bereq.request, req.request   # 请求方法;
    bereq.url, req.url   # 请求的 url;
    bereq.proto,req.proto   # 请求的协议版本;
    bereq.backend   # 指明要调用的后端主机;
    
    req.http.Cookie   # 客户端的请求报文中 Cookie 首部的值; 
    req.http.User-Agent ~ "chrome"
    
    
beresp.*, resp.*
    beresp.http.HEADERS
    beresp.status, resp.status   # 响应的状态码;
    reresp.proto, resp.proto   # 协议版本;
    beresp.backend.name   # BE 主机的主机名;
    beresp.ttl   # BE 主机响应的内容的余下的可缓存时长;
    
obj.*
    obj.hits   # 此对象从缓存中命中的次数;
    obj.ttl   # 对象的 ttl 值
    
server.*
    server.ip   # varnish 主机的 IP;
    server.hostname   # varnish 主机的 Hostname;
client.*
    client.ip   # 发请求至 varnish 主机的客户端 IP;
  • 用户自定义
set 
unset

示例
  • 强制对某类资源的请求不检查缓存
vcl_recv {
    if (req.url ~ "(?i)^/(login|admin)") {
        return(pass);
    }
}
  • 对于特定类型的资源,例如公开的图片等,取消其私有标识,并强行设定其可以由varnish缓存的时长; 定义在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;
    }
}
  • 定义在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;
    }
}

缓存对象的修剪:purge, ban

配置purge操作
  • 能执行purge操作
sub vcl_purge {
    return (synth(200,"Purged"));
}
  • 何时执行purge操作
sub vcl_recv {
    if (req.method == "PURGE") {
        return(purge);
    }
    ...
}
添加此类请求的访问控制法则
acl purgers {
    "127.0.0.0"/8;
    "10.1.0.0"/16;
}
sub vcl_recv {
    if (req.method == "PURGE") {
        if (!client.ip ~ purgers) {
            return(synth(405,"Purging not allowed for " + client.ip));
        }
        return(purge);
    }
    ...
}
Banning
  • varnishadm
    ban
    示例
ban req.url ~ (?i)^   # (?i) 表示不区分大小写
  • 在配置文件中定义,使用ban()函数
    示例
if (req.method == "BAN") {
    ban("req.http.host == " + req.http.host + " && req.url == " + req.url);
    # Throw a synthetic page so the request won't go to the backend.
    return(synth(200, "Ban added"));
}   

定义多个后端主机
backend default {
    .host = "172.16.100.6";
    .port = "80";
}
backend appsrv {
    .host = "172.16.100.7";
    .port = "80";
}
sub vcl_recv {              
    if (req.url ~ "(?i)\.php$") {
        set req.backend_hint = appsrv;
    } else {
        set req.backend_hint = default;
    }   
    
    ...
}

Director
varnish module
  • 使用前需导入
import directors;
  • 示例
import directors;    # load the directors
backend server1 {
    .host = 
    .port = 
}
backend server2 {
    .host = 
    .port = 
}
sub vcl_init {
    new GROUP_NAME = directors.round_robin();
    GROUP_NAME.add_backend(server1);
    GROUP_NAME.add_backend(server2);
}
sub vcl_recv {
    # send all traffic to the bar director:
    set req.backend_hint = GROUP_NAME.backend();
}

BackEnd Server 健康状态检测
语法
.probe = {
    .url= 
    .timeout= 
    .interval= 
    .window=
    .threshold=
}
定义检测方法
.probe   # 定义健康状态检测方法;
    .url   # 检测时要请求的 URL,默认为”/"; 
    .request   # 发出的具体请求;
        .request = 
            "GET /.healthtest.html HTTP/1.1"
            "Host: www.rookie.com"
            "Connection: close"
    .window   # 基于最近的多少次检查来判断其健康状态; 
    .threshold   # 最近 .window 中定义的这么次检查中至有 .threshhold 定义的次数是成功的;成功阈值;
    .interval   # 检测频度; 
    .timeout   # 超时时长;
    .expected_response   # 期望的响应码,默认为200;
健康状态检测的配置方式
  • 单独定义
probe PB_NAME  { }
 backend NAME = {
.probe = PB_NAME;
...
 }
  • 在需要检测的 BE 上定义
backend NAME  {
    .probe = {
        ...
    }
}
示例
probe check {
    .url = "/.healthcheck.html";
    .window = 5;
    .threshold = 4;
    .interval = 2s;
    .timeout = 1s;
}
backend default {
    .host = "10.1.0.68";
    .port = "80";
    .probe = check;
}
backend appsrv {
    .host = "10.1.0.69";
    .port = "80";
    .probe = check;
}
手动设定 BE 主机的状态
sick   # 管理down; 
healthy   # 管理up;
auto   # probe auto;

设置后端的主机属性
backend BE_NAME {
    ...
    .connect_timeout = 0.5s;
    .first_byte_timeout = 20s;
    .between_bytes_timeout = 5s;
    .max_connections = 50;
}

你可能感兴趣的:(Varnish 缓存策略)