美文网首页
varnish缓存服务

varnish缓存服务

作者: SRE1 | 来源:发表于2019-09-20 11:05 被阅读0次

    缓存系统相关概念

    缓存概念 说明
    时间局部性 一个数据被访问过之后,可能很快会被再次访问到
    空间局部性 一个数据被访问时,其周边的数据也有可能被访问到
    数据缓存 例如MySQL到web应用服务器之间的缓存服务器缓存的资源是数据缓存
    页面缓存 接入层和应用层中间的缓存服务器缓存的是可缓存的页面,这层就是缓存层
    缓存命中率 hit/(hit+miss),一般高于30%命中率则是正向收益,好的设计系统可以达到80%到95%以上
    字节命中率 按照数据的字节大小来计算命中率
    请求命中率 按照请求的数量来计算命中率
    private cache 私有缓存,用户代理附带的本地缓存机制
    public cache 公共缓存,反向代理服务器的缓存功能
    CND Content Delivery Network 内容投递系统
    GSLB 全网均衡调度

    代理式缓存:客户端访问缓存服务器,缓存服务器没有命中缓存时到后端服务器请求数据,此时它作为反向代理服务器工作,这种类型的缓存服务器叫做代理式缓存

    旁挂式缓存:客户端亲自去查询数据库,并且将数据复制给缓存服务器一份,下次先去找缓存服务器,如果没有命中则再去数据库服务器查询,此时这种工作方式的缓存叫做旁挂式缓存,这个客户端叫做胖客户端

    缓存有效性判断机制:

    • 过期时间
    • 条件式验证
      Last-Modified/If-Modified-Since:基于文件的修改时间戳来判别
      Etag/If-None-Match:基于文件的校验码来判别

    http协议缓存常见的首部

    Expires

    Expires是HTTP 1.0所提供的控制字段,是web服务器响应报文的字段,用于告诉客户端浏览器在Expires所指定的过期时间到来前,浏览器可直接从浏览器本地缓存中读取缓存响应请求,无需再次发送请求到服务器。

    Data表示请求报文发送的时间,而Expires则表示缓存在此日期到来前都是有效的。因此客户再次访问这类资源时,浏览器会直接从本地缓存中响应。

    Cache-control

    Cache-Control和Expires的作用差不多,都是用于指明当前资源的缓存有效期。通知客户端浏览器是从本地缓存中直接读取数据还是说重新发送请求到服务器中获取数据。Cache-control提供了多种资源有效期的选择,其优先级高于Expires。

    请求报文用于通知缓存服务如何使用缓存响应请求:

    cache-request-directive =
    "no-cache" 不能使用缓存系统中的缓存响应我,必须先去应用服务器做缓存验证
    "no-store" 不能使用缓存系统中的缓存响应我,必须去应用服务器请求响应我
    "max-age" "=" delta-seconds
    "max-stale" [ "=" delta-seconds ]
    "min-fresh" "=" delta-seconds
    "no-transform"
    "only-if-cached"
    cache-extension

    响应报文用于通知缓存服务器如何存储上级服务器响应的内容:

    cache-response-directive =
    "public" 所有缓存系统都可以缓存
    "private" [ "=" <"> 1#field-name <"> ] 仅能够被私有缓存所缓存
    "no-cache" [ "=" <"> 1#field-name <"> ],可缓存,但响应给客户端之前需要revalidation,即必须发出条件式请求进行缓存有效性验正
    "no-store" ,不允许存储响应内容于缓存中
    "no-transform" 不能转换格式
    "must-revalidate" 必须重新验证
    "proxy-revalidate"
    "max-age" "=" delta-seconds 私有缓存最大缓存时长
    "s-maxage" "=" delta-seconds 公共缓存最大缓存时长
    cache-extension

    Last-Modified/If-Modified-Since

    Last-Modified/If-Modified-Since需要配置Cache-control一起使用。

    Last-Modified:web服务器在响应请求时,会使用此字段来告诉浏览器,其请求的资源的最后修改时间。
    If-Modified-Since:当资源过期时或者请求中带有Cache-Control:max-age=0,并且发现该资源的缓存具有Last-Modified声明,则向web服务器发送请求时带上If-Modified-Since。web服务器收到请求后,将比较If-Modified-Since与被请求资源的最后修改时间。如果最后修改时间比If-Modified-Since的值更新,说明资源已经被改动过,服务器会响应此请求的资源,响应状态码为200;否则,说明资源没更新,则响应HTTP 304,告知浏览器可继续使用本地缓存。

    Etag/If-None-Match

    Etag:web服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器决定)。Apache中,ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的。
    Etag 可以解决 Last-Modified 无法解决的一些问题。

    1、一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;
    2、某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的变化时秒为单位的,这种修改无法判断。因此需要Etag来判断。
    3、某些服务器不能精确的得到文件的最后修改时间;

    如果Last-Modified与ETag一起使用时,服务器会优先验证ETag。而Last-Modified的优先级又高于Expires
    也就是优先级:ETag>Last-Modified>Expires

    If-None-Match:当资源过期时或者请求报文带有Cache-Control:max-age=0时,并且发现该资源的缓存具有Etage声明,则再次向web服务器请求时带上头If-None-Match (Etag的值)。web服务器收到请求后发现有头If-None-Match 则与被请求资源的相应校验串进行比对,决定返回200或304。

    http协议缓存工作原理

    当浏览器第一次发送http请求时,本地通常来说是没有缓存的,因此浏览器需要发送请求到服务器上去获取响应资源。此时浏览器向服务器发送的请求报文中通常会包含Cache-Control来告知服务器本地将对缓存作出何种处理。而服务器收到请求后,会将相关的缓存信息(Etag、Last-Modified等等)连通请求资源一起响应客户端。后续客户端的再次访问的请求报文,将结合缓存资源中的相关缓存字段来做出判断,最后决定使用本地缓存还是服务器再次响应该请求。

    没有缓存的http协议工作流程 客户端再次发送web请求时的工作流程

    Web Page Cache解决方案:squid和varnish

    squid出现比较早,但面临较大负载时工作非常稳定,且功能丰富,同时支持正向、反向代理;
    varnish是比较轻量,主要用来实现反代;但超过承受的负载时,可能很不稳定;

    varnish

    Varnish cache,或称Varnish,是一套高性能的反向网站缓存服务器(reverse proxy server)
    varnish官方站点: http://www.varnish-cache.org/

    varnish的程序架构图

    varnish拥有俩套配置文件;一套配置文件用于varnish自身进程的参数配置,另一套用于定义缓存规则;定义缓存规则需要使用灵活的语言来定义,这就是VCL(varnish语言);应用时需要将VCL编写的规则送给VCC编译后才能运行,所以安装varnish需要依赖gcc编译器。

    varnish的安装:yum install varnish -y,依赖epel源,目前CentOS7的epel源提供的版本是v4.0.5

    varnish的程序环境:

    /etc/varnish/varnish.params: 配置varnish服务进程的工作特性,例如监听的地址和端口,缓存机制
    /etc/varnish/default.vcl:配置各Child/Cache线程的缓存策略
    /usr/sbin/varnishd:主程序
    /usr/bin/varnishadm:命令行工具
    /usr/bin/varnishlog:查看内存中的日志
    /usr/bin/varnishncsa:以NCSA格式查看日志
    /usr/bin/varnishstat:查看缓存日志状态信息
    /usr/bin/varnishtop:以rank方式查看日志
    /usr/bin/varnishtest:测试工具程序
    /usr/sbin/varnish_reload_vcl:VCL配置文件重载程序
    /usr/lib/systemd/system/varnish.service:varnish服务
    /usr/lib/systemd/system/varnishlog.service:日志持久的服务
    /usr/lib/systemd/system/varnishncsa.service:日志持久的服务

    varnish管理工具

    varnishd
    • -s [name=]type[,options] :定义缓存数据的存储方式
      malloc[,size]:内存存储,[,size]用于定义空间大小;重启后所有缓存项失效
      file[,path[,size[,granularity]]]:磁盘文件存储,黑盒;重启后所有缓存项失效
      persistent,path,size:文件存储,黑盒;重启后所有缓存项有效;实验阶段,不建议使用
    • -a address[:port][,address[:port][...]:服务监听端口,默认为6081端口
    • -T address[:port]:管理服务监听端口,默认为6082端口
    • -f config:VCL配置文件
    • -F:运行于前台
    • -p param=value:设定运行参数及其值; 可重复使用多次
    • -r param[,param...]: 设定指定的参数为只读状态
    varnishstat
    [root@varnish ~]# varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss #显示指定参数的当前统计数据
    [root@varnish ~]# varnishstat -l -f MAIN -f MEMPOOL #列出指定配置段的每个参数的意义
    
    varnishtop
    • -1:打印统计信息一次并退出,而不是持续更新的显示
    • -i taglist:可以同时使用多个-i选项,也可以一个选项跟上多个标签
    • -I <[taglist:]regex>:对指定的标签的值基于regex进行过滤
    • -x taglist:排除列表
    • -X <[taglist:]regex>:对指定的标签的值基于regex进行过滤,符合条件的予以排除
    varnishadm
    [root@varnish ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 #登录管理程序
    help [<command>] 获取帮助
    ping [<timestamp>] 测试服务器
    auth <response>
    quit 退出cli
    banner
    status 显示状态
    start 启动
    stop 停止
    vcl.load <configname> <filename> 加载VCL配置文件
    vcl.inline <configname> <quoted_VCLstring>
    vcl.use <configname> 激活VCL配置文件
    vcl.discard <configname> 删除VCL配置
    vcl.list 列出VCL配置
    param.show [-l] [<param>] 列出当前运行的参数
    param.set <param> <value> 运行参数临时调整
    panic.show
    panic.clear
    storage.list 列出数据存储信息
    vcl.show [-v] <configname> 列出VCL详细配置
    backend.list [<backend_expression>] 列出后端服务器
    backend.set_health <backend_expression> <state>
    ban <field> <operator> <arg> [&& <field> <oper> <arg>]...
    ban.list
    

    配置文件

    默认配置文件:

    RELOAD_VCL=1
    VARNISH_VCL_CONF=/etc/varnish/default.vcl  #指定加载VCL配置文件
    VARNISH_LISTEN_ADDRESS=192.168.1.5  #服务监听的地址
    VARNISH_LISTEN_PORT=6081  #默认监听端口
    VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1  #管理服务监听的地址
    VARNISH_ADMIN_LISTEN_PORT=6082 #管理服务监听的端口
    VARNISH_SECRET_FILE=/etc/varnish/secret  #连接秘钥
    VARNISH_STORAGE="malloc,256M"  #用内存提供保存缓存,大小为256M
    VARNISH_USER=varnish  #用户身份
    VARNISH_GROUP=varnish #组身份
    DAEMON_OPTS="-p thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300" #指定进程的运行参数
    

    VCL

    Varnish配置语言(VCL)是一种特定于域的语言,用于描述Varnish Cache的请求处理和文档缓存策略。加载新配置时,由Manager进程创建的VCC进程将VCL代码转换为C.此C代码通常由gcc共享对象编译。然后将共享对象加载到cacher进程中。

    vcl是域配置语言,每一个sub的作用是定义一个域:

    varnish的有限状态机:

    上图适用于前端线程,即客户端请求,其中:
    1.vcl_pass:无论请求是否命中的第二种处理方法,例如命中时不响应,由pass处理转发到后端服务器
    2.vcl_purge:缓存清理的方法之一。
    如果缓存的内容与元数据不符,并响应给用户,同时响应给用户不能缓存的直接获取的元数据,则整个响应内容就会混乱,此时,需要介入外力强行清理缓存。缓存清理的方法有两种:
    (1)purge:请求内容在缓存中命中,则缓存继续生效,如果未命中,则失效,即清理缓存。
    (2)ban机制:可以自定义正则表达式模式,匹配到模式的内容禁止从缓存中响应,要从元数据获取,然后再次进行缓存,覆盖之前的缓存内容,达到清理缓存的效果。
    3.vcl_pipe:不能缓存的请求,直接与后端联系。两种情况:
    (1)正常的http协议请求,但是其中只有get和head可以缓存,其他的method都不能缓存
    (2)非http协议的请求

    上图适用于向服务器发送请求,其中:
    vcl_synth:负责清理缓存,之前的vcl_purge用来监控是否有清理缓存权限
    以上两图中,椭圆形的代表子例程,即域,也叫状态引擎。

    vcl有多个状态引擎,状态之间存在相关性,但状态引擎彼此间互相隔离;每个状态引擎可使用return(x)指明关联至哪个下一级引擎;每个状态引擎对应于vcl文件中的一个配置段,即为subroutine

    俩个特殊的引擎:
    vcl_init:在处理任何请求之前要执行的vcl代码:主要用于初始化VMODs;
    vcl_fini:所有的请求都已经结束,在vcl配置被丢弃时调用;主要用于清理VMODs;

    vainish默认的VCL配置

    默认VCL配置也叫做隐式规则,在配置文件中无法看到,即使我们修改了配置文件,默认配置规则也是在最后做处理。

    varnish> vcl.show -v boot  #在客户端cli工具中查看
    sub vcl_recv {
        if (req.method == "PRI") {  #如果客户端的请求方法是PRI,不支持SPDY或HTTP/2.0
            return (synth(405));  #则构建一个405的包响应给客户端
        }
        if (req.method != "GET" &&  #如果客户端的请求方法不是GET
          req.method != "HEAD" &&  #并且不是HEAD
          req.method != "PUT" &&  #并且不是PUT
          req.method != "POST" &&  #并且不是...
          req.method != "TRACE" &&
          req.method != "OPTIONS" &&
          req.method != "DELETE") {
            return (pipe);  #即,不是标准HTTP请求方法的交给pipe(管道)
        }
        if (req.method != "GET" && req.method != "HEAD") {  #请求方法不是GET和HEAD的
            return (pass);  #交给pass处理,也就是除了GAT和HEAD方法其他的无法缓存
        }
        if (req.http.Authorization || req.http.Cookie) {  #http的请求首部包含Authorization(认证)或Cookie,即个人专有信息
            return (pass);  #交给pass处理,因为这些带有个人信息的数据无法缓存
        }
        return (hash);  #以上的规则都没有做处理的请求交给hash做处理,剩下的是可以查询缓存的请求了
    }
    
    sub vcl_pipe
    sub vcl_pass
    sub vcl_hash
    sub vcl_purge
    sub vcl_hit
    sub vcl_miss
    sub vcl_deliver
    sub vcl_synth
    sub vcl_backend_fetch
    sub vcl_backend_response
    sub vcl_backend_error
    sub vcl_init
    sub vcl_fini
    
    内建函数
    • regsub(str, regex, sub)
    • regsuball(str, regex, sub)
    • ban(boolean expression)
    • hash_data(input)
    • synthetic(str)
    • hash_data():指明哈希计算的数据;减少差异,以提升命中率
    • regsub(str,regex,sub):把str中被regex第一次匹配到字符串替换为sub;主要用于URL Rewrite
    • regsuball(str,regex,sub):把str中被regex每一次匹配到字符串均替换为sub
    • return()
    • ban(expression)
    • ban_url(regex):Bans所有的其URL可以被此处的regex匹配到的缓存对象
    • synth(status,"STRING"):生成响应报文
    Keywords
    • call subroutine
    • return(action)
    • new
    • set
    • unset
    操作符
    • ==, !=, ~, >, >=, <, <=
    • 逻辑操作符:&&, ||, !
    • 变量赋值:=

    示例1:obj.hits是内建变量,用于保存某缓存项的从缓存中命中的次数

    [root@varnish ~]# vim /etc/varnish/varnish.params
    VARNISH_LISTEN_PORT=80
    [root@varnish ~]# vim /etc/varnish/default.vcl
    backend default {
        .host = "192.168.0.9";
        .port = "80";
    }
    sub vcl_deliver {
        if (obj.hits>0) {
            set resp.http.X-Cache = "HIT via" + " " + server.ip;
        } else {
            set resp.http.X-Cache = "MISS from " + server.ip;
        }
    }
    [root@varnish ~]# systemctl restart varnish  #谨慎重启varnish服务,会导致之前的缓存失效
    [root@varnish ~]# for i in {1..5}; do curl -I -s 192.168.0.8 |grep "X-Cache"; done  #在客户端测试,第一次Miss
    X-Cache: MISS from 192.168.0.8
    X-Cache: HIT via 192.168.0.8
    X-Cache: HIT via 192.168.0.8
    X-Cache: HIT via 192.168.0.8
    X-Cache: HIT via 192.168.0.8
    
    内建变量
    内建变量
    req.* request,表示由客户端发来的请求报文相关
    bereq.* 由varnish发往BE主机的httpd请求相关
    beresp.* 由BE主机响应给varnish的响应报文相关
    resp.* 由varnish响应给client相关
    obj.* 存储在缓存空间中的缓存对象的属性;只读
    常用变量
    bereq.request, req.request 请求方法
    bereq.url, req.url 请求的url;
    bereq.proto 请求的协议版本;
    bereq.backend 指明要调用的后端主机;
    req.http.Cookie 客户端的请求报文中Cookie首部的值;
    req.http.User-Agent ~ "chrome" 用户代理
    beresp.status, resp.status 响应的状态码
    reresp.proto, resp.proto 协议版本
    beresp.backend.name BE主机的主机名
    beresp.ttl BE主机响应的内容的余下的可缓存时长
    obj.hits 此对象从缓存中命中的次数
    obj.ttl 对象的ttl值
    server.ip varnish主机的IP
    server.hostname varnish主机的Hostname
    client.ip 发请求至varnish主机的客户端IP

    示例2:强制对某类资源的请求不检查缓存

    [root@varnish ~]# vim /etc/varnish/default.vcl
    sub vcl_recv {
        if (req.url ~ "(?i)^/(login|admin)") {  #"?i"表示忽略大小写,匹配到url中带有login或admin的不查询缓存
            return(pass);
        }
    }
    [root@varnish ~]# varnish_reload_vcl
    [root@varnish ~]# for i in {1..5}; do curl -I -s http://192.168.0.8/login |grep "X-Cache"; done  #客户端测试
    X-Cache: MISS from 192.168.0.8  #全部Miss
    X-Cache: MISS from 192.168.0.8
    X-Cache: MISS from 192.168.0.8
    X-Cache: MISS from 192.168.0.8
    X-Cache: MISS from 192.168.0.8
    # for i in {1..5}; do curl -I -s http://192.168.0.8/admin |grep "X-Cache"; done
    X-Cache: MISS from 192.168.0.8
    X-Cache: MISS from 192.168.0.8
    X-Cache: MISS from 192.168.0.8
    X-Cache: MISS from 192.168.0.8
    X-Cache: MISS from 192.168.0.8
    # for i in {1..5}; do curl -I -s http://192.168.0.8/ |grep "X-Cache"; done  #其他网页正常查询缓存
    X-Cache: MISS from 192.168.0.8
    X-Cache: HIT via 192.168.0.8
    X-Cache: HIT via 192.168.0.8
    X-Cache: HIT via 192.168.0.8
    X-Cache: HIT via 192.168.0.8
    

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

    sub vcl_backend_response {
        if (beresp.http.cache-control !~ "s-maxage") {
            if (bereq.url ~ "(?i)\.(jpg|jpeg|png|gif|css|js)$") {
                unset beresp.http.Set-Cookie;
                set beresp.ttl = 3600s;
            }
        }
    }
    

    示例4:在报文首部添加真正的客户端IP,使得后端server可以记录真正客户端来源

    [root@varnish ~]# vim /etc/varnish/default.vcl
    sub vcl_recv {
        if (req.restarts == 0) {  #匹配没有被重写的URL请求,即第一次请求
            if (req.http.X-Forwarded-For) {  #变量存在并且有值则为真
                set req.http.X-Forwarded-For = req.http.X-Forwarded-For + "," + client.ip;  #将真正的client.ip添加到此变量中,用","隔开
            } else {
                set req.http.X-Forwarded-For = client.ip;  #如果变量不存在或值为空,则直接将client.ip赋值与
            }
        }
    }
    [root@varnish ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
    varnish> vcl.load conf1 /etc/varnish/default.vcl
    varnish> vcl.use conf1
    varnish> vcl.list   
    available       0 boot
    available       0 reload_2018-07-14T09:55:58
    active          0 conf1  #当前正在使用的配置
    [root@web1 ~]# vim /etc/httpd/conf/httpd.conf
    LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    [root@web1 ~]# systemctl restart httpd
    [root@client ~]# for i in {1..5}; do curl -I -s http://192.168.0.8/login |grep "X-Cache"; done #在客户端测试
    [root@web1 ~]# tail /var/log/httpd/access_log 
    192.168.0.8 - - [14/Jul/2018:09:56:49 +0800] "HEAD /login HTTP/1.1" 301 - "-" "curl/7.29.0"
    192.168.0.8 - - [14/Jul/2018:09:56:49 +0800] "HEAD /login HTTP/1.1" 301 - "-" "curl/7.29.0"
    192.168.0.8 - - [14/Jul/2018:09:56:49 +0800] "HEAD /login HTTP/1.1" 301 - "-" "curl/7.29.0"
    192.168.0.8 - - [14/Jul/2018:09:56:49 +0800] "HEAD /login HTTP/1.1" 301 - "-" "curl/7.29.0"
    192.168.0.8 - - [14/Jul/2018:09:56:49 +0800] "HEAD /login HTTP/1.1" 301 - "-" "curl/7.29.0"
    192.168.0.7 - - [14/Jul/2018:10:25:11 +0800] "HEAD /login HTTP/1.1" 301 - "-" "curl/7.29.0"
    192.168.0.7 - - [14/Jul/2018:10:25:11 +0800] "HEAD /login HTTP/1.1" 301 - "-" "curl/7.29.0"
    192.168.0.7 - - [14/Jul/2018:10:25:11 +0800] "HEAD /login HTTP/1.1" 301 - "-" "curl/7.29.0"
    192.168.0.7 - - [14/Jul/2018:10:25:11 +0800] "HEAD /login HTTP/1.1" 301 - "-" "curl/7.29.0"
    192.168.0.7 - - [14/Jul/2018:10:25:11 +0800] "HEAD /login HTTP/1.1" 301 - "-" "curl/7.29.0"  #拿到了真正客户端IP,而不是之前的varnish服务器的IP
    

    示例5:访问控制,拒绝curl客户端的访问

    sub vcl_recv {
        if(req.http.User-Agent ~ "curl") {
            return(synth(403));
        }
    }
    
    缓存对象的修剪:purge

    1、能执行purge操作

    sub vcl_purge {
        return (synth(200,"Purged"));
    }
    

    2、何时执行purge操作

    sub vcl_recv {
        if (req.method == "PURGE") {
            return(purge);
        }
        ...
    }
    

    示例6:清除指定缓存

    [root@varnish ~]# vim /etc/varnish/default.vcl
    acl purgers {
        "127.0.0.0"/8;
        "192.168.0.0"/24;
    }
    sub vcl_recv {
        if (req.method == "PURGE") {
            if (!client.ip ~ purgers) {
                return(synth(405,"Purging not allowed for " + client.ip));
            }
            return(purge);
        }
    }
    varnish> vcl.load conf3 /etc/varnish/default.vcl
    varnish> vcl.use conf3
    [root@client ~]# curl -I http://192.168.0.8/
    X-Cache: HIT via 192.168.0.8
    [root@client ~]# curl -I -X "PURGE"  http://192.168.0.8/
    [root@client ~]# curl -I http://192.168.0.8/
    X-Cache: MISS from 192.168.0.8
    
    缓存对象的修剪:Banning

    1、arnishadm: ban <field> <operator> <arg>

    varnish> ban req.url ~ (?i)^/javascripts
    

    2、在配置文件中定义,使用ban()函数

    sub vcl_recv {
        if (req.method == "BAN") {
            ban("req.http.host == " + req.http.host + " && req.url == " + req.url);  #将规则拼接起来传递给ban函数
            return(synth(200, "Ban added"));
        }
    }
    # curl -I -X "BAN" http://192.168.0.8/javascripts/
    
    多个后端主机实现调度功能
    动静分离示例:
    backend default {
        .host = "172.16.0.9";
        .port = "80";
    }
    backend appsrv {
        .host = "172.16.0.10";
        .port = "80";
    }
    sub vcl_recv {
        if (req.url ~ "(?i)\.php$") {
            set req.backend_hint = appsrv;
        } else {
            set req.backend_hint = default;
        }
    }
    
    轮询调度
    import directors;
    backend srv1 {
        .host = "192.168.0.9";
        .port = "80";
    }
    backend srv2 {
        .host = "192.168.0.10";
        .port = "80";
    }
    sub vcl_init {
        new websrvs = directors.round_robin();  #round_robin()调度算法,不支持加权
        websrvs.add_backend(srv1);
        websrvs.add_backend(srv2);
    }
    sub vcl_recv {
        set req.backend_hint = websrvs.backend();
    }
    
    基于cookie的session sticky
    sub vcl_init {
        new h = directors.hash();
        h.add_backend(one, 1);
        h.add_backend(two, 1);
    }
    sub vcl_recv {
        set req.backend_hint = h.backend(req.http.cookie);
    }
    
    随机调度,支持权重
    sub vcl_init {
        new websrvs = directors.random();
        websrvs.add_backend(srv1, 1);
        websrvs.add_backend(srv2, 2);
    }
    
    后端健康检查

    .probe:定义健康状态检测方法;
    .url:检测时要请求的URL,默认为”/";
    .request:发出的具体请求;
    .request =
    "GET /.healthtest.html HTTP/1.1"
    "Host: www.dongfei.tech"
    "Connection: close"
    .window:基于最近的多少次检查来判断其健康状态;
    .threshold:最近.window中定义的这么次检查中至有.threshhold定义的次数是成功的;
    .interval:检测频度;
    .timeout:超时时长;
    .expected_response:期望的响应码,默认为200;

    import directors;
    probe http_chk {
            .url = "/index.html";
            .interval = 2s;
            .timeout = 2s;
            .window = 10;  #最近10次检查
            .threshold = 7;  #有7次成功则为健康主机
    }
    backend srv1 {
            .host = "192.168.0.9";
            .port = "80";
            .probe = http_chk;
    }
    backend srv2 {
            .host = "192.168.0.10";
            .port = "80";
            .probe = http_chk;
    }
    sub vcl_init {
            new websrvs = directors.random();
            websrvs.add_backend(srv1, 1);
            websrvs.add_backend(srv2, 2);
    }
    sub vcl_recv {
            set req.backend_hint = websrvs.backend();
    }
    
    varnish> backend.list #查看后端主机健康状态信息     
    Backend name                   Refs   Admin      Probe
    srv1(192.168.0.9,,80)          3      probe      Healthy 10/10
    srv2(192.168.0.10,,80)         3      probe      Healthy 10/10
    varnish> backend.set_health srv1 sick|healthy|auto  #手动标记主机状态 down|up|probe
    

    设置后端的主机属性:

    backend BE_NAME {
        ...
        .connect_timeout = 0.5s;  #连接超时时间
        .first_byte_timeout = 20s;  #第一个字节20s不响应则为超时
        .between_bytes_timeout = 5s;  #第一个字节和第二个字节间隔超时时间
        .max_connections = 50;  #最大连接数
    }
    

    varnish的运行时参数

    最大并发连接数 = thread_pools * thread_pool_max

    • thread_pools:工作线程数,最好小于或等于CPU核心数量
    • thread_pool_max:每线程池的最大线程数
    • thread_pool_min:最大空闲线程数
    • thread_pool_timeout:空闲超过多长时间被清除
    • thread_pool_add_delay:生成线程之前等待的时间
    • thread_pool_destroy_delay:清除超出最大空闲线程数的线程之前等待的时间

    日志管理

    virnish的日志默认存储在80M的内存空间中,如果日志记录超出了则覆盖前边的日志,服务器重启后丢失;需要更改配置使其永久保存到磁盘

    [root@varnish ~]# varnishstat -1 -f MAIN  #指定查看MAIN段的信息
    
    [root@varnish ~]# varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss  #显示指定参数的当前统计数据
    MAIN.cache_hit              47         0.00 Cache hits
    MAIN.cache_miss             89         0.01 Cache misses
    
    [root@varnish ~]# varnishtop -1 -i ReqHeader  #显示指定的排序信息
       165.00 ReqHeader Accept: */*
       165.00 ReqHeader Host: 192.168.0.8
       165.00 ReqHeader User-Agent: curl/7.29.0
       165.00 ReqHeader X-Forwarded-For: 192.168.0.7
    

    将日志永久保存到:/var/log/varnish/varnish.log

    [root@varnish ~]# systemctl start varnishlog.service
    

    以Apache/NCSA日志格式显示

    [root@varnish ~]# varnishncsa
    192.168.0.7 - - [14/Jul/2018:12:34:23 +0800] "GET http://192.168.0.8/javascripts/test1.html HTTP/1.1" 200 11 "-" "curl/7.29.0"
    

    参考文档:https://blog.csdn.net/jingsanliunian/article/details/78452602
    https://www.jianshu.com/p/e948549f34ae

    相关文章

      网友评论

          本文标题:varnish缓存服务

          本文链接:https://www.haomeiwen.com/subject/yhauyctx.html