Varnish用法详解

本文详细介绍了Varnish的相关配置,包括varnish的相关文件路径、程序运行流程、VCL配置语言以及后端主机健康检查。通过示例展示了如何设定多个后端主机、设定主机组以及进行后端健康检查,帮助读者深入理解Varnish的使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介:This is Varnish Cache, a high-performance HTTP accelerator

varnish相关

varnish 相关文件路径

/etc/varnish/varnish.params: 配置varnish服务进程的工作特性,例如监听的地址和端口,缓存机制;
/etc/varnish/default.vcl:配置各Child/Cache线程的缓存策略;

varnish相关程序

/usr/sbin/varnishd 主程序
/usr/bin/varnishadm admin 管理工具
交互工具:
/usr/bin/varnishhist
/usr/bin/varnishlog
/usr/bin/varnishncsa
/usr/bin/varnishstat
/usr/bin/varnishtop
VCL配置文件重载程序:
/usr/sbin/varnish_reload_vcl

varnish程序的选项:(可以用varnishd -h查看)

-a address[:port][,address[:port][…],默认为6081端口;
-T address[:port],默认为6082端口;
-s [name=]type[,options],定义缓存存储机制;
-u user
-g group
-f config:VCL配置文件;
-F:运行于前台;

varnish程序运行流程

这里写图片描述

vcl_recv(收到请求), vcl_pass, vcl_hit, vcl_miss, vcl_pipe(非http协议–> pipe), vcl_purge, vcl_synth, vcl_deliver

VCL(”域“专有类型的配置语言)

VCL有多个状态引擎,状态之间存在相关性,但状态引擎彼此间互相隔离;每个状态引擎可使用return(x)指明关联至哪个下一级引擎;每个状态引擎对应于vcl文件中的一个配置段

例如:

vcl_hash --> return(hit) --> vcl_hit

vcl_recv的默认配置

vcl默认配置文件在builtin.vcl,会自动加载到default.vcl配置文件里

# 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);
# }

上面是一个vcl.recv的例子,不用自己写。

状态引擎大体分为3部分:

Client Side:
vcl_recv(收到请求), vcl_pass, vcl_hit, vcl_miss, vcl_pipe(非http协议–> pipe), vcl_purge, vcl_synth, vcl_deliver
vcl_recv:
        hash:vcl_hash
        pass: vcl_pass #用于将客户端请求直接转发给后端服务器,后端服务器响应给客户端时,不进行缓存。
        由于直接将请求转发给后端服务器,因此该连接下的响应数据都是最新的
        pipe: vcl_pipe
        synth: vcl_synth(完成清理,响应清理并返回清理完成的内容)
        purge: vcl_hash --> vcl_purge
vcl_hash:
        lookup:
            hit: vcl_hit
            miss: vcl_miss
            pass, hit_for_pass: vcl_pass
            purge: vcl_purge(修剪缓存项,缓存没有失效但要删除旧的缓存,强制刷新缓存),监控用户是否有清理缓存的权限,如果有传给synth执行。
            ban: 一次修剪多个缓存项,可匹配正则表达式
Backend Side:
vcl_backend_fetch, vcl_backend_response, vcl_backend_error
两个特殊的引擎:(得加载模块director)
vcl_init:在处理任何请求之前要执行的vcl代码:主要用于初始化VMODs;
vcl_fini:所有的请求都已经结束,在vcl配置被丢弃时调用;主要用于清理VMODs;

举例:obj.hits是内建变量,用于保存某缓存项的从缓存中命中的次数;

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.* 表示由客户端发来的http请求报文相关
例如:

req.http.User-Agent, req.http.Referer # 只要是http请求头部变量就可以

bereq.*:由varnish发往BE主机的
bereq.http.*:httpd请求相关
beresp.*:由BE主机响应给varnish的响应报文相关
beresp.http.*:httpd请求相关
resp.*:由varnish响应给client相关
resp.http.*:http响应相关
obj.*:存储在缓存空间中的缓存对象的属性;只读

示例1:强制对某类资源的请求不检查缓存

vcl_recv {
    if (req.url ~ "(?i)^/(login|admin)") {
        return(pass);
    }
}

示例2:对于特定类型的资源,例如公开的图片等,取消其私有标识,并强行设定其可以由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;  #请求资源的可缓存时长
    }
}           

示例3:由于url重定向,请求重启,重新发起请求,或等待时间太长,为了安全起见,在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;
    }
}

示例4:缓存对象的修剪:purge, ban
添加此类请求的访问控制法则:先定义后使用

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);
    }
    ......
}

ban对多个文件修剪,有两种方式
(1) varnishadm:
ban <field> <operator> <arg>
示例:

ban req.url ~ ^/javascripts

(2) 在配置文件中定义,使用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"));
}   

以下是具体请求时的命令:                    
ban req.http.host==www.ilinux.io && req.url==/test1.html

设定多个后端主机

示例:

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;
    }               
        ...
}

设定主机组

使用前需要导入模块:import directors
示例:

backend server1 {
    .host = "172.16.100.6";
    .port = "80";
}
backend server2 {
    .host = "172.16.100.7";
    .port = "80";
}

sub vcl_init {
    new mygroup = directors.round_robin();
    mygroup.add_backend(server1);
    mygroup.add_backend(server2);
}

sub vcl_recv {
    # send all traffic to the bar director:
    set req.backend_hint = mygroup.backend();
}

后端主机健康检查

  • .probe:定义健康状态检测方法;
    • .url:检测时要请求的URL,默认为”/”;
    • .request:发出的具体请求;
      • .request =
      • “GET /.healthtest.html HTTP/1.1”
      • “Host: www.haha.com”
      • “Connection: close”
    • .window:基于最近的多少次检查来判断其健康状态;
    • .threshold:最近.window中定义的这么次检查中至有.threshhold定义的次数是成功的;
    • .interval:检测频度;
    • .timeout:超时时长;
    • .expected_response:期望的响应码,默认为200;

格式:

.probe可以写在后端主机里面也可以单独写

(1) probe PB_NAME  { }
        backend NAME = {
        .host = "172.16.100.6";
        .port = "80";
        .probe = PB_NAME;
                    ...
    }

(2) backend NAME  {
        .host = "172.16.100.6";
        .port = "80";
        .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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值