• varnish配置语言(1)



    知识来源为官方文档:
    《Varnish用户指南》
    《Varnish4.0电子书》

    通过对varnish原理的学习,我们知道varnish缓存策略是基于VCL语言实现,处理逻辑是编写在.vcl配置文件中
    涉及的总要知识点有以下几个

    1. vcl语法:运算符、条件语句、子程序、关键字
    2. 内置Subroutines
    3. Request and response VCL objects
    4. action:return(action)
    5. Functions:内建函数
    6. Variables:变量

    1. vcl语法

    varnish 4.0版本开始,vcl拥有自己的默认规则,它不可移除,总是追加在自定义的规则之后。

    • vcl配置文件以 vcl 4.0 开头;
    • C语言注释风格://or#or/* foo */;
    • 子函数使用sub关键字声明, 例如sub vcl_recv { ...};
    • 无循环, state-limited variables(受限于引擎的内建变量);
    • 使用return(action)中断引擎状态,指向下一步处理,action为关键字 ,例如: return(pass);
    • 可动态装载;

    VCL4相比VCL3语法的改变点

    • 要在配置文件中指定版本:即在第一行写上 vcl 4.0;
    • vcl_fetch函数被vcl_backend_response代替,且req.*不再适用vcl_backend_response;
    • 后端源服务器组director成为varnish模块,需import directors后再在vcl_init子例程中定义;
    • vcl_error变更为vcl_backend_error,必须使用beresp.,而不是obj.
    • req.request变更为req.method,obj为只读对象了。
    • 自定义的子例程(即一个sub)不能以vcl_开头,调用使用call sub_name;
    • error()函数被synth()替代;
    • return(lookup)被return(hash)替代;
    • 使用beresp.uncacheable创建hit_for_pss对象;
    • 变量req.backend.healty被std.healthy(req.backend)替代;
    • 变量req.backend被req.backend_hint替代;
    • 关键字remove被unset替代;
    • 关键字"purge"命令,已被去除。在vcl_recv使用return(purge)。
    • vcl_synth采用resp.,而非原来的obj.

    1.1 主体语法

    sub subroutine {
    ...
    }
    
    if CONDITION {
    ...
    } else {
    ...
    }
    
    return()  # Functions
    hash_data() # Functions
    

    1.2 操作符

    = 赋值
    == 等于
    ~ 匹配,可以与正则表达式或ACL一起使用。同时注意匹配的规则如果是字符串,则需要 " " 引起。
    ! 逻辑非
    && 逻辑与
    || 逻辑或
    

    1.3 Subroutines

    子例程
    子例程用于对代码进行分组以提高可读性或可重用性,例:

    sub pipe_if_local {
        if (client.ip ~ localnetwork) {
            return (pipe);
        }
    }
    

    VCL中的子例程不带参数,也不返回值。内置子例程的名称均以vcl_开头。
    要调用子例程,请使用call关键字,后跟子例程的名称:

    sub vcl_recv {
        call pipe_if_local;
    }
    

    Varnish具有许多内置的子例程,这些子例程在每次事务流经Varnish时都会被调用。这些内置的子例程都名为vcl_*。您自己的子例程不能以vcl_开头其名称。

    Return
    当执行return(action)语句时,正在进行的vcl_ *子例程执行结束。
    该操作指定执行的方式。上下文定义了可用的动作。

    1.4 关键字

    call subroutine, return(action),new,set,unset
    

    2. 内置的Subroutines

    内置函数4.0

    Varnish 处理 client 的请求和后端服务器的响应时,会调用多个内置的 subroutines 进行处理。通过 CLI 执行 vcl.load 和 vcl.discard 时,也会调用内置的 subroutines。

    下面对前端(client-side)和后端(backend-side)的处理分别进行介绍:

    2.1 client-side

    vcl_recv

    在请求开始时调用,在接收并解析完整的请求之后调用,在重新启动之后调用,或者作为ESI include的结果调用。
    它的目的是决定是否为请求服务,可能会修改它,并决定如何进一步处理它。可以将后端提示设置为后端处理端默认设置。

    vcl_recv 子例程可使用 return() 结合下面的其中一个关键字进行终止:

    hash
        请求的对象被认为是一个可能被缓存的对象,将继续对其进行处理。将控制权转交给 vcl_hash 子例程。
    
    pass
        转换至 pass 模式。控制权最终交给 vcl_pass 子例程。
    
    pipe
        转换至 pipe 模式。控制权最终交给 vcl_pipe 子例程。
    
    synth(status code, reason)
        转移到 vcl_synth 子例程,synth() 的参数值被预置为 resp.status 和 resp.reason
    
    purge
        清除请求的对象,以及它的变量(variants)。控制权先交给 vcl_hash,最终交给 vcl_purge
    

    vcl_pipe

    进入 pipe 模式时,vcl_pipe 子例程将被调用。在这个模式中,请求将被传递给后端服务器,这时 Varnish 会降级成为一个 TCP 代理,只充当一个数据流的通道,不会对数据进行任何修改,当 client 或 server 端决定关闭连接时,该模式结束。在调用 vcl_pipe 之后,对于一个处于 pipe 模式的连接,其他任何的 VCL 子例程都不会被调用。

    vcl_pipe 子例程可使用 return() 结合下面的其中一个关键字进行终止:

    pipe
        继续以 pipe mode 运行
    
    synth(status code, reason)
        转移到 vcl_synth 子例程,synth() 的参数值被预置为 resp.status 和 resp.reason
    

    vcl_pass

    在进入 pass 模式时,vcl_pass 将被调用,请求被转发给后端服务器,后端服务器的响应被转发给 client,但是响应不会被缓存。来自该 client 连接的后续请求,将被正常处理。

    vcl_pass 子例程可使用 return() 结合下面的其中一个关键字进行终止:

    fetch
        继续以 pass mode 运行 - 发起一个对后端服务器的请求
    
    restart
        重启该 transaction。增加 restart 计数器的计数。如果计数超过了 max_restarts,Varnish 发出一个错误:guru meditation error.
    
    synth(status code, reason)
        转移到 vcl_synth 子例程,synth() 的参数值被预置为 resp.status 和 resp.reason
    

    vcl_hit

    当缓存查找成功,vcl_hit 将被调用。缓存对象可能会过期,其 ttl 可能为 0 或者负数,with only grace or keep time left.

    vcl_hit 子例程可使用 return() 结合下面的其中一个关键字进行终止:

    deliver
        发送该对象。如果该对象过期,将触发一个 fetch 调用,更新该对象。
    
    fetch
        尽管缓存命中,但是会同步地从后端服务器更新缓存对象。控制权最终转交给 vcl_miss。
    
    pass
        转换至 pass 模式。控制权最终交给 vcl_pass 子例程。
    
    restart
        重启该 transaction。增加 restart 计数器的计数。如果计数超过了 max_restarts,Varnish 发出一个错误:guru meditation error.
    
    synth(status code, reason)
        转移到 vcl_synth 子例程,synth() 的参数值被预置为 resp.status 和 resp.reason    
    

    vcl_miss

    当缓存查找失败,或者当 vcl_hit 返回一个 fetch 时,调用 vcl_miss。
    vcl_miss 用于决定是否尝试从后端服务器获取文件。

    vcl_miss 子例程可使用 return() 结合下面的其中一个关键字进行终止:

    fetch
        从后端服务器获取请求的对象。控制权最终转交给 vcl_backend_fetch。
    
    pass
        转换至 pass 模式。控制权最终交给 vcl_pass 子例程。
    
    restart
        重启该 transaction。增加 restart 计数器的计数。如果计数超过了 max_restarts,Varnish 发出一个错误:guru meditation error.
    
    synth(status code, reason)
        转移到 vcl_synth 子例程,synth() 的参数值被预置为 resp.status 和 resp.reason
    

    vcl_hash

    当 vcl_recv 为请求创建了一个 hash 值时被调用。使用该值作为 key 进行缓存查找。

    vcl_hash 子例程只能以 return(lookup) 终止:

    lookup
        在缓存中查找请求的对象。如果从 vcl_recv 返回 return(purge),控制权转交给 vcl_purge。
        否则,如果缓存查找的结果是 hit,控制权转交给 vcl_hit;如果缓存查找的结果是 miss,控制权转交给 vcl_miss;
        如果缓存查找的结果是 hit on a hit-for-pass 对象 (object with obj.uncacheable == true),控制权转交给 vcl_pass。
    

    vcl_purge

    执行 purge 之后,vcl_purge 被调用,缓存对象被清除(失效),其所有变量(variants)将被回避。

    vcl_purge 子例程可使用 return() 结合下面的其中一个关键字进行终止:

    restart
        重启该 transaction。增加 restart 计数器的计数。如果计数超过了 max_restarts,Varnish 发出一个错误:guru meditation error.
    
    synth(status code, reason)
        转移到 vcl_synth 子例程,synth() 的参数值被预置为 resp.status 和 resp.reason    
    

    vcl_deliver

    发送对象给客户端前调用,除了将一个 vcl_synth 结果发送给客户端时不会调用。

    vcl_deliver 子例程可使用 return() 结合下面的其中一个关键字进行终止:

    deliver
        发送对象给 client
    
    restart
        重启该 transaction。增加 restart 计数器的计数。如果计数超过了 max_restarts,Varnish 发出一个错误:guru meditation error.
    
    synth(status code, reason)
        转移到 vcl_synth 子例程,synth() 的参数值被预置为 resp.status 和 resp.reason
    

    vcl_synth

    调用 vcl_synth 可以发送一个 synthetic 对象给客户端。synthetic 对象由 VCL 生成,不是从后端获取的。可使用 synthetic() 函数构造 synthetic 对象。

    vcl_synth 定义了一个对象,该对象不会被缓存,与其相反,vcl_backend_error 所定义的对象可能最终被缓存。

    vcl_synth 子例程可使用 return() 结合下面的其中一个关键字进行终止:

    deliver
        直接将 vcl_synth 定义的对象发送给客户端,不调用 vcl_deliver
    
    restart
        重启该 transaction。增加 restart 计数器的计数。如果计数超过了 max_restarts,
        Varnish 发出一个错误:guru meditation error.
    

    2.2 backend-side

    vcl_backend_fetch(more)

    对后端服务器发送请求时调用 vcl_backend_fetch。在这个子例程中,我们一般会修改请求,然后才发送给后端服务器。

    vcl_backend_fetch 子例程可使用 return() 结合下面的其中一个关键字进行终止:

    fetch
        从后端服务器获取对象
    
    abandon
        放弃对后端发起请求。除非后端请求是一个 background fetch,否则控制权将被转交给 client-side 的 vcl_synth,
        其 resp.status 被设置为 503。
    

    vcl_backend_response

    当成功从后端服务器获取到 response headers 时,调用 vcl_backend_response。

    vcl_backend_response 子例程可使用 return() 结合下面的其中一个关键字进行终止:

    deliver
        对于一个 304 响应,创建一个更新的缓存对象。否则,从后端获取对象的 body,然后发起 delevery 返回给客户端。
        很可能是并行的(streaming)
    
    abandon
        放弃对后端发起请求。除非后端请求是一个 background fetch,否则控制权将被转交给 client-side 的 vcl_synth,
        其 resp.status 被设置为 503。
            
    retry
        重试发起 backend transaction。增加重试计数,如果重试次数超过 max_retries,控制权转交给 vcl_backend_error
    

    vcl_backend_error

    当尝试从后端获取对象失败,或则重试次数超过 max_retries 时,vcl_backend_error 将被调用。

    VCL 生成一个 synthetic 对象,可使用 synthetic() 函数构造 synthetic 对象的 body。

    vcl_backend_error 子例程可使用 return() 结合下面的其中一个关键字进行终止:

    deliver
        发送 vcl_backend_error 定义的对象,可能的话,缓存该对象。就如同该对象是从后端获取的一般。这也被称为 "backend synth"。
    
    retry
        重试发起 backend transaction。增加重试计数,如果重试次数超过 max_retries,调用 client-side 的 vcl_synth,
        其 resp.status 被设置为 503。
    

    2.3 vcl.load / vcl.discard

    vcl_init

    当加载 VCL 之后,vcl_init 被调用。一般用于初始化 VMODs。

    vcl_init 子例程可使用 return() 结合下面的其中一个关键字进行终止:

    ok
        正常返回,VCL 继续加载
    
    fail
        停止加载这个 VCL  
    

    vcl_fini

    当一个 VCL 被废弃,当该 VCL 处理完所有请求,调用 vcl_fini。一般用于清除 VMODs。

    vcl_fini 子例程可使用 return() 结合下面的其中一个关键字进行终止:

    ok
        正常返回,VCL 将被废弃。
    

    3. Request and response VCL objects

    VCL中有些需要你注意的重要对象。这些对象可以在VCL被使用和操作

    ---req
    请求对象。当vanish接收到请求后,req对象被创建和生成。你可以在vcl_recv中使用req对象做很多事。
    
    ---bereq
    The backend request object. Varnish contructs this before sending it to the backend. It is based on the req object.
    后端请求对象。varnish在发送请求到后端之前构建这个对象。它基于req对象。
    
    ---beresp
    后端响应对象。它包含在从后端响应对象的头里。如果你想修改后端server返回的响应信息,你可以在vcl_backend_response中修改beresp对象。
    
    ---resp
    传递给客户端响应之前的response对象。通常在vcl_deliver中修改。
    
    ---obj
    The object as it is stored in cache. Read only.
    存储在缓存中的对象。 只读。
    

    4. action:return(action)

    actions 是在终止一个内置子例程时,配合 return() 使用的,如 return(pass),最常用的 actions 是这些:

    ---pass
    当你在子程序中return(pass)请求和随后的响应将被传递到后端server和从后端server回传回来。响应将不会被缓存。pass可以从vcl_recv中返回。
    
    ---hash
    在*vcl_recv*中return(hash),通知varnish从cache查找请求内容,除非这个请求不被标示,那么请求应当被pass。
    
    ---pipe .. XXX:What is pipe? benc
    如果从 vcl_recv 返回 pipe,将会进入 pipe 模式,Varnish 将前端与客户端的连接,以及与后端服务器的连接合并成一个数据流的通道,Varnish 不对数据做任何修改,只是将数据在两端发送,所以你的日志是不完整的。
    pipe也可以在*vcl_recv*中返回,return(pipe)。
    
    ---deliver
    传递对象给客户端。通常在vcl_backend_response中return。
    
    ---restart
    Restart processing of the request. You can restart the processing of the whole transaction. Changes to the req object are retained.
    重新对请求进行处理。你可以在整个请求处理的阶段重启。更改过的req对象将被保留。
    
    ---retry
    Retry the request against the backend. This can be returned from vcl_backend_response or vcl_backend_error if you don't like the response that the backend delivered .
    重启指向后端的请求。如果你不想从后端获得响应,你可以在vcl_backend_response 或者vcl_backend_error 中return。
    

    5. 内建函数

    hash_data():指明哈希计算的数据;减少差异,以提升命中率;
    regsub(str,regex,sub):把str中被regex第一次匹配到字符串替换为sub;主要用于URL Rewrite
    regsuball(str,regex,sub):把str中被regex每一次匹配到字符串均替换为sub;
    return():当某VCL域运行结束时将控制权返回给Varnish,并指示Varnish如何进行后续的动作;其可以返回的指令包括:lookup、hash、hit、miss、pass、pipe、hit_for_pass、purge等;但某特定域可能仅能返回某些特定的指令,而非前面列出的全部指令;
    return(restart):重新运行整个VCL,即重新从vcl_recv开始进行处理;每一次重启都会增加req.restarts变量中的值,而max_restarts参数则用于限定最大重启次数。
    ban(expression):清除能被表达式匹配的所有缓存对象
    ban_url(regex):Bans所有的其URL可以被此处的regex匹配到的缓存对象;
    synth(status,"STRING"):purge操作;
    

    6. 变量

    内建变量

    req.*:request,表示由客户端发来的请求报文相关;
        req.http.* *可以是http请求报文的任意首部的名称,代表引用http的某个请求首部
            req.http.User-Agent, req.http.Referer, ...
            req.http.host
        req.method 表示客户端的请求方法
        req.url 表示客户端请求的url
    
    bereq.*:varnish主机在向后端真实服务器发送http请求报文时的相关变量。
        如:可以将真实的客户端地址传递给后端真实web服务器,以便于后端真实服务器记录客户端的真实IP,而不是varnish的IP
        bereq.http.* 代表varnish发往后端的真实的web服务器的相关的请求报文中的首部
    
    beresp.*:由后端真实服务器发来的http响应报文中的某些首部信息相关的变量,一般是在vcl_backend_response或vcl_backend_fenth引擎中调用
        beresp.http.*
    resp.*:由varnish响应给客户端的响应报文相关的变量;
        一般用在vcl_deliver引擎中进行调用,因为deliver引擎是用于给客户端构建响应报文,发送响应报文  
        resp.http.: 可以是响应报文中的任意首部的名称,代表引用某个响应报文的值,可用于设定、添加、修改响应给客户端的响应报文中的响应首部的值
    
    obj.*:对存储在缓存空间中的缓存对象属性的引用变量;只读;
        obj.hits: 某个缓存对象的缓存的命中次数
    
    client.,server.,storage.*:可用在所有面向客户端一侧的引擎中,也就是vcl_recv、vcl_pipe、vcl_hash、vcl_pass、vcl_purge、vcl_miss、vcl_hit、vcl_deliver、vcl_synth中:
        client.ip 代表客户端的IP地址
        server.ip 代表当前varnish的IP地址
        client.port 代表客户端的端口
        server.port 代表当前varnish的端口
    
    用户自定义变量
        可用set,来设定某个用户自定义变量或现有变量的值
        可用unset,来取消某个用户自定义变量,或删除现有变量
    

    常用内建变量说明

    • bereq.*
      bereq.http.HEADERS: 表示varnish发往后端真实web服务器的请求报文中的某个首部
      bereq.request: 表示varnish发往后端真实web服务器的请求报文的请求方法(4.0版本的varnish改为了bereq.method)
      bereq.url:表示varnish发往后端真实web服务器的请求报文的请求的url
      bereq.proto:表示varnish发往后端真实web服务器的请求报文的http协议的协议版本
      bereq.backend:表示要varnish发送请求到后端真实web服务器时,后端服务器不止一台时,所调用的后端主机

    • beresp.*
      beresp.http.HEADERS:表示后端真实web服务器发给varnish的http响应报文的某个首部的信息
      beresp.proto:表示后端真实web服务器发给varnish的http响应报文的http协议版本
      beresp.status:表示后端真实web服务器发给varnish的http响应报文的响应状态码
      beresp.backend.name:表示后端真实web服务器发给varnish的http响应报文的后端主机的名称
      beresp.ttl:后端服务器响应中的内容的余下的生存时长

    • obj.*
      obj.hit 此对象在缓存中命中的次数
      obj.ttl 此对象的ttl值,也就是其缓存时长

    • server.*
      server.ip 当前varnish的IP
      server.hostname 当前varnish的主机名

    • req.*
      req.http.HEADERS: 表示客户端发送给varnish的请求报文中的某个首部
      req.request: 表示客户端发送给varnish的请求报文的请求方法(4.0版本的varnish改为了req.method)
      req.url:表示客户端发送给varnish的请求报文的请求的url
      req.proto:表示客户端发送给varnish的请求报文的http协议的协议版本

    • resp.*
      resp.http.HEADERS:表示varnish发送给客户端的响应报文的某个首部的信息
      resp.proto:表示varnish发送给客户端的http响应报文的http协议版本
      resp.status:表示varnish发送给客户端的http响应报文的响应状态码

    • 自定义变量:可用set 变量名= 值 来设定变量。例:
      set resp.http.X-Cache = "HIT"
      表示设定响应给客户端的响应报文中设定X-Cache首部的值为HIT
      set resp.http.IS-Cache = "YES"+" "server.ip
      表示设定响应给客户端的响应报文中的IS-Cache首部的值为"YES
      varnish服务器IP",多个元素之间要用+加号连接,如果要输出空格,需要用""引号引起来

    • 取消某变量:用unset 变量名。例:
      unset req.http.cookie
      表示取消客户端请求报文中http的cookie首部信息
      unset beresp.http.Set-cookie
      表示取消后端服务器发送到varnish上的响应报文http首部中的Set-cookie首部

    同时注意变量是受状态限制的,下图为可用表:


     
    [sleepy↓]

     

  • 相关阅读:
    通达OA二次开发 工作流表单中关联查询另外一个工作流方法(源代码)
    SpringMVC+ajaxFileUpload上传图片 IE浏览器弹下载框问题解决方式
    Javascript正则中的exec和match
    Java中byte转int的方法
    推断php操作mysql(添删改查)是否成功
    关于人工智能的一些思考~
    Tomcat的虚拟主机的配置
    最近遇到的若干技术问题
    2015年工作中遇到的问题:11-20
    2015年工作中遇到的问题:11-20
  • 原文地址:https://www.cnblogs.com/sunhongleibibi/p/11720212.html
Copyright © 2020-2023  润新知