Varnish基础原理及简单配置

 

Varnish基础原理及简单配置

  1. Varnish简介:

    Varnish是一填款高性能的开源HTTP加速器,同时作为http反向缓存 补充资料: http://book.varnish-software.com/4.0/

    特点

    • Varnis可以使用内存也可以使用硬盘进行数据缓存
    • 支持虚拟内存的使用
    • 有精确的时间管理机制
    • 状态引擎架构:通过特定的配置语言设计不同的语句
    • 以二叉堆格式管理数据

    优势:

    • varnish访问速度快,因为采用了“Visual Page Cache”技术,在读取数据时直接从内存中读取
    • varnish支持更多的并发连接,因为varnish的TCP连接比squid快
    • varnish通过管理端口,使用正则表达式批量的清除部分缓存

    劣势

    • 进程一旦crash或重启,缓存的数据将从内存中完全释放,导致后端服务器压力过大,重新启动的热身时间,需要耗时数小时不等
    • 在多台varnish实现负载均衡时,每次请求都会落到不同的varnish服务器中,造成url请求可能会穿透到后端

      解决方案:

      A:在varnish的后端添加squid/nginx代理,这样防止了当varnish缓存被清空时,瞬间大量的请求发往web服务器

      B:在负载均衡上做hash request_url,让单个url请求固定请求到一台varnish服务器上


  2. varnish组成:

    Management进程,用来管理进程,对child进程进行管理,同时对vcl配置进行编译

    child进程,子进程,生成线程池,负责处理用户请求

    阶段:

    • req:处理客户端发送的请求时使用
    • bereq:处理varnish向后端服务器发送的请求时使用
    • beresp:处理后端服务器响应时使用,用于varnish未缓存前
    • resp:处理返回给客户端的响应时使用
    • obj:处理存储在内存中的对象时使用



    varnish工作流程图:
  3. 客户端发送的请求对象
    阶段对象说明
    req整个HTTP请求数据结构
    req.backend_hint指定请求的后端节点
    req.http对应请求HTTP的header
    req.can_gzip客户端是否接受GZIP传输编码
    req.hash_always_miss是否强制不命中高速缓存
    req.hash_ignore_busy忽略缓存中忙碌的对象,多台缓存时可以避免死锁
    req.method请求类型(如GET,POST)
    req.restarts重新启动次数,默认最大值是4
    req.ttl缓存剩余时间
    req.url请求的url
    req.xid唯一ID
  4. 发送到后端的请求对象
    bereq整个后端请求后数据结构
    bereq.backend所请求后端节点配置
    bereq.between_bytes_timeout从后端每接收一个字节之间的等待时间(秒)
    bereq.connect_timeout连接后端等待时间(秒),最大等待时间
    bereq.first_byte_timeout等待后端第一个字节时间(秒),最大等待时间
    bereq.http对应发送到后端HTTP的header信息
    bereq.method发送到后端的请求类型
    bereq.uncacheable无缓存这个请求
    bereq.url发送到后端请求的URL
    bereq.xid请求唯一ID
  5. 后端响应请求对象
    beresp整个后端响应HTTP数据结构
    beresp.backend.ip后端响应的IP
    beresp.backend.name响应后端配置节点的name
    beresp.do_gunzip默认为false,缓存前解压该对象
    beresp.do_gzip默认为false,缓存前压缩该对象
    beresp.grace设置当前对象缓存过期后可额外宽限时间
    beresp.http对应的HTTP请求header
    beresp.keep对象缓存后带保持时间
    beresp.reason由服务器返回的HTTP状态信息
    beresp.status由服务器返回的状态码
    beresp.storage_hint指定保存的特定存储器
    beresp.ttl该对象缓存的剩余时间,指定统一缓存剩余时间
    beresp.uncacheable继承bereq.uncacheable,是否不缓存
  6. 高速缓存对象,缓存后端响应请求内容 服务器返回的状态码
    obj.grace该对象额外宽限时间
    obj.hits缓存命中次数
    obj.http对应HTTP的header
    obj.reason服务器返回的HTTP状态信息
    obj.status
    obj.ttl该对象缓存剩余时间秒
    obj.uncacheable不缓存对象
  7. 返回给客户端的响应对象
    resp整个响应HTTP数据结构
    resp.http对应HTTP的hearder
    resp.proto编辑响应的HTTP协议版本
    resp.reason将要返回的HTTP状态信息
    resp.status将要返回的HTTP状态码


  8. 运算符:
    • =:赋值运算
    • ==:相等比较
    • ~ :匹配,可以使用正则表达式,或访问控制列表
    • !~:不匹配,可以使用正则表达式,或访问控制列表
    • ! :非
    • &&:逻辑与
    • ||:逻辑或


  9. 功能语句与对象
    一般功能语句都用于匹配对象,就是对某个对象实现什么操作
    • ban():清除指定对象缓存
    • ban_url(regex):可以清除被此处匹配到的缓存
    • call():调用子程序
    • hash_data():生成hash键值,只能在vck_hash子程序中使用
    • new():创建一个vcl对象,只能在vcl_init子程序中使用
    • return():结束当前子程序并执行下一步动作
    • rollback():恢复http头到原来的状态,现在使用std.rollback()代替
    • synthetic():合成器,用于自定义一个响应内容,只能在vcl_synth和vcl_backend_error子程序中使用
    • regsub(str,regex,sub):把str中被regex第一次匹配到字符串替换为sub;主要用于URL Rewrite
    • regsuball(str,regex,sub):把str中被regex每一次匹配到字符串均替换为sub;
    • return的常用动作
      语法:return (action)
    • abandon:放弃处理,并生成一个错误
    • deliver:交付至后端处理
    • fetch:从后端取出响应对象
    • hash:哈希缓存处理
    • lookup:从缓存中查找应答数据并返回,如果查找不到,则调用pass函数,从后端服务器调用数据
    • ok:继续执行
    • pass:绕过缓存,直接向后端服务器调用数据
    • pipe: 建立客户端和后端服务器之间的直接连接,之后客户端的所有请求都直接发送给服务器,绕过varnish,不再由varnish检查请求,直到断开连接
    • purge:清除缓存对象,构建响应
    • restart:重新开始
    • retry: 重试后端处理
    • synth 合成响应报文,响应客户端

      varnish中内置子程序:
    • 子进程也叫状态引擎,每一个状态引擎均有自己限定的返回动作return,不同的动作将调用对应下一个状态引擎。

    • 我们可以把一个请求分为多个阶段,每个阶段都会调用不同的状态引擎去操作,这样,我们只编写出相应的状态引擎,就可认控制每个请求阶段

    • varnish内置子程序均有自己限定的返回动作return,不同的动作将调用对应下一个子程序 每个子程序都需要通过关键字sub进行定义

  10. vcl_recv子程序
    开始处理请求,通过return(动作);选择varnish处理模式,默认进入hash缓存模式(即return(hash);),缓存时间为配置default_ttl(默认为120秒)过期保持时间default_grace(过期容忍时间,默认为10秒)。该子程序一般用于模式选择,对象缓存及信息修改,后端节点修改,终止请求等操作
    返回值:synth,pass,pipe,hash,pruge
  11. vcl_pipe子程序
    pipe模式处理,该模式主要用于直接取后端响应内容返回客户端,可定义响应内容返回客户端。该子程序一般用于需要及时且不作处理的后端信息,取出后端响应内容后直接交付到客户端不进入vcl_deliver子程序处理
    返回值:synth,pipe
  12. vcl_pass子程序
    pass模式处理,该模式类似hash缓存模式,仅不做缓存处理
    返回值:synth,fetch:继续pass模式,进入后端vcl_backend_fetch子程序,默认返回值
  13. vcl_hit子程序
    hash缓存模式时存在hash缓存时调用,用于缓存处理,可放弃或修改缓存
    返回值:restart,deliver默认返回值,synth
  14. vcl_miss子程序
    hash缓存模式时不存在hash缓存时调用,用于判断性的选择进入后端取响应内容,可以修改为pass模式
    返回值:restart重启请求,synth,pass,fetch:正常取后端内容再缓存,进入vcl_backend_fetch子程序,默认返回值
  15. vcl_hash
    hash缓存模式,生成hash值作为缓存查找键名提取缓存内容,主要用于缓存hash键值处理,可使用hash_data(string)指定键值组成结构,可在同一页面通过IP或Cookie生成不同的缓存键值
    返回值:lookup:查找缓存对象,存在缓存进入vcl_hit子程序,不存在缓存进入vcl_miss子程序,当使用了purge清理模式时会进入vcl_purge子程序,默认返回值
  16. acl_purge子程序
    清理模式,当查找到对应的缓存时清除并调用,用于请求方法清除缓存,并报告
    返回值:synth,restart
  17. vcl_deliver子程序
    客户端交付子程序,在vcl_backend_response子程序后调用(非pipe模式),或vcl_hit子程序后调用,可用于追加响应头信息,cookie等内容
    返回值:deliver,restart
  18. vcl_backend_fetch子程序
    发送后端请求之前调用,可用于改变请求地址或其它信息,或放弃请求
    返回值:fetch:正常发送请求到后端取出响应内容,进入vcl_backend_response子程序,默认返回值,abandon
  19. vcl_backend_redponse子程序
    后端响应后调用,可用于修改缓存时间及缓存相关信息
    返回值:deliver,abandon,retry:重试后端请求,重试计数器加1,当超过配置中max_retries值时会报错并进入vcl_backend_error子程序
  20. vcl_backend_error子程序
    后端处理失败调用,异常页面展示效果处理,可自定义错误响应内容,或修改beresp.status与beresp.http.Location重定向等
    返回值:deliver,retry
  21. vcl_synth子程序
    自定义响应内容,可以通过synthetic()和返回值synth调用,这里可以自定义异常显示内容,也可以修改resp.status与resp.http.Location重定向
    返回值:deliver,restart
  22. vcl_init子程序
    加载vcl时最先调用,用于初始化VMODs,该子程序不参与请求处理,仅在vcl加载时调用一次
    返回值:ok
  23. vcl_fini子程序
    卸载当前vcl配置时调用,用于清理VMODs,该子程序不参与请求处理,仅在vcl正常丢弃后调用
    返回值:ok


  24. 后端服务器定义:

    属性说明
    .host= "IP";要转向主机(即后端主机)的IP或域名,必填键值对
    .port = "80";主机连接端口号或协议名(HTTP等),默认80
    .connect_timeout = 0.5s;连接后端主机的超时时长
    .first_byte_timeout = 2s;等待从后端返回的第一个字节时间
    .between_bytes_timeout = 2s;每接收一个字节之间等待时间
    .probe = probe_name监控后端主机的状态,指定外部监控name或者内部直接添加
    .max_connections = 1000;设置最大并发连接数,超过这个数后连接就会失败
  25. 监视器定义

    .url = "/";指定监控入口地址,默认为“/”
    .request = "";指定监控请求入口地址,比.url优先级高
    .timeout = "";超时时长
    .window = "";基于最近的多少次检查来判断其健康状态,默认为8
    .threshold = "";最近.window中定义的这么次检查中至少有.threshold定义的次数是成功的,默认是3
    .interval = "";检测频度,默认为5秒
    .initial = -1window中有几次是良好启用此节点
    .expected_reponse = "";期望的响应码,默认为200

  26. 检测实例:
    probe check {
            .url = "/";
            .timeout = 2s;
            .interval = 2s;    //这里又引入了新的问题,虽然会去自动检测后端主机的健康性,但是后端主机会记录日志的,如果设定的时间过短,会增大后端服务器的磁盘压力,过长,则会使用户感觉不好,设一个稳点的值
            .window = 8;
            .threshold = 6;
    }
    
    backend websrv {
            .host = "172.16.252.113";
            .port = "80";
            .max_connections = 500;
            .probe = check;
    }
    
    
    >backend.list
    200        
    Backend name                   Refs   Admin      Probe
    websrv(172.16.252.113,,80)     4      probe      Sick 5/8   //检测出来的效果sick生病了
    default(127.0.0.1,,8080)       4      probe      Healthy (no probe)
    backend.list
    200        
    Backend name                   Refs   Admin      Probe
    websrv(172.16.252.113,,80)     4      probe      Sick 4/8
    default(127.0.0.1,,8080)       4      probe      Healthy (no probe)
    backend.list
    200        
    


  27. PURGE和BAN操作,来清理特定的缓存,也可以在命令行中执行

    acl purgers {
        "127.0.0.1";
        "192.168.0.0"/24;
    }
    
    sub vcl_recv {
        # allow PURGE from localhost and 192.168.0...
        if (req.method == "PURGE") {
            if (!client.ip ~ purgers) {
                return (synth(405, "Purging not allowed for " + client.ip));
            }
            return (purge);
        }
    }
    
    sub vcl_purge {
        return (synth(200,"Purged,now!"));
    #   set req.method = "GET";
    #   return (restart);
    }
        if (req.method == "BAN") {
            if (!client.ip ~ purgers) {
            return (synth(405,"Banning not allowd for" + client.ip));
            }
       ban(" req.http.host == " + req.http.host + " && req.url == " + req.url);   //运算符边上必须有空格,要不然会实现不了功能的
        return (synth(200,"Ban added."));
        }
    
    
    
    操作:
    ~]# varnish -S /etc/varnish/secret -T 127.0.0.1:6082
    vcl.load test1 default.vcl
    vcl.use test1 
    也可在此操作清除缓存:
    ban req.url ~ .js$    //清除以.js结尾的文件缓存,毕竟可以用正则表达式,多方便
    
    
    客户端操作:
    ~]# crul -I http://172.16.254.35
    HTTP/1.1 200 OK
    Server: nginx/1.10.2
    Date: Tue, 27 Jun 2017 09:27:38 GMT
    Content-Type: text/html
    Content-Length: 17
    Last-Modified: Tue, 27 Jun 2017 06:21:47 GMT
    ETag: "5951f97b-11"
    X-Varnish: 3964978
    Age: 0
    Via: 1.1 varnish-v4
    X-Cache: Miss via172.16.254.35  //没有命中
    Connection: keep-alive
    
    ~]# curl -I http://172.16.254.35/index.html
    ....
    X-Cache: Hit via172.16.254.35  //命中
    ...
    
    进行PURGE操作:
    ~]# curl -X PURGE http://172.16.254.35/index.html
    ...
    Error 405 Purging not allowed for172.16.251.81
    ...
    再次访问:
    ~]# curl -I http://172.16.254.35/index.html
    ...
    X-Cache: Miss via172.16.254.35  //不能命中缓存
    ...
    ~]# curl -I http://172.16.254.35/index.html
    ....
    X-Cache: Hit via172.16.254.35  //命中
    ...
    
    进行BAN操作:
    ~]# curl -X BAN http://172.16.254.35/index.html
    ...
    Error 405 Purging not allowed for172.16.251.81
    ...
    再次访问:
    ~]# curl -I http://172.16.254.35/index.html
    ...
    X-Cache: Miss via172.16.254.35  //不能命中缓存
    ...
    ~]# curl -I http://172.16.254.35/index.html
    ....
    X-Cache: Hit via172.16.254.35  //命中
    ...    
    


  28. 实例:在缓存中,强制对某类资源的请求不检查缓存:
    vcl_recv {
        if (req.url ~ "(?i)^/(login|admin)") {   //(?i)不区分字符大小写
            return(pass);
        }
    }    
    

  29. 实例:对于特定类型的资源,例如公开的图片等,取消其私有标识,并强行设定其可以由varnish缓存的时长;定义在vcl_backend_response中
    if (beresp.http.cache-control !~ "s-maxage") {    //如果后端服务器没有给缓存时长
        if (bereq.url ~ "(?i)\.(jpg|jpeg|png|gif|css|js)$") {   //同时匹配以.jpg...结尾的文件
            unset beresp.http.Set-Cookie;  //说明:默认情况下,varnish不缓存从后端响应的http头中带有Set-Cookie的对象。如果客户端发送的请求带有Cookie header,varnish将忽略缓存,直接将请求递送至后端服务器上
            set beresp.ttl = 3600s;  //设置后端响应首部的生存时长为1h
        }
    }
    

  30. 实例:将真实的客户IP地址转移至后端服务器上,以便日志记录
    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;
        }
    }
    


  31. 最后的一个整体笔记:
    import directors;   //负载均衡集群需要directors模块支持,import directors
    
    acl purgers {    //对缓存资源进行控制
            "127.0.0.1";
            "172.16.0.0"/16;
    }
    
    
    
    probe check {    //对后端服务器的状态检测
            .url = "/";
            .timeout = 2s;
            .interval = 10s;
            .window = 8;
            .threshold = 6;
    }
    
    backend websrv {      //定义后端主机的属性
            .host = "172.16.252.113";
            .port = "80";
            .max_connections = 500;
            .port = "80";
            .max_connections = 500;
            .probe = check;      //执行健康状态检测
    }
    backend websrv2 {
            .host = "172.16.250.84";
            .port = "80";
            .probe = check;
    }
    
    
    
    
    # Default backend definition. Set this to point to your content server.
    backend default {      
        .host = "127.0.0.1";
        .port = "8080";
    }
    
    sub vcl_init {      //初始化子程序创建后端主机组,即directors
            new WEBGROUP = directors.round_robin();   //使用new关键字创建director对象,使用round_robin算法
            WEBGROUP.add_backend(websrv);
            WEBGROUP.add_backend(websrv2);
            WEBGROUP.add_backend(websrv);
            WEBGROUP.add_backend(websrv2);
    }
    
    
    sub vcl_recv {           //接受请求子程序
    
            set req.backend_hint = WEBGROUP.backend(); //调用后端主机组
    
            if (req.url ~ "(?i)\.(JPG|PNG|GIF)") {   //对几种图片不进行缓存查找
                    return(pass);
            }
    
            if (req.restarts == 0) {     //IP地址转移
                    if (req.http.X-Forwarded-For) {
                            set req.http.x-forwarded-for = req.http.x-forwarded-for + "," + client.ip;
                    } else {
                            set req.http.x-forwarded-for = client.ip;
                    }
            }
    
        
            if (req.method == "PURGE") {   //对某个缓存对象进行清理操作
                    if (!client.ip ~ purgers) {
                            return (synth(405,"Purging not allowed for" + client.ip));
                    }
            return (purge);    //去往purge子程序操作
            }
    
            if (req.method == "BAN") {     //清理某一类缓存对象
                    if (!client.ip ~ purgers) {
                            return (synth(405,"Banning not allowd for" + client.ip));
                    }
                    ban("req.http.host == " + req.http.host + " && req.url == " + req.url);//清除host+url的对象
                    return (synth(200,"Ban added."));    
            }
    
    #       if (req.url ~ "(?i)\.php$") {      //以.php请求至后端
    #               set req.backend_hint = websrv;
    #       } else {
    #               set req.backend_hint = default;
    #       }
    }
    
    
    sub vcl_purge {    //purge子程序
            return (synth(200,"Purged"));//合成信息,并返回值
    #       set req.method = "GET";//将请求方法设置成GET
    #       return (restart);//在发还给客户端,让客户端重新来取
    
    }
    
    
    
    sub vcl_backend_response {
        # Happens after we have read the response headers from the backend.
        #
        # Here you clean the response headers, removing silly Set-Cookie headers
        # and other mistakes your backend does.
    }
    
    
    sub vcl_deliver {   //发送给客户的数据报文
        if (obj.hits>0) {   //测试用,如果 有缓存,就把X-Cache首部信息发给客户端
            set resp.http.X-Cache = "Hit via" + server.ip;
        } else {
            set resp.http.X-Cache = "Miss via" + server.ip;
        }
    }
    


    varnish日志区域:
    1、varnishstat - Varnish Cache statistics

    -1 //显示一次

    -1 -f FILED_NAME

    -l:可用于-f选项指定的字段名称列表;

    MAIN.cache_hit

    MAIN.cache_miss

    # varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss

    # varnishstat -l -f MAIN -f MEMPOOL

    2、varnishtop - Varnish log entry ranking

    -1 Instead of a continously updated display, print the statistics once and exit.

    -i taglist,可以同时使用多个-i选项,也可以一个选项跟上多个标签;

    -I <[taglist:]regex>

    -x taglist:排除列表

    -X <[taglist:]regex>

    3、varnishlog - Display Varnish logs

    4、 varnishncsa - Display Varnish logs in Apache / NCSA combined log format

    systemctl start varnishncsa.service //开启日志功能服务

Varnish基础原理及简单配置

  1. Varnish简介:

    Varnish是一填款高性能的开源HTTP加速器,同时作为http反向缓存 补充资料: http://book.varnish-software.com/4.0/

    特点

    • Varnis可以使用内存也可以使用硬盘进行数据缓存
    • 支持虚拟内存的使用
    • 有精确的时间管理机制
    • 状态引擎架构:通过特定的配置语言设计不同的语句
    • 以二叉堆格式管理数据

    优势:

    • varnish访问速度快,因为采用了“Visual Page Cache”技术,在读取数据时直接从内存中读取
    • varnish支持更多的并发连接,因为varnish的TCP连接比squid快
    • varnish通过管理端口,使用正则表达式批量的清除部分缓存

    劣势

    • 进程一旦crash或重启,缓存的数据将从内存中完全释放,导致后端服务器压力过大,重新启动的热身时间,需要耗时数小时不等
    • 在多台varnish实现负载均衡时,每次请求都会落到不同的varnish服务器中,造成url请求可能会穿透到后端

      解决方案:

      A:在varnish的后端添加squid/nginx代理,这样防止了当varnish缓存被清空时,瞬间大量的请求发往web服务器

      B:在负载均衡上做hash request_url,让单个url请求固定请求到一台varnish服务器上


  2. varnish组成:

    Management进程,用来管理进程,对child进程进行管理,同时对vcl配置进行编译

    child进程,子进程,生成线程池,负责处理用户请求

    阶段:

    • req:处理客户端发送的请求时使用
    • bereq:处理varnish向后端服务器发送的请求时使用
    • beresp:处理后端服务器响应时使用,用于varnish未缓存前
    • resp:处理返回给客户端的响应时使用
    • obj:处理存储在内存中的对象时使用



    varnish工作流程图:
  3. 客户端发送的请求对象
    阶段对象说明
    req整个HTTP请求数据结构
    req.backend_hint指定请求的后端节点
    req.http对应请求HTTP的header
    req.can_gzip客户端是否接受GZIP传输编码
    req.hash_always_miss是否强制不命中高速缓存
    req.hash_ignore_busy忽略缓存中忙碌的对象,多台缓存时可以避免死锁
    req.method请求类型(如GET,POST)
    req.restarts重新启动次数,默认最大值是4
    req.ttl缓存剩余时间
    req.url请求的url
    req.xid唯一ID
  4. 发送到后端的请求对象
    bereq整个后端请求后数据结构
    bereq.backend所请求后端节点配置
    bereq.between_bytes_timeout从后端每接收一个字节之间的等待时间(秒)
    bereq.connect_timeout连接后端等待时间(秒),最大等待时间
    bereq.first_byte_timeout等待后端第一个字节时间(秒),最大等待时间
    bereq.http对应发送到后端HTTP的header信息
    bereq.method发送到后端的请求类型
    bereq.uncacheable无缓存这个请求
    bereq.url发送到后端请求的URL
    bereq.xid请求唯一ID
  5. 后端响应请求对象
    beresp整个后端响应HTTP数据结构
    beresp.backend.ip后端响应的IP
    beresp.backend.name响应后端配置节点的name
    beresp.do_gunzip默认为false,缓存前解压该对象
    beresp.do_gzip默认为false,缓存前压缩该对象
    beresp.grace设置当前对象缓存过期后可额外宽限时间
    beresp.http对应的HTTP请求header
    beresp.keep对象缓存后带保持时间
    beresp.reason由服务器返回的HTTP状态信息
    beresp.status由服务器返回的状态码
    beresp.storage_hint指定保存的特定存储器
    beresp.ttl该对象缓存的剩余时间,指定统一缓存剩余时间
    beresp.uncacheable继承bereq.uncacheable,是否不缓存
  6. 高速缓存对象,缓存后端响应请求内容 服务器返回的状态码
    obj.grace该对象额外宽限时间
    obj.hits缓存命中次数
    obj.http对应HTTP的header
    obj.reason服务器返回的HTTP状态信息
    obj.status
    obj.ttl该对象缓存剩余时间秒
    obj.uncacheable不缓存对象
  7. 返回给客户端的响应对象
    resp整个响应HTTP数据结构
    resp.http对应HTTP的hearder
    resp.proto编辑响应的HTTP协议版本
    resp.reason将要返回的HTTP状态信息
    resp.status将要返回的HTTP状态码


  8. 运算符:
    • =:赋值运算
    • ==:相等比较
    • ~ :匹配,可以使用正则表达式,或访问控制列表
    • !~:不匹配,可以使用正则表达式,或访问控制列表
    • ! :非
    • &&:逻辑与
    • ||:逻辑或


  9. 功能语句与对象
    一般功能语句都用于匹配对象,就是对某个对象实现什么操作
    • ban():清除指定对象缓存
    • ban_url(regex):可以清除被此处匹配到的缓存
    • call():调用子程序
    • hash_data():生成hash键值,只能在vck_hash子程序中使用
    • new():创建一个vcl对象,只能在vcl_init子程序中使用
    • return():结束当前子程序并执行下一步动作
    • rollback():恢复http头到原来的状态,现在使用std.rollback()代替
    • synthetic():合成器,用于自定义一个响应内容,只能在vcl_synth和vcl_backend_error子程序中使用
    • regsub(str,regex,sub):把str中被regex第一次匹配到字符串替换为sub;主要用于URL Rewrite
    • regsuball(str,regex,sub):把str中被regex每一次匹配到字符串均替换为sub;
    • return的常用动作
      语法:return (action)
    • abandon:放弃处理,并生成一个错误
    • deliver:交付至后端处理
    • fetch:从后端取出响应对象
    • hash:哈希缓存处理
    • lookup:从缓存中查找应答数据并返回,如果查找不到,则调用pass函数,从后端服务器调用数据
    • ok:继续执行
    • pass:绕过缓存,直接向后端服务器调用数据
    • pipe: 建立客户端和后端服务器之间的直接连接,之后客户端的所有请求都直接发送给服务器,绕过varnish,不再由varnish检查请求,直到断开连接
    • purge:清除缓存对象,构建响应
    • restart:重新开始
    • retry: 重试后端处理
    • synth 合成响应报文,响应客户端

      varnish中内置子程序:
    • 子进程也叫状态引擎,每一个状态引擎均有自己限定的返回动作return,不同的动作将调用对应下一个状态引擎。

    • 我们可以把一个请求分为多个阶段,每个阶段都会调用不同的状态引擎去操作,这样,我们只编写出相应的状态引擎,就可认控制每个请求阶段

    • varnish内置子程序均有自己限定的返回动作return,不同的动作将调用对应下一个子程序 每个子程序都需要通过关键字sub进行定义

  10. vcl_recv子程序
    开始处理请求,通过return(动作);选择varnish处理模式,默认进入hash缓存模式(即return(hash);),缓存时间为配置default_ttl(默认为120秒)过期保持时间default_grace(过期容忍时间,默认为10秒)。该子程序一般用于模式选择,对象缓存及信息修改,后端节点修改,终止请求等操作
    返回值:synth,pass,pipe,hash,pruge
  11. vcl_pipe子程序
    pipe模式处理,该模式主要用于直接取后端响应内容返回客户端,可定义响应内容返回客户端。该子程序一般用于需要及时且不作处理的后端信息,取出后端响应内容后直接交付到客户端不进入vcl_deliver子程序处理
    返回值:synth,pipe
  12. vcl_pass子程序
    pass模式处理,该模式类似hash缓存模式,仅不做缓存处理
    返回值:synth,fetch:继续pass模式,进入后端vcl_backend_fetch子程序,默认返回值
  13. vcl_hit子程序
    hash缓存模式时存在hash缓存时调用,用于缓存处理,可放弃或修改缓存
    返回值:restart,deliver默认返回值,synth
  14. vcl_miss子程序
    hash缓存模式时不存在hash缓存时调用,用于判断性的选择进入后端取响应内容,可以修改为pass模式
    返回值:restart重启请求,synth,pass,fetch:正常取后端内容再缓存,进入vcl_backend_fetch子程序,默认返回值
  15. vcl_hash
    hash缓存模式,生成hash值作为缓存查找键名提取缓存内容,主要用于缓存hash键值处理,可使用hash_data(string)指定键值组成结构,可在同一页面通过IP或Cookie生成不同的缓存键值
    返回值:lookup:查找缓存对象,存在缓存进入vcl_hit子程序,不存在缓存进入vcl_miss子程序,当使用了purge清理模式时会进入vcl_purge子程序,默认返回值
  16. acl_purge子程序
    清理模式,当查找到对应的缓存时清除并调用,用于请求方法清除缓存,并报告
    返回值:synth,restart
  17. vcl_deliver子程序
    客户端交付子程序,在vcl_backend_response子程序后调用(非pipe模式),或vcl_hit子程序后调用,可用于追加响应头信息,cookie等内容
    返回值:deliver,restart
  18. vcl_backend_fetch子程序
    发送后端请求之前调用,可用于改变请求地址或其它信息,或放弃请求
    返回值:fetch:正常发送请求到后端取出响应内容,进入vcl_backend_response子程序,默认返回值,abandon
  19. vcl_backend_redponse子程序
    后端响应后调用,可用于修改缓存时间及缓存相关信息
    返回值:deliver,abandon,retry:重试后端请求,重试计数器加1,当超过配置中max_retries值时会报错并进入vcl_backend_error子程序
  20. vcl_backend_error子程序
    后端处理失败调用,异常页面展示效果处理,可自定义错误响应内容,或修改beresp.status与beresp.http.Location重定向等
    返回值:deliver,retry
  21. vcl_synth子程序
    自定义响应内容,可以通过synthetic()和返回值synth调用,这里可以自定义异常显示内容,也可以修改resp.status与resp.http.Location重定向
    返回值:deliver,restart
  22. vcl_init子程序
    加载vcl时最先调用,用于初始化VMODs,该子程序不参与请求处理,仅在vcl加载时调用一次
    返回值:ok
  23. vcl_fini子程序
    卸载当前vcl配置时调用,用于清理VMODs,该子程序不参与请求处理,仅在vcl正常丢弃后调用
    返回值:ok


  24. 后端服务器定义:

    属性说明
    .host= "IP";要转向主机(即后端主机)的IP或域名,必填键值对
    .port = "80";主机连接端口号或协议名(HTTP等),默认80
    .connect_timeout = 0.5s;连接后端主机的超时时长
    .first_byte_timeout = 2s;等待从后端返回的第一个字节时间
    .between_bytes_timeout = 2s;每接收一个字节之间等待时间
    .probe = probe_name监控后端主机的状态,指定外部监控name或者内部直接添加
    .max_connections = 1000;设置最大并发连接数,超过这个数后连接就会失败
  25. 监视器定义

    .url = "/";指定监控入口地址,默认为“/”
    .request = "";指定监控请求入口地址,比.url优先级高
    .timeout = "";超时时长
    .window = "";基于最近的多少次检查来判断其健康状态,默认为8
    .threshold = "";最近.window中定义的这么次检查中至少有.threshold定义的次数是成功的,默认是3
    .interval = "";检测频度,默认为5秒
    .initial = -1window中有几次是良好启用此节点
    .expected_reponse = "";期望的响应码,默认为200

  26. 检测实例:
    probe check {
            .url = "/";
            .timeout = 2s;
            .interval = 2s;    //这里又引入了新的问题,虽然会去自动检测后端主机的健康性,但是后端主机会记录日志的,如果设定的时间过短,会增大后端服务器的磁盘压力,过长,则会使用户感觉不好,设一个稳点的值
            .window = 8;
            .threshold = 6;
    }
    
    backend websrv {
            .host = "172.16.252.113";
            .port = "80";
            .max_connections = 500;
            .probe = check;
    }
    
    
    >backend.list
    200        
    Backend name                   Refs   Admin      Probe
    websrv(172.16.252.113,,80)     4      probe      Sick 5/8   //检测出来的效果sick生病了
    default(127.0.0.1,,8080)       4      probe      Healthy (no probe)
    backend.list
    200        
    Backend name                   Refs   Admin      Probe
    websrv(172.16.252.113,,80)     4      probe      Sick 4/8
    default(127.0.0.1,,8080)       4      probe      Healthy (no probe)
    backend.list
    200        
    


  27. PURGE和BAN操作,来清理特定的缓存,也可以在命令行中执行

    acl purgers {
        "127.0.0.1";
        "192.168.0.0"/24;
    }
    
    sub vcl_recv {
        # allow PURGE from localhost and 192.168.0...
        if (req.method == "PURGE") {
            if (!client.ip ~ purgers) {
                return (synth(405, "Purging not allowed for " + client.ip));
            }
            return (purge);
        }
    }
    
    sub vcl_purge {
        return (synth(200,"Purged,now!"));
    #   set req.method = "GET";
    #   return (restart);
    }
        if (req.method == "BAN") {
            if (!client.ip ~ purgers) {
            return (synth(405,"Banning not allowd for" + client.ip));
            }
       ban(" req.http.host == " + req.http.host + " && req.url == " + req.url);   //运算符边上必须有空格,要不然会实现不了功能的
        return (synth(200,"Ban added."));
        }
    
    
    
    操作:
    ~]# varnish -S /etc/varnish/secret -T 127.0.0.1:6082
    vcl.load test1 default.vcl
    vcl.use test1 
    也可在此操作清除缓存:
    ban req.url ~ .js$    //清除以.js结尾的文件缓存,毕竟可以用正则表达式,多方便
    
    
    客户端操作:
    ~]# crul -I http://172.16.254.35
    HTTP/1.1 200 OK
    Server: nginx/1.10.2
    Date: Tue, 27 Jun 2017 09:27:38 GMT
    Content-Type: text/html
    Content-Length: 17
    Last-Modified: Tue, 27 Jun 2017 06:21:47 GMT
    ETag: "5951f97b-11"
    X-Varnish: 3964978
    Age: 0
    Via: 1.1 varnish-v4
    X-Cache: Miss via172.16.254.35  //没有命中
    Connection: keep-alive
    
    ~]# curl -I http://172.16.254.35/index.html
    ....
    X-Cache: Hit via172.16.254.35  //命中
    ...
    
    进行PURGE操作:
    ~]# curl -X PURGE http://172.16.254.35/index.html
    ...
    Error 405 Purging not allowed for172.16.251.81
    ...
    再次访问:
    ~]# curl -I http://172.16.254.35/index.html
    ...
    X-Cache: Miss via172.16.254.35  //不能命中缓存
    ...
    ~]# curl -I http://172.16.254.35/index.html
    ....
    X-Cache: Hit via172.16.254.35  //命中
    ...
    
    进行BAN操作:
    ~]# curl -X BAN http://172.16.254.35/index.html
    ...
    Error 405 Purging not allowed for172.16.251.81
    ...
    再次访问:
    ~]# curl -I http://172.16.254.35/index.html
    ...
    X-Cache: Miss via172.16.254.35  //不能命中缓存
    ...
    ~]# curl -I http://172.16.254.35/index.html
    ....
    X-Cache: Hit via172.16.254.35  //命中
    ...    
    


  28. 实例:在缓存中,强制对某类资源的请求不检查缓存:
    vcl_recv {
        if (req.url ~ "(?i)^/(login|admin)") {   //(?i)不区分字符大小写
            return(pass);
        }
    }    
    

  29. 实例:对于特定类型的资源,例如公开的图片等,取消其私有标识,并强行设定其可以由varnish缓存的时长;定义在vcl_backend_response中
    if (beresp.http.cache-control !~ "s-maxage") {    //如果后端服务器没有给缓存时长
        if (bereq.url ~ "(?i)\.(jpg|jpeg|png|gif|css|js)$") {   //同时匹配以.jpg...结尾的文件
            unset beresp.http.Set-Cookie;  //说明:默认情况下,varnish不缓存从后端响应的http头中带有Set-Cookie的对象。如果客户端发送的请求带有Cookie header,varnish将忽略缓存,直接将请求递送至后端服务器上
            set beresp.ttl = 3600s;  //设置后端响应首部的生存时长为1h
        }
    }
    

  30. 实例:将真实的客户IP地址转移至后端服务器上,以便日志记录
    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;
        }
    }
    


  31. 最后的一个整体笔记:
    import directors;   //负载均衡集群需要directors模块支持,import directors
    
    acl purgers {    //对缓存资源进行控制
            "127.0.0.1";
            "172.16.0.0"/16;
    }
    
    
    
    probe check {    //对后端服务器的状态检测
            .url = "/";
            .timeout = 2s;
            .interval = 10s;
            .window = 8;
            .threshold = 6;
    }
    
    backend websrv {      //定义后端主机的属性
            .host = "172.16.252.113";
            .port = "80";
            .max_connections = 500;
            .port = "80";
            .max_connections = 500;
            .probe = check;      //执行健康状态检测
    }
    backend websrv2 {
            .host = "172.16.250.84";
            .port = "80";
            .probe = check;
    }
    
    
    
    
    # Default backend definition. Set this to point to your content server.
    backend default {      
        .host = "127.0.0.1";
        .port = "8080";
    }
    
    sub vcl_init {      //初始化子程序创建后端主机组,即directors
            new WEBGROUP = directors.round_robin();   //使用new关键字创建director对象,使用round_robin算法
            WEBGROUP.add_backend(websrv);
            WEBGROUP.add_backend(websrv2);
            WEBGROUP.add_backend(websrv);
            WEBGROUP.add_backend(websrv2);
    }
    
    
    sub vcl_recv {           //接受请求子程序
    
            set req.backend_hint = WEBGROUP.backend(); //调用后端主机组
    
            if (req.url ~ "(?i)\.(JPG|PNG|GIF)") {   //对几种图片不进行缓存查找
                    return(pass);
            }
    
            if (req.restarts == 0) {     //IP地址转移
                    if (req.http.X-Forwarded-For) {
                            set req.http.x-forwarded-for = req.http.x-forwarded-for + "," + client.ip;
                    } else {
                            set req.http.x-forwarded-for = client.ip;
                    }
            }
    
        
            if (req.method == "PURGE") {   //对某个缓存对象进行清理操作
                    if (!client.ip ~ purgers) {
                            return (synth(405,"Purging not allowed for" + client.ip));
                    }
            return (purge);    //去往purge子程序操作
            }
    
            if (req.method == "BAN") {     //清理某一类缓存对象
                    if (!client.ip ~ purgers) {
                            return (synth(405,"Banning not allowd for" + client.ip));
                    }
                    ban("req.http.host == " + req.http.host + " && req.url == " + req.url);//清除host+url的对象
                    return (synth(200,"Ban added."));    
            }
    
    #       if (req.url ~ "(?i)\.php$") {      //以.php请求至后端
    #               set req.backend_hint = websrv;
    #       } else {
    #               set req.backend_hint = default;
    #       }
    }
    
    
    sub vcl_purge {    //purge子程序
            return (synth(200,"Purged"));//合成信息,并返回值
    #       set req.method = "GET";//将请求方法设置成GET
    #       return (restart);//在发还给客户端,让客户端重新来取
    
    }
    
    
    
    sub vcl_backend_response {
        # Happens after we have read the response headers from the backend.
        #
        # Here you clean the response headers, removing silly Set-Cookie headers
        # and other mistakes your backend does.
    }
    
    
    sub vcl_deliver {   //发送给客户的数据报文
        if (obj.hits>0) {   //测试用,如果 有缓存,就把X-Cache首部信息发给客户端
            set resp.http.X-Cache = "Hit via" + server.ip;
        } else {
            set resp.http.X-Cache = "Miss via" + server.ip;
        }
    }
    


    varnish日志区域:
    1、varnishstat - Varnish Cache statistics

    -1 //显示一次

    -1 -f FILED_NAME

    -l:可用于-f选项指定的字段名称列表;

    MAIN.cache_hit

    MAIN.cache_miss

    # varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss

    # varnishstat -l -f MAIN -f MEMPOOL

    2、varnishtop - Varnish log entry ranking

    -1 Instead of a continously updated display, print the statistics once and exit.

    -i taglist,可以同时使用多个-i选项,也可以一个选项跟上多个标签;

    -I <[taglist:]regex>

    -x taglist:排除列表

    -X <[taglist:]regex>

    3、varnishlog - Display Varnish logs

    4、 varnishncsa - Display Varnish logs in Apache / NCSA combined log format

    systemctl start varnishncsa.service //开启日志功能服务

 
 

你可能感兴趣的:(varnish)