缓存服务之varnish的简单应用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了缓存服务之varnish的简单应用相关的知识,希望对你有一定的参考价值。

Varnish:

       技术分享varnish是一款轻量级的http cache和反向代理软件,类似于nginx,缓存功能非常强大,相比squid重量级的缓存服务,varnish 具有性能更高、速度更快、管理更加方便等诸多优点,很多大型的网站都开始尝试使用 varnish 来替换 squid,这些都促进 varnish 迅速发展起来。

      挪威的最大的在线报纸 Verdens Gang(vg.no) 使用 3 台 Varnish 代替了原来的 12 台 Squid,性能比以前更好,这是 Varnish 最成功的应用案例。      //这个看看就行

     varnish组成部分分为三部分:
     1、Management:命令行、子进程管理、编译VCL并应用新配置,监控vanish,初始化varnish。

     2、Child/cache: 命令行、缓存hash、日志数据统计、接收用户请求、工作线程、与后端主机的连接,缓存有效性验证清理。

     3、VCL: 控制缓存机制,而不是控制varnish,调用C编译器,生成二进制程序,让子进程加载。

  

   

       varnish存储缓存内容的方法:      

    1、file:自管理的文件系统,黑盒,只对当前进程有效,不支持持久机制;

       2、malloc:使用内存分配函数malloc()库调用varnish启动时向内存申请指定大小的空间;

       3、persisent:与file功能相同;仍处于测试期,基于文件的持久存储。

    

缓存:

       把向服务器端请求到的资源缓存到本地,提供响应速率,并减少对后端服务器的压力,但并不是所有的数据都需要缓存,缓存的数据必须要有热点性,如果数据不存在热点性,那缓存也没什么意义,而且私有数据是不能缓存的。

      衡量一个缓存的有效性:            

        缓存命中率:hit/(hit+miss)

               文档命中率: 从文档个数进行衡量

                字节命中率: 从内容的大小进行衡量       

        缓存的生命周期:   

                   缓存的清理有两种情况

                缓存项过期:   惰性清理

                缓存空间用尽:LRU算法  

     一个缓存项的过期并不会真正从内存中清理,只是简单标记为失效,而不是把它删除,只有当缓存空间空间用尽时,才会真正的删除缓存项。

     因为缓存都有生命周期,如果判断缓存是否有效,可以根据新鲜度检测及有效性再验正:revalidate。     

   新鲜度检测机制:给予过期日期,多久之后才消失

    HTTP/1.0 Expires,                         给予的是绝对时长,缺点是时间不同步会导致缓存总是失效

Expires:Thu, 04 Jun 2015 23:38:18 GMT   

    HTTP/1.1 Cache-Control: max-age   给予的是相对时长,接收到响应报文后开始算起

Cache-Control:max-age=600

     有效性再验正:revalidate

  如果原始内容未改变,则仅响应首部(不附带body部分),响应码304 (Not Modified)

  如果原始内容发生改变,则正常响应,响应码200;

  如果原始内容消失,则响应404,此时缓存中的cache object也应该被删除;

      有效性在验证时的条件式请求首部:

  If-Modified-Since:   基于请求内容的最近一次修改的时间戳作验正;(返回200,并响应新的内容)

  If-Unmodified-Since:  基于请求内容的最近的一次是否发生改变  (返回304  not modified) 

  If-Match:      基于请求内容的匹配做验证

  If-None-Match: 基于Etag的比较进行内容验证


一个完整的缓存处理请求:

     接收请求-->解析请求(提取请求的URL及各种首部)-->根据key来查询缓存-->新鲜度检测-->有效性在验证-->创建响应报文-->发送响应-->记录日志


一、安装varnish

]# yum -y install varnish
]# rpm -ql varnish
/etc/varnish
/etc/varnish/default.vcl               //VCL配置文件,管理缓存策略
/etc/varnish/varnish.params            //varnish配置参数

编辑varnish配置参数文件:

]# vim /etc/varnish/varnish.params 
RELOAD_VCL=1                                 //重新编译VCL配置文件
VARNISH_VCL_CONF=/etc/varnish/default.vcl    //VCL配置文件
# VARNISH_LISTEN_ADDRESS=192.168.1.5        //监听的IP地址
VARNISH_LISTEN_PORT=6080                    //监听的端口,如果作为反向代理则需要改成80
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1      //管理varnish程序的地址
VARNISH_ADMIN_LISTEN_PORT=6082              //管理varnish的端口
VARNISH_STORAGE="file,/var/lib/varnish/varnish_storage.bin,1G"       
                                     varnish_storage.bin 二进制文件    //缓存内容的存储
VARNISH_TTL=120                             //默认缓存的有效期
DAEMON_OPTS="-p thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300
                                            //定义其他扩展选项,调优专用

请求报文的流程图:

技术分享

 vcl:

         1、"域"专用的编程语言,类似于iptables的钩子函数,只要符合要求的都处理,不符合要求的跳转到下一个状态。

         2、状态引擎:                 

            vcl_recv:接收

            vcl_hash:hash

                   vcl_hit:  命中

                   vcl_miss:  未命中

                   vcl_purge: 清缓存

                   vcl_pipe:  建立管道,直接送到后端主机

                   vcl_pass:  跳过,直接传送到pass                               

            vcl_backend_fetch   后端取数据

            vcl_backend_response

            vcl_backend_error                  

            vcl_synth:  同步

            vcl_deliver:返回客户端


数据报文请求流向:

         vcl_recv -->vcl_hash(对请求的内容做hash计算)-->分为四种情况

        1、如果命中(vcl_hit )-->直接发送给客户端(vcl_deliver)或者vcl_pass,不请求缓存,直接传递给后端(vcl_backend_fetch

                2、如果未命中(vcl_miss)-->发送给vcl_pass,再由vcl_pass传递给后端取数据,或者直接传递给后端

                3、如果请求的是purge,则直接清理缓存并同步vcl_synth

                4、如果请求的内容未知,则vcl_pipe(管道)直接传递给后端主机,varnish只缓存静态文件               

       vcl_backend_fetch -->

                 1、后端主机处理完后发送响应报文给varnish,varnish判断是否可以缓存,然后响应给客户端

                 2、后端主机也处理不了,直接返回error给varnish,然后响应给客户端

        

VCL支持的语法: 

    vcl的语法:

             1、//,#,/*...*/ :注释

             2、sub $name: 定义子历程:

                      sub vcl_recv {

                      }

             3、不支持循环,支持条件判断                   

            if (CONDTION) {

            } else {

                 }    

             4、有内建变量;

                      req.http    resp.http

             5、使用终止语句return,没有返回值

             6、操作符:==,==,!=,~,&&,||

    

VCL的内建变量:

    内建变量:

           req.*:  请求,接收客户端的请求  

             req.http.*;请求报文各首部值

           resp.*:   由varnish响应给client的http的响应报文;

          resp.http:响应报文的首部

           bereq.*:  由varnish向backend主机发出的http请求; 

           beresp.*:由后端主机发来的响应报文的首部;(在vcl_fetch和vcl_respone中实现)

           obj.*:   存储在缓存空间中的缓存对象属性;只读;                    

              client.*:  可用在所有的client side的sub routines中

              server.*:  varnish主机                

              storage.*:  存储类型


      常用的内建变量:                 

      bereq:varnish请求后端主机的报文

        bereq.http.HEADERS: 由varnish发往backend server的请求报文的指定首部;

bereq.request:请求方法;

bereq.url:  请求的url

bereq.proto:请求的协议版本

bereq.backend:指明要调用的后端主机;


          beresp   后端返回的响应报文

beresp.proto   协议版本

beresp.status:后端服务器的响应的状态码

beresp.reason:原因短语;

beresp.backend.ip:  获取后端服务器的IP  

beresp.backend.name:获取后端服务器的名称

beresp.http.HEADER: 从backend server响应的报文的首部;

beresp.ttl:后端服务器响应的内容的余下的生存时长;


           obj:对象

obj.ttl: 对象的ttl值;缓存时长

obj.hits:此对象从缓存中命中的次数;


          server: varnish主机

server.ip              获取varnish的ip

server.hostname  获取varnish的主机名

server.port          获取varnish的端口


          req:接收客户端的请求

                req.method:  请求方法

                req.url:     请求的url 


自定义变量:

    set beresp.ttl = varlue

        set resp.http.X-cache = value


编辑VCL配置文件:

backend webser1 {                //设置后端主机
    .host = "172.18.250.76";
    .port = "80";
}

示例:设置响应首部,查看缓存是否命中:

sub vcl_deliver {    
    if(obj.hits>0) {
     set resp.http.X-cache = "HIT" + “ ” + server.ip;
    }else{
     set resp.http.X-cache = "MISS" + “ ” + server.ip;
    }
}

技术分享

第二次请求就为HIT:

技术分享


示例:强制对某资源进行请求,不检查缓存:

sub vcl_recv {
    if(req.url ~ "^/index.html"){
     return(pass)
    }
}

  技术分享     

    


对特定类型的资源,例如公开的图片等,取消其私有的cookie标识,并强行设定其可以varnish缓存的时长:

if (beresp.http.cache-control !~ "s-maxage") {      
       if (bereq.url ~ "(?i).jpg$") {                 //(?i)不区分大小写
        set beresp.ttl = 60s;
        unset beresp.http.Set-Cookie;
       }
   }

技术分享


示例:清理缓存缓存

sub vcl_recv {
    if(req.method == "PURGE"){
      if(client.ip !~ purges){
      return(synth(405));
       }
      return(purge);
    }
}
]# curl -X PURGE http://172.18.250.77
<!DOCTYPE html>
<html>
  <head>
    <title>200 purges</title>


二、varnish可以作为负载均衡:

]# vim /etc/varnish/default.vcl
import directors;

backend default1 {
    .host = "172.18.250.76";
    .port = "80";
}

backend default2 {
    .host = "172.18.250.78";
    .port = "80";
}
sub vcl_init {
     new mycluster = directors.round_robin();
     mycluster.add_backend(default1);
     mycluster.add_backend(default2);
}
vcl_recv {
     set req.backend_hint = mycluster.backend();
}

技术分享

技术分享


三、varnish也可以对后端主机进行健康状态检测:

backend default {
      .host = "172.16.100.68";
      .port = "80";
      .probe = {
      .url = "/test1.html";          //测试页
      .interval = 1s;               //扫描时间
      .window = 8;                 //最近探测的次数
      .threshold = 5;             //探测有5次返回正常才算健康
      .timeout = 2s;              //后端主机超时时长 
       }
}


四、varnish也提供了很多命令行工具:

]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
200        
-----------------------------
Varnish Cache CLI 1.0
-----------------------------
Linux,3.10.0-229.el7.x86_64,x86_64,-sfile,-smalloc,-hcritbit
varnish-4.0.3 revision b8c4a34

Type ‘help‘ for command list.
Type ‘quit‘ to close CLI session.
]# varnishstat

技术分享

以上是关于缓存服务之varnish的简单应用的主要内容,如果未能解决你的问题,请参考以下文章

linux之搭建varnish缓存代理服务器

缓存服务器之memcached和varnish

Varnish缓存机制详细介绍及简单配置

加速与缓存技术之Varnish

Varnish缓存服务及应用

varnish简单入门