阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Varnish的VCL子程序

302次阅读
没有评论

共计 6487 个字符,预计需要花费 17 分钟才能阅读完成。

VCL 子进程,在其中定制 Varnish 的行为。VCL 子例程可用于:添加自定义标头,更改 Varnish 错误消息的外观,在 Varnish 中添加 HTTP 重定向功能,清除内容以及定义缓存对象的哪些部分是唯一的。
注意:强烈建议尽可能让默认的内置子程序。内置子程序的设计考虑到安全性,这通常意味着它们可以合理的方式处理 VCL 代码中的任何缺陷。

vcl_recv

    规范化客户端输入
    选择一个后端 Web 服务器
    重新编写 Web 应用程序的客户端数据
    根据客户端输入决定缓存策略
    访问控制列表(ACL)安全屏障,例如针对 SQL 注入攻击
    修复错误,例如index.htlm- >index.html

vcl_recv 是 Varnish 第一个 VCL 子进程,将客户端请求解析为其基本数据结构之后执行。vcl_recv 有四个主要用途:

    修改客户端数据以减少缓存的多样性。决定使用哪个 Web 服务器。根据客户端数据决定缓存策略。执行特定 Web 应用程序所需的重写规则。

在 vcl_recv 你可以执行以下终止操作:

    pass:它通过缓存查找,但它执行 Varnish 请求流的其余部分。pass 不会将来自后端的响应存储在缓存中。pipe:此操作创建一个全双工管道,将客户端请求转发到后端,且不查看其内容。后端回复被转发回客户端且不缓存其内容。由于 Varnish 不再尝试将内容映射到请求上,因此任何子进程的请求发送给活动连接将被通过 pipe 转发。pipe请求不会出现在任何日志中。hash:它在缓存中查找请求。purge:它在缓存中查找请求以便删除它。synth - 从 Varnish 生成合成响应。这种合成响应通常是一个带有错误信息的网页。synth 也可以用来重定向客户端请求。

同样可以使用 vcl_recv 来设置以下安全措施。varnish 不是入侵检测系统的替代品,但仍可以用来提前阻止一些典型的攻击。简单访问控制列表(ACL)也可以应用到 vcl_recv 上。
内建的 vcl_recv 子进程不会缓存所有你想要的,同时也最好不要缓存错误内容而是把它们发送给错误的用户。
重新访问内置的 vcl_recv:

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

示例:

    基本设备检测
        sub vcl_recv {if (req.http.User-Agent ~ "iPad" ||
                req.http.User-Agent ~ "iPhone" ||
                req.http.User-Agent ~ "Android") {set req.http.X-Device = "mobile";
            } else {set req.http.X-Device = "desktop";
            }
        }

vcl_pass

    进入 pass 模式是调用
        sub vcl_pass {return (fetch);
        }

当上一层子进程返回 pass 动作后才会调用 vcl_pass 子进程。这动作的请求是在 pass 模式中设置的。vcl_pass 通常作为一个重要的 catch-all,服务于 vcl_hit 和 vcl_miss 执行结果。
vcl_pass 可能会返回是三个动作:fetch、synth、或者是 restart。当返回的的是 fetch 时,正在进行的请求就采用 pass 模式。采用 pass 模式从请求中抓取的对象不被缓存,但会传递到客户端。synth 和 restart 返回的动作会调用相关的子进程。
hit-for-pass

        当一个对象不应该被缓存是使用
        hit-for-pass对象取代抓取的对象
        存在 TTL
    一些请求就不应该被缓存,一个典型的例子就是当一个请求页中含有 set-cookie 响应头部时,且 必须并只能把它递送给所需的客户端。因此你可以告诉 varnish 创建个 hit-for-pass的对象并存储这个对象到缓存,而不是存储抓取的这个对象。分布式的请求被采用 pass 模式处理。当一个对象不需要被缓存是,beresp.uncacheable 变量会设置为 true。结果,cacher 进程会保持对 hit-for-pass对象的 hash 散列应用。这种情况下,对请求的查找操作会传递给 hash 来找个 hit-for-pass对象。如此类的请求会被 vclpass 子进程中的 pass 模式给处理。如同其他缓存对象一样,hit-for-pass对象也有一个 TTL(生命周期)。一旦生命周期过了,这个对象就会从缓存上删除。

vcl_backend_fetch

        sub vcl_backend_fetch {return (fetch);
        }
    vcl_backend_fetch 可以从 vcl_miss 或 vcl_pass 中调用。当 vcl_backend_fetch 从 vcl_miss 中调用时,抓取的对象会被缓存。如果 vcl_backend_fetch 被从 vcl_pass 中调用时,抓取的对象也不会被缓存的,即使是 obj.ttl 或 obj.keep 变量的值比 0 大。一个相关的变量是 bereq.uncacheable,这个变量指示出从后端来的对象请求是否被缓存。当然从 pass 请求中来的对象是绝不被缓存的。vcl_backend_fetch 有俩个可能的终端操作,fetch 或 abandon。fetch 动作发送请求给后动,abandon 动作调用 vcl_synth 子进程。内建 vcl_bakend_fetch 子进程只返回 fetch 动作。后端响应被 vcl_backend-response 还是 vcl_backend_error 处理取决于响应来之于那个服务。如果 Varnish 收到语法正确的 HTTP 响应,则 Varnish 将控制权交给 vcl_backend_response。语法正确的 HTTP 响应包括 HTTP 5xx 错误代码。如果 Varnish 没有收到 HTTP 响应,则将控制权交给 vcl_backend_error。

vcl_hash

    定义什么是唯一的请求
    vcl_hash 终是在 vcl_recv 后,或者另个子进程范围 hash 动作关键词。sub vcl_hash {hash_data(req.url);
        if (req.http.host) {hash_data(req.http.host);
        } else {hash_data(server.ip);
        }
        return (lookup);
    }

vcl_hash 定义要用于缓存对象的 hash key。Hash key 将一个缓存对象与另一个缓存对象区分开来。默认的 VCL 为 vcl_hash 添加主机名或 ip 地址,同时添加请求的 url 给 cache hash。
vcl_hash 的一个用法是在 cache hash 上添加用户名来识别用户指定的数据。当然缓存用户数据时应该谨慎进行。一个更好的选择可能是 hash 每个会话缓存对象。
vcl_hash 子进程返回 lookup 操作关键字。不像其他动作关键词,lookup 是一个操作, 而不是子进程。在 vcl_hash 后的下个状态取决于在缓存中 lookup 的查找。
当 lookup 操作没能匹配到任何 hash 时,它会创建一个带有 busy 标志的对象并存储在缓存中。然后,请求会被发送到 vcl_miss 子进程中。一旦请求被处理 busy 标志会被删除,并从后端的响应中更新对象。
随后遇到 busy 标记的对象请求将被发送到等待列表中。这个等待名单旨在提高响应性能,这个在 waiting state 选项中有解释。
注意:一个高速缓存散列可以指代一个或多个对象变量。对象变量是基于 Vary 头域的创建的。在一个缓存散列下保留多个变量是比较好的做法,而不是每个变量创建一个散列。

vcl_hit

    在 lookup 操作之后执行,调用 vcl_hash,找到(hits)在缓存上的对象。sub vcl_hit {if (obj.ttl >= 0s) {// A pure unadultered hit, deliver it
            return (deliver);
        }
        if (obj.ttl + obj.grace > 0s) {// Object is in grace, deliver it
            // Automatically triggers a background fetch
            return (deliver);
        }
        // fetch & deliver once we get the result
        return (fetch);
    }

vcl_hit 子进程通常通过调用含有 deliver,restart 或者 synth 的 return()来进行终止。
如果对象的 TTL+grace time 没有过时的话,返回的 deliver 会控制 vcl_deliver。如果过时时间超过了 TTL,但没有超过 TTL+grace time,deliver 会调用与 vcl_deliver 同步的 background fetch。background fetch 是一种异步调用,用来插入一个新的请求对象到缓存中。grace time 会在 grace 模式选项中有解释。
restart 重启传输,并增加重启计数器设定值。如果重启的次数比 max_restarts 设定的值要大,varnish 会发出一个 guru mediation 的错误。
synth(status code,reason)返回指定状态码给客户端并丢弃请求。

vcl_miss

    如果一个请求对象没有被 lookup 操作找到时子进程会被调用。包含有是否尝试从后端检索文档以及使用那个后端的策略。sub vcl_miss {return (fetch);
    }

子进程 vcl_hit 和 vcl_miss 是相关的。你很少调用他们,因为 HTTP 请求投吧的修改通常是在 vcl_recv 中进行。但是,如果你不希望发送 X -Varnish 头部给后端服务,你可以把它移动动 vcl_miss 或 vcl_pass 中。基于这种情况,你可以使用 unset bereq,http,x-varnish。

vcl_deliver

    所有请求流程的公共最后退出点,除了通过 vcl_pipe 的请求。经常用于添加和移除 debug-headers。sub vcl_deliver {return (deliver);
    }

vcl_deliver 子进程是简单的,同样也是对修改 varnish 的输出很有用的。如果你需要删除一个头部,或添加一个不应该存储在 cache 中的头部,vcl_deliver 可以胜任这个工作。
在 vcl_deliver 中常用的且被可被修改的变量是:

    resp.http.*:发送个客户端的头部,它们可以被 setunsetresp.status:状态码为 200,404,503 等
    resp.reason:被返回给客户端的 http 状态信息
    obj.hit:在对象上的 cache-hits 的数。因此,0 代表miss,可以评估这个变量来轻松地显示响应是来自缓存命中还是未命中。req.restarts:在 VCL 中发出的重启次数 - 如果没有发生,则返回 0。

vcl_synth

    用于在 Varnish 中生成内容
    错误消息可以在这里创建
    其他用例:重定向用户(301/302 重定向)

vcl/default-vcl_synth.vcl:

    sub vcl_synth {
        set resp.http.Content-Type = "text/html; charset=utf-8";
        set resp.http.Retry-After = "5";
        synthetic({"<!DOCTYPE html>
    <html>
      <head>
        <title>"} + resp.status +" "+ resp.reason + {"</title>
      </head>
      <body>
        <h1>Error "} + resp.status +" "+ resp.reason + {"</h1>
        <p>"} + resp.reason + {"</p>
        <h3>Guru Meditation:</h3>
        <p>XID: "} + req.xid + {"</p>
        <hr>
        <p>Varnish cache server</p>
      </body>
    </html>
    "} );
        return (deliver);
    }

你可以创建合成响应,例如,在 vcl_synth 上的个性化错误信息。调用这个子进程你可以做:
return (synth(status_code, “reason”));
注意 synth 不是一个关键字,而是个带有参数的函数。
你必须为 vcl_synth 明确地返回 status code 和 reason 参数。在 resp.http 上设置合成响应的头部。
注意:从 vcl/default-vcl_synth.vcl 注意到 {” and “}可以用于创建多行的字段。这个不仅限于 synthetic()函数,在其他地址也可以使用。vcl_synth 定义的对象绝不在缓存上存储,对立与 vcl_backend_error 定义的对象。
示例:

    使用 vcl_synth 重定向请求
        sub vcl_recv {if (req.http.host == "www.example.com") {set req.http.location = "http://example.com" + req.url;
                return (synth(750, "Permanently moved"));
            }
        }
        sub vcl_synth {if (resp.status == 750) {set resp.http.location = req.http.location;  set resp.status = 301;
                return (deliver);
              
            }
        }

 

 

缓存服务器 Varnish 概念篇 http://www.linuxidc.com/Linux/2014-05/101389.htm

缓存服务器 Varnish 概念篇 http://www.linuxidc.com/Linux/2014-05/101389.htm

CentOS 5.8 下 Varnish-2.1.5 的安装配置 http://www.linuxidc.com/Linux/2013-09/89916.htm

RedHat 脚本改用 CentOS 源更新安装 Nginx、PHP 5.3、Varnish http://www.linuxidc.com/Linux/2012-07/65801.htm

Red Hat Linux 7 下 Varnish 简单搭建 http://www.linuxidc.com/Linux/2016-03/129284.htm

Varnish 缓存实现动静分离  http://www.linuxidc.com/Linux/2016-11/137152.htm

高性能缓存服务器 Varnish 深入浅出部署  http://www.linuxidc.com/Linux/2017-02/140655.htm

Linux 中 Varnish 基础应用  http://www.linuxidc.com/Linux/2016-08/134025.htm

Varnish 的详细介绍:请点这里
Varnish 的下载地址:请点这里

内容参考:
http://book.varnish-software.com/4.0/

本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-11/148557.htm

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-21发表,共计6487字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中