varnish配置详解

能用到缓存的服务器的原因是,应用到了程序的局部性。

空间局部性:一个程序最近访问了一个空间,那么他周边的空间也将被访问。

时间的局部性:一条指令一段时间内被执行,之后的一段时间还会被执行。

衡量缓存的效率使用的缓存命中率:

文档命中率: 按照文档的数量进行衡量,10000 命中2000,就是1/5

字节命中率: 按照字节数量进行衡量,比如之前命中的两个为为100M,后面的八个为100K,那么按照数量来衡量命中率就最好用字节来衡量了。

缓存经历流程

浏览器缓存-->上游服务器缓存CDN-->反向代理的缓存-->真正原始服务器


varnish  的配置文件

1.用于定义各后端节点;

2.定义缓存机制

varnish的九个状态引擎

图:

每一个状态都有一个状态码,指明下一步如何进行。

vcl_pipe()表示不识别直接交给后端,只是在vcl_recv和后端主机之间建立了一个管道。

vcl_pass()表示略过,这是针对的不可缓存的对象

vcl_recv()是接受用户请求判断用户的请求首部,然后返回状态码pipe(不识别)|pass(不可缓存)|error(请求被拒绝)|lookup(交给hash查询)

vcl_error()表示直接返回错误信息

vcl_hash():对用户的请求首部urlhash计算,查看是否有缓存。

vcl_hit ():表示内容被命中

vcl_miss():表示未命中

vcl_pass():如果是 对于不可缓存的对象,通过vcl_fetch建立客户端与后端主机,让后端主机直接给予应答,之后也不会给予缓存。

vcl_fetch():这是在后端主机更新缓存是时使用,1.如果请求是可缓存,并且规则允许缓存时,那么经过vcl_fetch,此时会给予链接至后端主机,由后端主机响应数据给客户端,然后本地缓存。2.如果请求是可以缓存的,但是我们本地规则设置不允许缓存的,我们给予建立后端链接,让客户端响应,本地不给于缓存。3.对于不可以缓存的,直接建立后端链接,让后端主机响应,本地不做缓存。

 

下载安装varnish包:

lftp172.16.0.1:/pub/Sources/6.x86_64/varnish> mget ./varnish*
881392 bytes transferred                                           Total 4
files transferred
lftp 172.16.0.1:/pub/Sources/6.x86_64/varnish> bye
[root@localhost haproxy ]# ls
varnish-docs-3.0.6-1.el6.x86_64.rpm     //varnish的文件
varnish-3.0.6-1.el6.x86_64.rpm              
varnish-libs-3.0.6-1.el6.x86_64.rpm     //varnish的库文件


安装生成文件:

配置文件:

这是关键配置文件,进程自己的工作属性

/etc/sysconfig/varnish

定义代理的工作属性

/etc/varnish/default.vcl

配置文件的修改

[root@localhost sysconfig ]# vim varnish    
 # Maximum number of open files (for ulimit -n)
 8 NFILES=131072  //可以打开的最大文件数
10 #Locked shared memory (for ulimit -l)
11 #Default log size is 82MB + header
12 MEMLOCK=82000   //日志的最大首部大小
15 NPROCS="unlimited"
66  VARNISH_LISTEN_PORT=6081
89 #VARNISH_STORAGE_SIZE=1G
90 VARNISH__MALLOC_SIZE=512M     //指定存储的大小
91 # #Backend storage specification   
#VARNISH_STORAGE="file,${VARNISH_STORAGE_FILE},${VARNISH_STORAGE_SIZE}"  //指定存储的类型
 VARNISH_STORAGE="malloc,,${VARNISH_MALLOC__SIZE}"     //这

里是使用内存的方式

1.自定义配置文件的名字

我们使用test.vcl 代替default.vcl

[root@localhost varnish ]# mv default.vcl test.vcl //我们还需要到进程配置文件的,修改默认的配置文件名
59 # #Main configuration file. You probably want to change it :)
60 #VARNISH_VCL_CONF=/etc/varnish/default.vcl
61 VARNISH_VCL_CONF=/etc/varnish/test.vcl   //这样我们重启就可以是实现修改默认配置文件了
#service
 varnish restart


#但是缓存服务器一般不会重启,我们使用的方式是:

[root@localhost
etc ]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
200       
varnish>
vcl.load t1 test.vcl
200       
varnish>
vcl.use t1
varnish>
vcl.list
200       
available       0 boot
active

2.定义单个后端主机:

格式:

Backend
nodename {
.host = "ipaddr";  //分号结尾
.port = "port";    //点号开头
}

例如:

 7 backend default {

  8   .host = "172.16.249.248";

  9   .port = "80";

 10 }

3.定义deliver投递方式:

我们自己定义一个变量:set 设置自定义首部。 + 用于连接字符串。

这里我们的代理配置文件定义一个默认后端主机:

定义一个后端主机:然后开器deliver状态引擎。:

 7  backend default {
 8  .host = "172.16.249.220";
 9  .port = "80";
 10 } 
    sub vcl_deliver  {
116     if(obj.hits > 0) {
117         set resp.http.X-Cache = "HIT via" + " " + server.hostname;
118     }
119     else {
120         set resp.http.X-Cache ="MISS";
121    }
122      return(deliver);
123 }

4.内置变量:

五类:

Req resp ,bereq ,beresp ,obj

请求类:

Sever.ip 服务端IP

Serve.hostname 主机名

Req.backend 指定对应主机名

Req.url 指定请求的地址

Req.http.header 指定请求http协议头部信息。

Req.quest指定请求方法

Req.http.x-forword-for 转发上一级的IP信息

Req.http

响应类:

Resp.response 响应给客户端的http信息

Resp.http.header 返回给客户端的http头部信息

Resp.status 响应的状态码

bereqvarnish向后端主机的请求类

beReq.url 指定请求的地址

beReq.http.header 指定请求http协议头部信息。

beReq.quest指定请求方法

由后端主机向varnish响应的变量

Beresp.request 指定请求的类型

Beresp.url 指定请求的路径

Beresp.http.header 请求的首部信息

Beresp.ttl 缓存的保留时长

关于获取内容的变量

           Obj.status 请求状态码

Obj.ttl    缓存时间

Obj.hits   命中次数

5.VCL语法:

vcl是基于域的编程语言,支持算数运算和逻辑运算们支持正则表达式。支持set自定义变量,支持unset撤销变量,支持if条件判断,有内置的函数和变量;

保存于vcl配置文件中;此配置文件需要编译为二级制方式,才能使用。

后端节点backend name {}

代理缓存

Sub 来定义状态引擎。

是由manager进程调用gcc,编译然后交给子进程使用。

状态引擎有很大的相关性:returnX)定义退出状态,进而决定继续处理的下一个引擎。

vcl的语法格式:

1.注释:使用//, /*多行注释*/

2.sub $name 定义函数

3.不支持循环

4.支持条件判断

5.支持终止语句

6.域专用

7.操作符:===~,!,  支持正则表达式

vcl内置函数:

Regsub(str,pattern,sub) 按照正则表达式,把str换成sub

Regsubball(str,regexp,sub) 全局】

Hash_data(str)

Purge:从缓存中挑选出对象并删除

return()

例如:vcl-recl 可以返回pass,pipe,lookup ,error

6.if语句的使用语法结构:

语法的使用:

If 语句 单分支{

}

多分支

If(condition){

…;

}

Else{

…;

}

7.定义某类内容被缓存:

注意这里面模式匹配的内容要用到引号引起来。语法把他们当做语法。

 38    if (req.http.Authorization || req.http.Cookie) {
 39         /* Not cacheable by default */
 40         return (pass);
 41     }
 42     if (req.url ~"\.(jpg|jpeg|png|gif)$"){    //如果是以这些结尾
 43     if(req.http.Cookie){                                     //如果有cookie
 44         unset req.http.Cookie;                           //清除cookie
 45     }
 46     }
 47      return (lookup);                                         //返回查询状态码
 48  }

我下线httpd ,查看是否缓存下来

8.基于ACL的支持访问控制机制:

使用格式:

Acl name {

"ip";

"net";  //注意在;这里如果是一个网段掩码要在外面 "172.16.0.0"/16;

}

 

这种情况,我们一般用在特殊,需要控制的范围。例如:清除缓存。

9.error内置命令的使用

Error code 直接生成一个响应页面,这个页面可以是完成的,也可以是错误的。

常用code 200 405 " "

10.清除缓存purge的设定

1.首先设置访问控制,只允许本机和IP172.16.249.141访问。

acl purges {
 12     "127.0.0.1";
 13     ="localhost";
 14     "172.16.249.141";
 15     }

2.配置purge规则

自定义一个请求方法比如是PURGE

如果用用户是通过我们定义的主机使用的purge方法,允许清除对应的缓存,如果不是返回错误页面。

如果没有命中要清除的缓存,也返回提示错误页面

 

backend default {
  8  .host = "172.16.249.248";
  9  .port = "80";
 10 }
  #对purges设置权限
 11 acl purges {
 12     "127.0.0.1";
 13     "localhost";
 14     "172.16.249.141";
 15     }
 23 sub vcl_recv {
 24 if (req.restarts == 0) {
 25 if (req.http.x-forwarded-for) {
 26 set req.http.X-Forwarded-For =
 27 req.http.X-Forwarded-For + ", " + client.ip;
 28     }else {
 29        set req.http.X-Forwarded-For = client.ip;
 30     }
 31     }
 #定义请求方法,允许使用PURGE
 32     if (req.request != "GET" &&
 33     req.request != "HEAD" &&
 34     req.request != "PUT" &&
 35     req.request != "POST" &&
 36     req.request != "TRACE" &&
 37     req.request != "OPTIONS" &&
 38     req.request != "DELETE" &&
 39     req.request != "PURGE") {
 40     /* Non-RFC2616 or CONNECT which is weird. */
 41     return (pipe);
 42     } #定义请求方法,允许使用PURGE
 43     if (req.request != "GET" && req.request !="HEAD" && req.request != "PURGE") {
 44     /* We only deal with GET and HEAD by default */
 45     return (pass);
 46     }
 47     if (req.http.Authorization || req.http.Cookie) {
 48     /* Not cacheable by default */
 49     return (pass);
 50     } 
 51     if (req.request =="PURGE") {
 52     if (!client.ip ~purges){
 53     error 405 "forbidding";
 54       }
 55     }
 56    if (req.url ~ "\.(jpg|jpeg|png|gif)$"){
 57    if(req.http.Cookie){
 58        unset req.http.Cookie;
 59     }
 60     }
 61     return (lookup);
 62  }#定义命中状态引擎,命中执行purge函数
 92 sub vcl_hit {
 93    if (req.request == "PURGE"){
 94    purge;
 95    error 200 "finished";
 96     }
 97  }#定义非命中状态引擎, 错误引擎
102 subvcl_miss {
103     if (req.request == "PURGE"){
104     purge;
105     error 404 "no cache";
106      }
107 }

wKioL1S2o9GgjTuLAAFrQwGt1Pk811.jpg


wKiom1S2o1-Ra8L2AAGwCB7-mCw481.jpg


11.自定义那些内容可以缓存,以及缓存时长

124 sub vcl_fetch {
125     if (req.url ~"\.(jpg|jpeg|png|gif)$"){
127     set beresp.ttl = 3600 s;
128     return(deliver);}
129     if (req.url ~ "\.(php|cgi)$"){
130         set beresp.ttl = 0 s; }
131          return(deliver);
132     }

12.健康状态检查:

.probe = {  //可以单独定义,也可以在backend中定义
.url =#              //指明路径
.request =#   
//定义请求格式
.windowns =#   
//基于最近多少次检查,是失败还是成功。这里是8次
.threshold = 
# 这里是必须成功了5次才认为是健康的。
.initial = 
#         成功多少次,才把后端主机设置为健康状态。
.expected_response=#    //指定的时间
.interval =                              //间隔时间
.timeout = 
}
 
例如:
probe dynamic {                 
    .url = "/index.html";
    .interval = 5s;
    .timeout = 1s;
    .expected_response= 200;
}

13.定义缓存的负载均衡和动静分离

backend app1 {                  
   .host = "172.16.11.11";    
   .port = "80";              
            }
backend app2 {
   .host = "172.16.11.12";
    .port = "80";
}
backend web1 {         
   .host = "172.16.11.13";
   .port = "80";
}
backend web2 {
   .host = "172.16.11.14";
   .port = "80";
  }
director apps random {           #定义一个后端服务器组,实现负载均衡效果
    {
        .backend = app1;          #调用前面已定义过的后端主机
    .weight = 2;                 #设置权重
    }
    {
    .backend = app2;
    .weight = 2;
    }
}
director webs random {            #定义后端静态服务器组,实现负载均衡效果
    {
       .backend = web1;
       .weight = 2 ;
    }
    {
       .backend = web2;
       .weight = 2 ;
    }
}
sub vcl_recv {                    #定义引用规则
   if (req.url ~ "\.php(\?\.*|$)") {
   set req.backend = apps;
    }else {
   set req.backend = webs;
    }
   return(lookup);

varnish管理命令

  跟随varnish会一起安装一些方便的调试工具,用好这些工具,对你更好的应用varnish有很大的帮助。
varnishncsa(以 NCSA 的格式显示日志) 
  通过这个命令,可以像类似于 nginx/apache一样的显示出用户的访问日志来。
varnishlog(varnish详细日志)
  如果你想跟踪varnish处理每个请求时的详细处理情况,可以使用此命令。
  直接使用这个命令,显示的内容非常多,通常我们可以通过一些参数,使它只显示我们关心的内容。
    -b    \\只显示varnish和backend server之间的日志,当您想要优化命中率的时 候可以使用这个参数。  
    -c    \\和-b差不多,不过它代表的是 varnish和 client端的通信。  
    -i tag  \\只显示某个 tag,比如“varnishlog –i SessionOpen”将只显示新会话,注意,这个地方的tag名字是不区分大小写的。  
    -I    \\通过正则表达式过滤数据,比如“varnishlog -c -i RxHeader -I Cookie”将显示所有接到到来自客户端的包含 Cookie 单词的头信息。  
    -o    \\聚合日志请求 ID 
  varnishlog -c -o /auth/login  这个命令将告诉您来自客户端(-c)的所有包含”/auth/login” 字段(-o)请求。
  varnishlog -c -o ReqStart 192.168.1.100  只跟踪一个单独的client请求 
varnishtop 
    您可以使用varnishtop 确定哪些URL经常被透传到后端。    
    适当的过滤使用  –I,-i,-X  和-x 选项,它可以按照您的要求显示请求的内容,客
户端,浏览器等其他日志里的信息。 
    varnishtop -i rxurl    \\您可以看到客户端请求的 url次数。 
    Varnishtop -i txurl    \\您可以看到请求后端服务器的url次数。 
    Varnishtop -i Rxheader -I Accept-Encoding \\可以看见接收到的头信息中有有多少次
包含Accept-Encoding。 
varnishstat 
  显示一个运行varnishd实例的相关统计数据。 
  Varnish 包含很多计数器,请求丢失率,命中率,存储信息,创建线程,删除对象等,几乎所有的操作。通过跟踪这些计数器,可以很好的了解varnish运行状态。  
varnishadm 
  通过命令行,控制varnish服务器。可以动态的删除缓存,重新加载配置文件等。
管理端口有两种链接方式:
  1,telnet方式,可以通过telnet来连接管理端口.如:"telnet localhost 6082"
  2,varnishadm方式,可以通过varnish自带的管理程序传递命令.如: varnishadm -n vcache -T localhost:6082 help
动态清除缓存
  varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 ban.url /2011111.png
  其中:ban.url 后的路径一定不要带abc.xxx.com域名之类的,否则缓存清除不了。
清除包含某个子目录的URL地址:
  /usr/local/varnish/bin/varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 url.purge /a/
不重启加载配置文件
  登陆到管理界面
  /usr/local/varnish/bin/varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 
  加载配置文件
  vcl.load new.vcl /etc/varnish/default.vcl
  编译出错的话会有提示,成功会返回200
  加载新配置文件
  vcl.use new.vcl
  此时新的配置文件已经生效!