首页 > 代码库 > Varnish配置语言之VCL

Varnish配置语言之VCL

Varnish配置语言之VCL常用配置

用户请求一个资源的流程

(1)DNS查询

(2)建立连接

(3)服务器接收到请求后构建响应并处理完成

(4)发送至客户端,传输时间

(5)断开连接

 

缓存优化的意义

所谓的优化就是从以上每个角度去缩短时间,缓存是能够降低服务器的处理时间的

 

命中率的类型

·文档命中率,文档命中率高并不能够说明服务器性能增强很明显

    比如命中的都是很小的资源,而未命中的都是很大,所以就算命中率达到80%也并不说明传输的内容量小了80%,因此还有字节命中率

·字节命中率

    命中的文档个数可能并不多,但是字节所需要传输内容命中内容非常多的话,也是非常高的

所以不能仅仅衡量文档命中率来判断其效率的高低

 

web服务器缓存在实现命中在实现缓存功能的时候通常会需要完全的负责用户请求的构建,所以通常用户的请求必须由缓存服务器自身直接处理,所以两种功能需要柔和起来工作的

·代理

·缓存

 一般来讲web缓存一般都是反向代理才可以,对于varnish来讲应用了新的体系结构,因此在性能上,尤其是在高并发的时候要比squid好,但是在并发特别大的时候其实两者性能是不相上下的,因此varnish更容易部署,更适合轻量级用用,在高并发的时候(在请求数据量不大,吞吐率要求不高的时候)还是有一定优势的

 

Varnish的状态引擎

varnish内部有所谓的状态引擎的概念

    当用户请求进入后,varinish在内部完成用户请求处理(包括缓存查询等),在内部内置了钩子函数能够在不同的阶段上让用户自定义处理机制的

 

Varnish的内置变量

变量种类

最常见的类型有以下两种

    req.*         #用户的请求刚刚到达本机的时候

    bereq.*        #在执行req之前

其他种类

wKioL1PPbLPBPlszAAGoN4UJN-E212.jpg

 

请求

作为varnish而言,客户端请求到达服务器为一个请求;

服务器本地缓存没有于是向后端服务器请求,因此想将用户的请求或者构建请求转发至后端的时候,也是一种请求;

 

响应

后端服务器构建的算作一个响应;

后端服务向前端回应的时候算作一个响应;

服务器向后端取得内容之后接下来要不要缓存都是服务器进行处理,服务器取得内容之后被称为obj.ttl

 

resp.* 响应报文只有两个地方可以用:

·deliver         #因为只有在其状态引擎才能构建客户端响应状态

·error          #作为缓存,自行也会构建错误响应报文

 

beresp.*          #响应之前,当响应构建还没有进行响应,因此只能应用在fetch上

            #但是服务器向前端响应的时候,一旦响应了,就无法处理

 

例:

构建客户端响应都会在deliver上去做规则

sub vcl_deliver {
        set resp.http.X-Age = resp.http.Age;                #内置指定,设置变量值
        unset resp.http.Age;                                #撤销变量值

        if (obj.hits > 0) {      #
               set resp.http.X-Cache = “HIT”;
        } else {
               set resp.http.X-Cache = “MISS”;
        }
}

 

在用户的报文由deliver响应之前自定义了一个首部为xage,而其值等于esp.http.Age的值

说白了就是将esp.http.Age换成X.age的首部而已

unset resp.http.Age 撤销了其resp.http.age首部将其换成了X.age

if (obj.hits > 0) {                #一旦被投递了这个对象,如果其内部个数大于0,那么则命中

 set resp.http.X-Cache = “HIT”;     #于是构建在响应报文中自定义首部X.Cache="HIT"否则构建请求首部MISS ,于是客户端将会看到是否命中

 

定义VCL

自定义vcl 尽可能不要更改默认的配置文件

任何一个vcl必须要有一个backend 不然的话无法连接至后端服务器从而无法使得构建响应

[root@node1varnish]# vim test.vcl

内容如下:

backend webserver1{
        .host="10.0.10.63";
        .port="8080";
}

 

首先访问63测试是否可以访问

[root@node1varnish]# curl  http://10.0.10.63:8080

node1

启动varnish并进入管理界面

[root@node1varnish]# /etc/init.d/varnish start
Starting VarnishCache:               [  OK  ]
[root@node1 varnish]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082

导入最新的配置文件,并将其命名为test1

varnish>vcl.load test1 ./test.vcl

200       

VCL compiled.

激活并使用新的配置文件

varnish>vcl.use test1

200   

再次查看list,可以看到test1已经被加载至列表并已经启用

varnish>vcl.list

200       

available       0 boot

active          0 test1

访问测试

[root@node1varnish]# curl http://10.0.10.63:8080

node1

11

[root@node1varnish]# curl http://10.0.10.61    

node1

11

 

使用浏览器访问并调用开发工具观察

wKioL1PPbMmhSTEjAAM2bVvg3U8307.jpg

Status Code:304 Not Modified    只显示在本地缓存生效,并没有显示varnish是否命中

 

让varnish显示是否命中

编辑配置文件,将以下参数加入配置文件中

[root@node1varnish]# vim test.vcl

backend webserver1{

        .host="10.0.10.63";

        .port="8080";

}

#加入以下参数

#如果obj.hits大于0 也就意味着找到数据,则返回hit,否则为miss

sub vcl_deliver{

   if (obj.hits > 0) {

        set resp.http.X-Cache ="HIT";

        } else {

               set resp.http.XCahche ="MISS";

        }

}

使其生效

varnish>vcl.load test2 ./test.vcl
200       
VCL compiled.

使用test2

varnish>vcl.use test2
200   

再次访问

wKiom1PPa8WAc4K6AAMVJXMHu4s486.jpg

 

样例:我们来看默认配置文件

#    if (req.request != "GET" &&
#       req.request != "HEAD"&&
#       req.request != "PUT" &&
#       req.request != "POST"&&
#       req.request != "TRACE"&&
#       req.request != "OPTIONS"&&
#       req.request != "DELETE") {
#         /* Non-RFC2616 or CONNECTwhich is weird. */
#         return (pipe);

#    }

#    if (req.request != "GET" && req.request != "HEAD"){
#         /* We only deal with GET andHEAD by default */
#         return (pass);
#     }
#     if (req.http.Authorization || req.http.Cookie) {
#         /* Not cacheable by default*/
#         return (pass);
#     }
#     return (lookup);
# }

正常情况下在RECV中如果用户请求如果不上以上几个状态,那么则不管它

如果用户的请求不是GET并且也不是HEAD 就直接pass

在RECV中可以自定义在那种情况下明确自定义使用哪种后端,这样req.backend用来自定义所使用的后端主机

如果请求内容中含有Authorization 的首部或则有cookie的首部,则不缓存

 

更精确的条件判断

将hit的名字来源标注其IP地址

backend webserver1{

        .host="10.0.10.63";

        .port="8080";

}

sub vcl_deliver {

   if (obj.hits > 0) {

        set resp.http.X-Cache = "HITfrom"+" "+server.ip;

        } else {

               set resp.http.XCahche ="MISS";

        }

}

刷新配置文件

varnish>vcl.load test3 ./test.vcl
200       
VCL compiled.
varnish> vcl.use test3
200 

再次访问测试,这里使用curl命令来查看头部信息

[root@node1varnish]# curl -I http://10.0.10.61

HTTP/1.1 200 OK

Server:nginx/1.4.2

Content-Type:text/html

Last-Modified:Fri, 18 Jul 2014 06:50:43 GMT

ETag:"53c8c3c3-9"

Content-Length: 9

Accept-Ranges:bytes

Date: Wed, 23 Jul2014 06:37:26 GMT

X-Varnish:1312365651 1312365649

Age: 16

Via: 1.1 varnish

Connection:keep-alive

X-Cache: HITfrom 10.0.10.61

定义recv

如果用户请求的url是index.html 则不让其命中

加入以下参数:

backend webserver1{

        .host="10.0.10.63";

        .port="8080";

}

 

sub vcl_deliver {

   if (obj.hits > 0) {

        set resp.http.X-Cache = "HITfrom"+" "+ server.ip;

        } else {

               set resp.http.XCahche ="MISS";

        }

}

 

sub vcl_recv {

   if(req.url ~ "index.html$") {

    return(pass);

        }

    }

重新载入配置文件后,访问测试

多访问几次,可以看到依旧是miss

[root@node1varnish]#  curl -Ihttp://10.0.10.61/index.html     HTTP/1.1200 OK

Server:nginx/1.4.2

Content-Type:text/html

Content-Length: 9

Last-Modified:Fri, 18 Jul 2014 06:50:43 GMT

ETag:"53c8c3c3-9"

Accept-Ranges:bytes

Accept-Ranges:bytes

Date: Wed, 23 Jul2014 06:40:43 GMT

X-Varnish:1312365654

Age: 0

Via: 1.1 varnish

Connection:keep-alive

XCahche: MISS

 

[root@node1varnish]#  curl -Ihttp://10.0.10.61/index.html     HTTP/1.1200 OK

Server:nginx/1.4.2

Content-Type:text/html

Content-Length: 9

Last-Modified:Fri, 18 Jul 2014 06:50:43 GMT

ETag:"53c8c3c3-9"

Accept-Ranges:bytes

Accept-Ranges:bytes

Date: Wed, 23 Jul2014 06:40:46 GMT

X-Varnish:1312365655

Age: 0

Via: 1.1 varnish

Connection:keep-alive

XCahche: MISS

这就意味着如果我们请求的不是index.html这个文件,则不会出现miss,那么我们来请求其他名称的文件

[root@node1varnish]#  curl -Ihttp://10.0.10.61/1.html    

HTTP/1.1 200 OK

Server:nginx/1.4.2

Content-Type:text/html

Last-Modified:Fri, 18 Jul 2014 06:50:23 GMT

ETag:"53c8c3af-4"

Content-Length: 4

Accept-Ranges:bytes

Date: Wed, 23 Jul2014 06:42:06 GMT

X-Varnish:1312365657 1312365656

Age: 3

Via: 1.1 varnish

Connection:keep-alive

X-Cache: HITfrom 10.0.10.61

 

只设置为客户端IP

都将X-Forward-For设置记录每个客户端ip

backend webserver1{

        .host="10.0.10.63";

        .port="8080";

}

 

sub vcl_deliver {

   set req.http.X-Forward-For = client.ip;

   if (obj.hits > 0) {

        set resp.http.X-Cache = "HITfrom"+" "+ server.ip;

        } else {

               set resp.http.XCahche ="MISS";

        }

}

 

sub vcl_recv {

   if(req.url ~ "index.html$") {

    return(pass);

        }

    }

 

varnish>vcl.load test5 ./test.vcl

200       

VCL compiled.

varnish>vcl.use test5

200 

之所以这么加是为了方便客户端记录ip的时候显示的是真正的请求者的IP而不是前端代理者的IP

在httpd或者在nginx加入头部即可,更改nginx日志配置:

    log_format main  ‘"$http_x_forwarded_for" - $remote_user [$time_local] "$request" ‘

                       ‘$status $body_bytes_sent"$http_referer"‘

                       ‘"$http_user_agent"‘;

    access_log logs/access.log  main;

访问测试

"10.0.10.1"- - [23/Jul/2014:15:32:31 +0800] "GET /favicon.ico HTTP/1.1" 404 570"-""Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36"

"10.0.10.61"- - [23/Jul/2014:15:35:24 +0800] "GET / HTTP/1.1" 200 9"-""curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7NSS/3.13.6.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"

已经发现,后端服务器在收到请求的时候,记录的是不是代理服务器的IP地址,而是客户端真实的IP地址

 

基于Varnish VCL实现动静分离

如果用户请求的是图片那么则发给静态服务器,反之,如果是动态内容则发送给动态服务器

首先需要定义两个backend

backendimg_server1 {

        .host="10.0.10.63";

        .port="8080";

}

 

backendapp_server1 {

        .host="10.0.10.62";

        .port="8080";

}

 

sub vcl_recv {

   if(req.url ~ "index.html$") {

    return(pass);

        }

   if(req.url ~ "\.php$") {

           set req.backend = app_server1;

       } else {

           set req.backend = img_eserver1;   

       }

}

 

sub vcl_deliver {

   set req.http.X-Forward-For = client.ip;

   if (obj.hits > 0) {

        set resp.http.X-Cache = "HITfrom"+" "+ server.ip;

        } else {

               set resp.http.XCahche ="MISS";

        }

}

 

varnish>vcl.load test6 ./test.vcl

200       

VCL compiled.

varnish>vcl.use test6

200

 

Varnish状态监测机制

可以使用backend probe进行定义

我们在backend

每个后端服务器当前探测的健康状态探测方法通过.probe进行设定,其结果可由req.backend.healthy变量获取,也可通过varnishlog中的Backend_health查看或varnishadm的debug.health查看。

例:

backend web1 {
     .host = "www.magedu.com";
     .probe = {
          .url ="/.healthtest.html";        #探测请求哪个文件做监测
          .interval = 1s;                   #指定超时时间
          .window = 5;                      #采样几次
          .threshold = 2;                   #预值,至少重复采样几次认为正常
     }
}

 

定义检测机制

probe healtchk {
   .url = "/";
   .interval = 1s;
   .timeout = 0.1s;
   .expected_response = 200;
}


backend imageserver1 {
  .host = "10.0.10.63";
  .port = "8080";
 
.probe = healtchk;
}

backend appserver1 {
  .host = "10.0.10.62";
  .port = "8080";
 
.probe = healtchk;
}
sub vcl_recv {
   set req.http.X-Forward-For = client.ip;

   if(req.url ~ "index.html$") {
    return(pass);
     }

   if(req.url ~ "\.php$") {
        set req.backend = appserver1;
    } else {
     set req.backend = imageserver1;    
      }
}

sub vcl_deliver {
   if(obj.hits > 0) {
     set resp.http.X-Cache = "HIT from"+""+ server.ip;
     } else {
            setresp.http.XCahche = "MISS";
     }
}

 

varnish>vcl.load test7 ./test.vcl
200       
VCL compiled.

 

END,感谢各位

 

本文出自 “心情依旧” 博客,转载请与作者联系!

Varnish配置语言之VCL