两类缓存服务器:
1.代理式缓存服务器;proxy-like cache server;
2.旁挂式缓存服务器;bypass cache server;

缓存服务器也可以根据缓存数据内容分类:
    1.数据缓存;data cache
    2.页面缓存;page cache

数据存在访问热区,指被经常访问的数据。

缓存的实质是:用空间换时间;
缓存的局部性特征:空间局部性和时间局部性:

缓存的时效性:
过期清理:PURGE,修剪;
未过期但溢出清理:LRU(最少使用原则);
未过期但被修改:PURGE,修剪;

缓存命中率:Hits/(Hits + Miss) ,取值范围区间是(0,1),通常也会用百分数进行表示;
页面命中率:基于命中的页面数量进行统计衡量的一种标准;
字节命中率:基于命中的页面的体积进行统计衡量的一种标准;(更为精确)

数据缓存与否:
1.私有数据:private data,放置于私有缓存中;
http/1.1版本后的首部中,提供了一个Cach-Control的首部;Cache-Control首部的值中包含有private字样,或者提供了Cookie或者Cookie2的首部;此类数据大多数都是由浏览器完成缓存;
2.公共数据:public data,可以放置于公共缓存,也可以放置于私有缓存中;
此类数据大多数缓存在反代服务器上或者专用的Cache Server上;
小部分也可以缓存在浏览器上;

注意:
    浏览器的缓存(一般是私有缓存):
        仅针对于单独的用户生效,使用户重复访问某资源时能够加速访问;
    缓存服务器的缓存(一般是公共缓存):
        为前端调度器或反代服务器加速资源访问,降低后端资源服务器的访问压力;

对于缓存服务器来说,缓存的处理步骤(大致成功的处理步骤):
接收请求 --> 解析请求(从请求报文的http协议首部中提取URL及其他相关的首部信息) --> 查询缓存 --> 缓存数据的新鲜度检测 --> 构建响应报文 --> 发送响应报文--> 记录日志

缓存数据的有效性判断机制:
1.过期时间:
HTTP/1.0:
Expires,绝对时间;
HTTP/1.1:
1.Expires
2.Cache-Control(首部):max-age=86400
3.Cache-Control:s-maxage=10000 (s代表公共缓存)
2.条件式请求:
Last-Modified/If-Modified-Since :响应报文/请求报文的条件请求
Etag/If-None-Match :扩展标签,对标签进行哈希计算;If-None-Match:如果不匹配,返回200代表不匹配

示例:查看百度的logo资源:
Cache-Control max-age=2592000 //缓存资源的最大有效时间
ETag "593645fd-664" //得到的16进制的哈希值
Expires Wed, 11 Jul 2018 03:43:28 GMT //过期时间
Last-Modified Tue, 06 Jun 2017 06:04:45 GMT //自 06 Jun 2017 06:04:45 GMT这个时间点开始资源无变化(GMT:格林尼治时间)

一、memcached缓存服务器:
属于旁挂式缓存服务器,也属于数据缓存;

memcached存储形式:
    1.将所有数据采用键值对儿的形式存储于内存当中;
    2.无持久存储功能;
    3.通常用于缓存小文件,小数据,单项缓存数据内容上限是1MB;

memcached由LiveJournal公司旗下的子公司Danga Interactive研发者Brad Fitzpatrick研发;

memcached特性:
    1.k/v cache;可序列化数据,扁平化数据;         //常见的还有JSON,也是序列化数据
    2.存储项:key(键), value(值), flag(16位二进制数字,0-65535), expire_time(超时时间), length(保存数据的长度)等简单部分组成;
    3.旁挂式缓存,功能实现一半依赖于客户端,另一半靠memcached server;
    4.O(1)的查找和执行效率;
    5.可以构建分布式缓存系统,各服务器之间互不通信的分布式集群系统;
    6.缓存数据的处理方式(较为特殊):
        1)缓存空间耗尽:根据LRU(最近最少使用算法)完成清理过期数据;
        2)缓存项过期:惰性清理机制---用来尽可能减少内存碎片
    7.内存分配方式:
        slab allocation:按照页面进行打散,将打散的页面分成若干个更小的页面,最大1M
            facter:增长因子;默认1.25倍递增;小页面根据增长因子来分配空间大小,最后会留下一个最大不超过1M的空间。

安装配置memcached:
    1.base源中有对应的rpm包;可以直接使用yum方式安装内容;
            ~]# yum install memcached -y
    2.从memcached.org官方站点下载源代码包,编译安装;

    memcached缓存服务监听的端口:
        11211/TCP, 11211/UDP;

    memcached缓存服务程序安装后的默认环境:
        主程序:/usr/bin/memcached
        环境配置文件:/etc/sysconfig/memcached
            ~]# cat /etc/sysconfig/memcached 
            PORT="11211"        //监听的端口号
            USER="memcached"    //程序属于哪个用户
            MAXCONN="1024"      //服务的最大连接数
            CACHESIZE="64"      //缓存大小默认为64
            OPTIONS=""                  //其他选项默认为空

    memcached缓存服务使用的协议是memcached协议,memcached协议支持的数据传输格式是:
        1.文件格式
        2.二进制格式

    交互式操作(~]# telnet+载有memcached服务主机的IP地址+端口号(默认是11211),使用telnet命令进入交互式操作模式):
        命令:
            1.统计类:stats, stats items(缓存项查看), stats slabs(内存空间的查看), stats sizes
            2.管理类:set(修改特定键的值), add(添加一个新的键), replace(替换原有键的值), append(在原有键值后附加一个值), prepend(在原有键值前附加一个值), delete(删除键), incr(给键添加值), decr(给键删除值), flush_all(清空所有键)
            3.查看类:get

        memcached交互式命令的一般格式:
             key_name [flags] [expire_time] [length_bytes] \n

             key_name:键名
             [flags]:标志位,范围是0-65535
             [expire_time]:键最大缓存时间(秒)
             [length_bytes]:字符长度

            例:
                添加一个新键:
                    add testkey 0 300 11
                    hello world
                    STORED
                查看新键:
                    get testkey
                    VALUE testkey 0 11
                    hello world
                    END
                在新键后添加字符并查看:
                    添加:
                        append testkey 0 300 2
                        hi
                        STORED
                    查看:
                        get testkey
                        VALUE testkey 0 13
                        hello worldhi
                        END
                在新键前添加字符并查看:
                    添加:
                        prepend testkey 0 300 3
                        hi 
                        STORED
                    查看:
                        get testkey
                        VALUE testkey 0 14
                        hi hello world
                        END

    memcached命令选项:
        -c num :指名并发连接数量,默认是1024
        -m num :分配多大的内存空间,默认是64M
        -u username :指定哪个用户启动memcached服务进程
        -p port :指定端口号,默认是11211
        -U port :指定UDP协议的端口号,默认是11211,0是关闭
        -l ipaddress :监听哪一个地址,默认是所有
        -f facter :指明增长因子,默认是1.25倍
        -t thread_num :设置线程数,默认是4个线程
        -v,-vv,-vvv :显示的详细信息程度

二、VARNISH缓存服务器:
varnish缓存服务器是属于页面缓存服务器的一种,用来为客户端请求提供查询结果,也属于代理式缓存服务器。

varnish缓存服务器特点:
    varnish缓存服务器可以实现的功能:反向代理 + 缓存服务器
    varnish缓存服务器默认在内存中占用128M内存空间去进行缓存服务

缓存服务器的实现:
开源解决方案:
squid:上世纪90年代中期出现;使用率较低
varnish:反向代理式缓存:使用率较高的缓存服务器实现方案;
https://www.varnish-software.com/ //商业版本服务站点
http://varnish-cache.org/ //开源站点

varnish程序的组织结构:
        1.Management进程:
                     1)varnish的主进程;
                     2)提供命令行工具的访问接口,用来管理子进程,初始化缓存;
        2.Child/Cache进程:拥有多种线程模型,如下:
                    command line
                    storage/hashing
                    log/stats
                    accept
                    worker threads
                    object expiry
                    backend communication
                    ...
        3.VCL compiler:C compiler(gcc)

varnish的线程池作用:
    统计数据:数据统计和计数器;
    日志区域:日志数据;

VCL文件的处理方式:
    vcl compiler (vcl编译器编译完成)--> C compiler (再到C的编译器中编译处理)--> shared object

vcl配置文件的重载工具:
        /usr/sbin/varnish_reload_vcl

VCL:Varnish Configuration Language,varnish配置语言;
统一存放于后缀名为".vcl"的文件中,在初次安装了varnish之后,在配置主目录中会自动创建出一个名为"default.vcl"的文件,但其内容几乎为空;

varnish的安装:
在EPEL源中直接提供了varnish的稳定版本;
安装命令:yum install -y varnish (需先配置EPEL源)

varnish的程序环境:
    1.配置文件:
        /etc/varnish/default.vcl
            定义缓存策略的默认配置文件,主要用于配置各Child/Cache线程的工作属性;
        /etc/varnish/varnish.params
            定义varnish缓存服务的运行时参数以及工作特性;
        /etc/varnish/secret
            在使用varnishadm命令行管理工具时,为了安全起见使用的预共享密钥;

    2.主程序:  /usr/sbin/varnishd

     1)CLI(简单的命令行接口管理工具):
        /usr/bin/varnishadm

     2)Share Memory Log交互工具:
        /usr/bin/varnishhist
        /usr/bin/varnishlog
        /usr/bin/varnishncsa
        /usr/bin/varnishstat
        /usr/bin/varnishtop

                开启varnish日志记录(默认没有开启):
                    1./usr/bin/varnishlog
                    2./usr/bin/varnishncsa(建议在需要开启日志记录的时候开启,因为其更接近于Apache的command的命令形式)

    3)缓存测试工具:
        /usr/bin/varnishtest

    4)varnish的Unit FIle:
        /usr/lib/systemd/system/varnish.service:管理varnish的Management进程;
        实现日志持久化存储的服务文件;
            /usr/lib/systemd/system/varnishlog.service
            /usr/lib/systemd/system/varnishncsa.service

主程序:/usr/sbin/varnishd
    varnishd - HTTP accelerator daemon  --http加速器守护进程
        常用选项:
            -a address[:port][,address[:port][...]
                指定用于接收客户端请求所监听的地址和服务端口,默认值为127.0.0.1:6081
            -b host[:port]:添加一个backend sever的主机和端口号
            -T address[:port]:实现管理的时候需要用到的地址和端口号;
            -f config:
                指明此次需要编译并装载的VCL配置文件,默认为/etc/varnish/default.vcl;
            -p param=value
                设置varnish线程模型的运行时参数和参数值;
                大多数的运行时参数都有默认值,不要轻易尝试调整运行时参数的值;
                在命令行工具中使用此选项调整的运行时参数的值,仅当次生效;
            -r param[,param...]
                将运行时参数设置为只读属性;意味着当再次运行时,其值无法被修改;
            -s [name=]type[,options]:指定缓存的存储机制
                定义缓存数据的存储方式,目前有三种存储机制:
                    1.malloc[,size]:性能最好,但是所有的数据保存在内存中;
                    2.file[,path[,size[,granularity]]]:只是一种黑盒文件,内容无法观察;键值对儿存放于内存当中,哈希值存放于磁盘中,保证快速检索,不会占用内存太多空间
                    3.persistent,path,size (experimental,体验测试版):持久存储(机制不成熟)

            -T address[:port]
                在指定的IP地址和端口号上提供管理接口;默认为127.0.0.1:6082;
            -u user、-g group
                指定允许varnish服务进程的系统用户和系统组,默认均为varnish;

    运行时参数的配置文件:/etc/varnish/varnish.params
        DAEMON_OPTS="-p param1=value1 -p param2=value2 ..."

        thread_pool_min=5
        thread_pool_max=500
        thread_pool_timeout=300

命令行管理工具:varnishadm (交互式模式)
    varnishadm - Control a running Varnish instance
        常用选项:
            -S secret_file
                指定通过命令行工具实现验证时的预共享密钥文件;
            -T address:port
                指定管理地址和端口;

    交互式模式的命令:
        help [] :varnishadm命令帮助
        ping [] :做连通测试
        auth  :做认证
        quit :退出交互式模式
        banner :做条幅
        status :状态输出
        start :启动varnish服务(不建议使用)        //重启、关闭、开启都会把缓存清空,这是致命的
        stop :关闭varnish服务(不建议使用)
        管理vcl:
            vcl.load  :装载并且编译vcl文件
            vcl.inline  :
            vcl.use :激活已经编译好的vcl文件;
            vcl.discard :删除已经编译好的非激活状态下的vcl配置文件;
            vcl.list:vcl配置文件一共有哪些;
        param.show [-l] []:列举所有运行时参数并且输出详细参数;
        param.set  :临时修改某个运行时参数的值,一次性修改,重启后恢复默认
        panic.show:显示运行时参数列表或显示指定的运行时参数的详细信息;
        panic.clear:清空运行时参数列表;
        storage.list:显示缓存存储相关信息;
        vcl.show [-v]  :显示default.vcl所有配置历史更改列表,包括正在使用和使用过的;
        backend.list [] :后端服务器列表显示;
        backend.set_health   :设置后端服务器将康状态码;

常用的命令:
    VCL配置文件管理相关:
        vcl.load:装载并编译VCL配置文件;
        vcl.use:激活已经编译完成的VCL配置文件;
        vcl.discard:删除非激活状态下的VCL配置文件;

    运行时参数相关:
        param.show:显示运行时参数列表或显示指定的运行时参数的详细信息;
        param.set:实时设置或修改运行时参数的值;(不要轻易尝试修改,一定要清楚操作的目的)

    缓存存储相关:
        storage.list:显示缓存存储相关信息;

    后端服务器相关:
        backend.list:显示可以直接访问的后端服务器列表;
        backend.set_health:指明后端服务器的健康状态检测方式;

VCL:Varnish Configuration Language;
    "域"专有类型的配置语言;

    VCL中定义了多个状态引擎,各状态引擎之间存在相关性,同时又彼此隔离;每个状态引擎内都可以使用return()关键字指明各状态引擎之间的关联关系;在VCL文件中,状态引擎使用如下的方式进行定义:
        sub STATE_ENGINE_NAME { ...; }
        sub+状态引擎的名字+{ 配置指令1;配置指令2;... }

三个varnish状态引擎版本对比以及数据处理流程:
1.varnish 2.0-状态引擎包括:
vcl_recv:接收请求,并且判断是否可以使用缓存数据;
vcl_hash:对于从backend端取回的数据,如果可被缓存,则进行哈希计算;
vcl_hit:对于请求的资源可以在缓存对象中直接获取;
vcl_miss:对于请求的资源无法在缓存对象中直接获取;
vcl_deliver:构建响应报文;
vcl_fetch:从backend端取回数据;

        varnish2.0的处理流程:
            1.vcl_recv --> vcl_hash --> vcl_hit --> vcl_deliver
            2.vcl_recv --> vcl_hash --> vcl_miss --> vcl_fetch --> vcl_deliver
            3.vcl_recv --> vcl_fetch --> vcl_deliver (不走缓存)

    2.varnish 3.0状态引擎包括:
        vcl_recv:接收请求,并且判断是否可以使用缓存数据;
        vcl_hash:对于从backend端取回的数据,如果可被缓存,则进行哈希计算;
        vcl_hit:对于请求的资源可以在缓存对象中直接获取;
        vcl_miss:对于请求的资源无法在缓存对象中直接获取;
        vcl_deliver:构建响应报文;
        vcl_fetch:从backend端取回数据;
        较varnish2.0新增:
            vcl_pass:对于本来可以从缓存中查找到资源明确的设置不使用缓存;多数用于私有缓存的查找策略;
            vcl_pipe:对于无法理解的请求,直接按照原样的封装直接代理至backend端;
            vcl_error:本地发生错误时,构建错误响应报文;

        varnish的处理流程:
            1.vcl_recv --> vcl_hash --> vcl_hit --> vcl_deliver
            2.vcl_recv --> vcl_hash --> vcl_hit --> vcl_pass --> vcl_fetch -->vcl_deliver
            3.vcl_recv --> vcl_hash --> vcl_miss --> vcl_fetch --> vcl_deliver
            4.vcl_recv --> vcl_hash --> vcl_miss --> vcl_pass --> vcl_fetch --> vcl_deliver
            5.vcl_recv --> vcl_pass --> vcl_fetch --> vcl_deliver
            6.vcl_recv --> vcl_pipe

    3.varnish 4.0+状态引擎包括:
        vcl_recv:接收请求,并且判断是否可以使用缓存数据;
        vcl_hash:对于从backend端取回的数据,如果可被缓存,则进行哈希计算;
        vcl_hit:对于请求的资源可以在缓存对象中直接获取;
        vcl_miss:对于请求的资源无法在缓存对象中直接获取;
        vcl_deliver:构建响应报文;
        vcl_pass:对于本来可以从缓存中查找到资源明确的设置不使用缓存;多数用于私有缓存的查找策略;
        vcl_pipe:对于无法理解的请求,直接按照原样的封装直接代理至backend端;
        较于varnish3.0新增:
            vcl_backend_fetch:从backend端取回数据;
            vcl_backend_response:处理从backend取回的数据;
            vcl_backend_error:本地发生错误时,构建错误响应报文;
            vcl_synth:主要用于缓存修剪及信息发送;(由varnish3.0中的error变化而来)
            vcl_purge:修剪缓存;

        varnish的处理流程:
            1.vcl_recv --> vcl_hash --> vcl_hit --> vcl_deliver
            2.vcl_recv --> vcl_hash --> vcl_hit --> vcl_pass --> vcl_backend_fetch --> vcl_backend_response --> vcl_deliver
            3.vcl_recv --> vcl_hash --> vcl_pass --> vcl_backend_fetch --> vcl_backend_response --> vcl_deliver
            4.vcl_recv --> vcl_hash --> vcl_miss[ --> vcl_pass ] --> vcl_backend_fetch --> vcl_backend_response --> vcl_deliver
            5.vcl_recv --> vcl_hash --> vcl_purge --> vcl_synth
            6.vcl_recv --> vcl_hash --> vcl_pipe
            7.vcl_recv --> vcl_hash --> waiting
                                                                    ↑                                   ↓
                                                                     ←←←←←

        varnish中还有两个特殊的状态引擎:
            vcl_init:
                在处理任何请求之前要调用此引擎,主要用于初始化VMODs;
            vcl_fini:
                在所有的请求都已经处理结束,在VCL的配置被丢弃时调用此引擎,主要用于清理VMODs;

VCL的语法格式:
    1.与C、C++语言的语法非常相似,可以支持C、C++或perl风格的注释方式:
        //, #, /* ... */
    2.VCL不支持循环和跳转语句;但可以是if条件分支(单分支、双分支及多分支);
        if的单分支格式:
            if (condition) {
                ...;
            }
        if的双分支格式:
            if (condition) {
                ...;
            } else {
                ...;
            }
        if的多分支格式:
            if (condition1) {
                ...;
            } elseif (condition2) {
                ...;
            } else {
                ...;
            }
    3.所有的字符串内容应该放置于""之内,且不能使用换行符;
    4.支持内建和自定义的ACL;
    5.支持丰富的操作符:=(赋值符号), ==(等值比较), >, >=, <, <=, !, &&(与运算), ||(或运算), ~
    6.使用return()关键字来决定下一个处理流程使用哪个引擎,且return()关键字无返回值;
    7.支持内建变量及自定义变量,并且内建变量之间存在依赖关系,只能在特定的引擎中调用特定的内建变量;
        set var_name = value
        unset var_name

VCL中的内建变量:
    req.*:request,表示客户端发送来的请求报文相关的变量;
    bereq.*:backend request,由varnish向backend端主机发送请求的相关变量;
    resp.*:response,由varnish响应给前端设备或客户端的响应报文的相关变量;
    beresp.*:backend response,由backend主机响应给varnish的响应报文的相关变量;
    obj.*:存在在缓存空间中的缓存对象相关的变量,只读;

    常用的内建变量:
        req类:
            req.http.HTTP_HEADER_NAME:
                req.http.Cache-Control
                req.http.User-Agent
                req.http.Host:
                ...
            req.url:客户端发送来的请求报文中的URL相关信息;
                if (req.url ~ (?i)\.php$) {
                    return(pass);
                }
            req.method:客户端发送来的请求报文中的请求资源的方法;
            req.proto:客户端发送来的请求报文中使用的http协议版本;

        bereq类:
            bereq.http.HTTP_HEADER_NAME:
                bereq.http.Cache-Control
                bereq.http.User-Agent
                bereq.http.Host:

            bereq.url:varnish向backend端发送的请求报文中的URL相关信息;
            bereq.method:varnish向backend端发送的请求报文中的请求资源的方法;
            bereq.proto:varnish向backend端发送的请求报文中使用的http协议版本;
            bereq.backend:指明要调度的后端主机;

        resp类:
            resp.http.HTTP_HEADER_NAME:
            resp.status:varnish自身向客户端发送的响应报文中的响应状态码;
            resp.proto:varnish自身向客户端发送的响应报文中的http协议版本号;

        beresp类:
            beresp.http.HTTP_HEADER_NAME:
            beresp.status:backend端主机向varnish发送的响应报文中的响应状态码;
            beresp.proto:backend端主机向varnish发送的响应报文中的http协议版本号;
            beresp.backend.name:backend端主机型varnish发送的响应报文中的主机名;
            beresp.ttl:backend端主机响应的内容剩余的可缓存时长;

        obj类:
            obj.hits:指定的对象从缓存中命中的次数;(实时数值)
            obj.miss:指定的对象从缓存中未命中的次数;(实时数值)
            obj.ttl:指定的对象在缓存中剩余有效缓存时长;

VCL的自定义变量:
    定义变量:
        set VAR_NAME = VALUE;
    取消定义的变量:
        unset VAR_NAME;

为了方便展示下面的配置示例,说一下环境:
1.在安装好的varnish缓存服务器主机上,/etc/varnish/varnish.params中修改监听的后端服务器端口号为80而不是默认的6081,其他默认就可以,方便显示;
2.在/etc/varnish/varnish.params中VARNISH_LISTEN_PORT=80,然后保存退出重启服务(重启命令:systemctl reload varnish.service)
3.iptables -F关闭防火墙;
4.setenforce 0 更改SELinux的状态,防止访问受影响;

示例(1):设置如果缓存命中则显示HIT,未命中显示MISS(做测试专用):
在安装好的varnish缓存服务器主机上,/etc/varnish/default.vcl文件中配置如下内容:
#要显示在客户端,所以我们要在构建响应报文中做配置即vcl_deliver
sub vcl_deliver {
#如果缓存服务器中缓存没有命中,obj.hits大于0即是缓存命中,在向客户端发送的响应报文中显示“HIT”,未命中则显示“MISS”
if (obj.hits>0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
}
并且在/etc/varnish/default.vcl文件中添加一个后台服务器主机172.16.75.2(直接修改默认的backend default段就可以):
#监听的端口号要和/etc/varnish/varnish.params中修改的保持一致
backend websrv1 {
.host = "172.16.75.2";
.port = "80";
}
运行时重载varnish服务,使其生效(也可以使用交互式命令进入交互式模式:varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 ):
~]#varnish_reload_vcl

在后端主机172.16.75.2上配置主页index.html中添加内容:Backend Server 7.5B
测试结果如下:
访问172.16.75.1得到的是172.16.75.2的主页
缓存服务器memcached和varnish
在响应报文中,显示第一次未命中MISS,第一次必定是MISS未命中,因为第一次缓存服务器和浏览器缓存中都没有我们期望的缓存:
缓存服务器memcached和varnish_第1张图片
CTRL+F5不使用浏览器缓存,直接从服务器端取数据,如下,X-Cache显示HIT,下面的Pragma是no-cache,表示未使用浏览器端缓存(CTRL+F5刷新的结果):
缓存服务器memcached和varnish_第2张图片

示例2:人为的设定对某特定资源的请求,无论缓存与否,强制其不检查缓存;
#在客户端请求报文中的URL如果匹配到“/test.html”字样,不在缓存服务器端取值直接向后端服务器取值(pass起到的作用);
#仍然是在请求段配置需求;
#延续上面的配置段;
backend websrv1 {
.host = "172.16.75.2";
.port = "80";
}
#
sub vcl_recv {
if (req.url == "/test.html") {
return(pass);
}
#在客户端请求报文中的URL如果匹配到“/login”或“/admin”字样((?i)代表不区分后边的字符大小写),不在缓存服务器端取值直接向后端服务器取数据
if (req.url ~ "(?i)^/(login|admin)") {
return(pass);
}
}
在172.16.75.2主机上/var/www/html/中创建test.html且创建目录admin/index.html,并添加内容方便测试,测试结果显示使用CTRL+F5刷新,X-Cache显示一直都是MISS,证明客户端直接从后端服务器中取数据,就算缓存服务器中存在数据也直接pass过直接去往后端服务器取数据:
缓存服务器memcached和varnish_第3张图片

访问admin目录主页,结果与预料一致,客户端直接从后端服务器直接获取数据:
缓存服务器memcached和varnish_第4张图片

示例3:对于某些特定类型资源,如:公开的图片,音频或视频流媒体资源,取消此类资源上的私有标识,并强制设定其可以由varnish进行缓存,且可以设定缓存时长;
#因为设定的是缓存服务器上的配置,所以这里是在后端服务器返回数据到缓存服务器段的配置;
sub vcl_backend_response {
#如果从后端服务器上返回的数据包括公共资源(s-maxage)和通用资源(max-age),再判断缓存服务器端向后端服务器请求的数据报文的URL中如果包括流媒体格式的文件,就取消此类资源上的私有标识并设定缓存时长;
if (beresp.http.Cache-Control !~ "(s-maxage|max-age)") {
if (bereq.url ~ "(?i).(jpg|jpeg|png|gif|mp4|mp3|js|css)$") {
unset beresp.http.Set-Cookie;
set beresp.ttl = 86400s;
}
}
}

示例4:缓存对象的修剪:purge,ban
#如果缓存服务器端收到客户端的请求带有指定的PUGER方法,则直接return到puger段,直接return到synth进行缓存修剪并返回一个状态码和一段信息;
sub vcl_recv {
if (req.method == "PURGE") {
return(purge);
}
}
#必须经过purge修剪状态引擎才能跳转到synth;
sub vcl_purge {
return(synth(200,"Cache Purged"));
}

测试方法:
curl -X PURGE http://172.16.75.1/

测试结果,与我们设置的内容一致,状态码200等:![](https://s1.51cto.com/images/blog/201807/12/769cb5660d62f9d22e8969ad0b014c0b.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)

注意:修剪缓存对象的操作对于varnish来说,可能造成非常大的影响;如果修剪不当或者是恶意修剪,可能会直接导致backend端压力剧增,甚至可能会出现故障,无法正常提供服务;

对于此类修剪缓存对象的操作,务必要做好访问控制法则:
更安全的缓存修剪策略示例:

#只允许本机修改
acl allowpurge {
"127.0.0.1";
}

设置修剪缓存的执行前提:
#如果客户端使用PURGE方法请求访问数据并且客户端IP不是缓存服务器本机,那我们只好返回403状态码并且提示对方,如果是我们本机则直接return到purge段进行缓存数据的修剪;
sub vcl_recv {
if (req.method == "PURGE") {
if (client.ip !~ allowpurge) {
return(synth(403,"Purge Forbidden for" + client.ip));
}
return(purge);
}
}

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

测试结果:
首先我们使用非本地主机(172.16.74.1)使用PURGE方法访问数据,如下结果:禁止访问
缓存服务器memcached和varnish_第5张图片
再使用本机(172.16.75.1)127.0.0.1进行访问,结果如下:显示正确的状态码,已经允许本机进行PURGE
缓存服务器memcached和varnish_第6张图片

acl的定义语法:
acl ACL_NAME {
"HOSTNAME";
"IP_ADDRESS";
"NETWORK_ADDRESS"/PREFIX
}

示例5:设定让Varnish可以使用多个后端主机(Backend Server);
#/etc/varnish/default.vcl文件中配置;
backend websrv1 {
.host = "172.16.75.3";
.port = "80";
}

backend appsrv1 {
.host = "172.16.75.4";
.port = "80";
}
#如果客户端请求的URL中包含以".php"结尾的信息,那么就把这个请求发给appsrv1,否则就把这个请求发给websrv1;
sub vcl_recv {
if (req.url ~ "(?i).php$") {
set req.backend_hint = appsrv1;
} else {
set req.backend_hint = websrv1;
}
}

在后端服务器主机172.16.74.1的/var/www/html/中添加一个以“.php”结尾的首页文件,进行测试访问:
]#vim index.php
7.4A PHP info page.

phpinfo();
?>
开始测试,结果如下显示,可以通过URL来实现动静分离:
缓存服务器memcached和varnish_第7张图片

示例6:让vanish充当负载均衡集群的调度器,并对后端主机进行健康状态检测;
import directors;

backend websrv1 {
.host = "172.16.75.3";
.port = "80";
}

backend websrv2 {
.host = "172.16.75.4";
.port = "80";
}

sub vcl_init {
new websrvs = directors.round_robin();
websrvs.add_backend(websrv1);
websrvs.add_backend(websrv2);
}

sub vcl_recv {
if (req.url ~ "(?i).php$") {
set req.backend_hint = appsrv1;
} else {
set req.backend_hint = websrvs.backend();
}

if (req.url ~ "(?i)^/(login|admin)") {
  return(pass);
}

}

后端主机的健康状态检测:
backend websrv1 {
.host = "172.16.75.3";
.port = "80";
.probe = {
#.url = "/healthcheck"; //.url和.requset只能选一个,后者较为精准;
.timeout = 1s;
.interval = 2s;
.window = 5;
.threshold = 3;
.request =
"GET /healthcheck.html HTTP/1.1"
"Host: www.qhdlink.com"
"Connection: close";
.expected_response = 200;
}
}

说明:
.probe:定义开启对于指定的backend server进行健康状态检测;
.url:在执行健康状态检测时需要请求的URL,如果省略,默认为/;
.timeout:健康状态检测时被标识为失败的超时时间;
.interval:检测频率,即:多长时间进行一次健康状态检测;
.window:基于最近的多少次检测结果来判断后端主机的健康状态;
.threshold:阈值,在最近的.window次的检测中,至少应该有.threshold次是成功的,才会标识后端主机的健康状态为"healthy"或"Happy";否则标识后端主机的监控状态为"sick";
.request:对后端主机进行健康状态检测时发送的请求报文的具体内容;
.expected_response:对后端主机进行健康状态检测时,期望后端主机发送的响应报文中所包含的响应状态码,默认是200;

如果想要为多个backend设置统一的健康状态检测方法,可以事先定义健康状态检测方法,然后再在backend中引用此方法即可;

probe httpcheck {
.url = "/hc.html";
.timeout = 1s;
.interval = 2s;
.window = 5;
.threshold = 3;
}

backend websrv1 {
.host = "172.16.75.3";
.port = "80";
.probe = httpcheck;
}

backend websrv2 {
.host = "172.16.75.4";
.port = "80";
.probe = httpcheck;
}

分别在后端服务器172.16.75.2和172.16.74.1的/var/www/html/中设置一个健康状态监测网页hc.html,使用varnishadm交互模式进行测试:
两个后台都正常运行时:
缓存服务器memcached和varnish_第8张图片
关闭172.16.75.2后进行健康监测,结果如下:
[root@chenliang html]# systemctl stop httpd.service
下图显示,172.16.75.2已经sick:
缓存服务器memcached和varnish_第9张图片
上面就是健康测试机制。

varnish的运行时参数:
varnish的线程模型(Threads Model):
cache-worker:用于处理从前端发送来的请求的线程模型;每个请求都有一个该线程进行处理;
cache-main:用于管理和启动cache功能的线程模型;
ban lurker:用于实现基于正则表达式的模式匹配做缓存数据对象的修剪的进程模型;使用此类方式进行修剪时,不准确的正则表达式匹配规则有可能会对缓存对象造成误伤;
acceptor:用来接受新连接建立请求的线程模型;
epoll/kqueue:用于管理线程池,实现并发处理的线程模型;
expire:用于清理过期缓存数据对象内容的线程模型;
backend poll:用于对后端主机进行健康状态检测的线程模型;

运行时参数就是线程模型在运行时的工作参数;

常用的运行时参数:
    thread_pool_add_delay:每次创建新线程之前,所需要的延迟时间;默认为0s;
    thread_pool_destroy_delay:两次终止线程之间的延迟时间;默认为1s;
    thread_pool_fail_delay:在创建新线程失败之后,创建新线程之前的延迟时间,默认为0.2s;
    thread_pool_max:每个线程池中可以激活的线程的最大数量;
    thread_pool_min:每个线程池中可以保有的活跃线程的最小值;也可以理解为:每个线程池中最大的空闲线程数量;
    thread_pool_timeout:对于那些超过thread_pool_min数量的所有的空闲线程的销毁的等待时间;
    thread_pools:定义了可以开启的线程池的最大数量,其值最好不要超过最大CPU核心数;

    在线程池的内部,每个有前端发送来的请求都需要一个worker线程予以处理,varnish的并发处理能力:
        thread_pool * thread_pool_max

    vcl_dir
  Value is: /etc/varnish (default)
  Default is: /etc/varnish

  Directory from which relative VCL filenames (vcl.load and include) are opened.

    vmod_dir
        Value is: /usr/lib64/varnish/vmods (default)
  Default is: /usr/lib64/varnish/vmods

  Directory where VCL modules are to be found.

查看运行时参数:varnishadm命令行工具中查看:
查看所有运行时参数列表:
varnish> param.show -l
查看特定的运行时参数:
varnish> param.show PARAM_NAME

修改或设置运行时参数的值:
只读的运行时参数不能被修改;
实时修改,立即生效:
varnish> param.set PARAM_NAME VALUE

    示例:
    varnish> param.set thread_pool_min 1000

非实时修改,但永久生效:
    /etc/varnish/varnish.params
        在这个文件中,如果在修改的选项中加入-r代表只读即不能在varnishadm中实时修改生效;

varnish的日志区域(内存中直接存储):
shared memory log区域:
计数器;
日志信息;

varnish的日志查看和日志管理工具:
    1.varnishstat
        varnishstat - Varnish Cache statistics

        常用选项:
            -1:不再连续的刷新显示varnish的状态信息,而是一次性的将即时的状态信息直接显示在标准输出;
            -f FIELD:显示指定的字段所代表的状态属性信息,通常与-1选项一同使用;字段描述时可以使用通配符(*,?);

            示例:
                varnishstat -1 -f MAIN.cache_hit
                varnishstat -1 -f MAIN.cache_miss
                varnishstat -1 -f MAIN.c*

    2.varnishtop
        varnishtop - Varnish log entry ranking

        常用选项:
            -1:不再连续的刷新显示varnish的日志信息,而是一次性的将即时的日志信息直接显示在标准输出;
            -i taglist:选择仅显示指定标签所对应的属性信息,可以使用","分隔多个标签,可以使用多个-i选项显示,还可以使用通配符;
                示例:
                    varnishtop -1 -i BereqMethod,ReqMethod
                    varnishtop -1 -i Bereq*
            -I [taglist:]regex:显示指定标签或所有标签的值中可以被"regex"所匹配的所有的日志信息;
            -x taglist:选择不显示指定标签所对应的属性信息,可以使用","分隔多个标签,可以使用多个-i选项排除对应的标签,还可以使用通配符;
            -X [taglist:]regex:排除显示指定标签或所有标签的值中可以被"regex"所匹配的所有的日志信息;

    3.varnishlog
        varnishlog - Display Varnish logs

        注意:默认情况下vanish会将所有的varnish风格的日志信息记录于共享内存域中,如果想要将此类日志信息保存至文件系统中,CentOS系发行版的LInux系统中可以使用varnishlog.service服务实现;
        日志文件:/var/log/varnish/varnish.log

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

        注意:默认情况下vanish会将所有的Apache combined格式的日志信息记录于共享内存域中,如果想要将此类日志信息保存至文件系统中,CentOS系发行版的LInux系统中可以使用varnishncsa.service服务实现;
        日志文件:/var/log/varnish/varnishncsa.log

varnish中的内建函数和关键字:
    Function(函数):
        regsub(str, regex, sub)
            将str中被regex第一次匹配到的部分换成sub;可以用于rewrite;
        regsuball(str, regex, sub)
            将str中所有能够被regex匹配到的部分都缓存sub;
        ban(boolean expression)
            修剪所有被boolean expression匹配的结果为"TRUE"的缓存对象;
        hash_data(input)
            用于指明对哪些数据进行哈希运算,主要用于通过指定特定键的方式提供命中率和查找效率;
        synthetic(str)
            发送一段信息;
            可以实现purge操作;

    Keyword(关键字)
        1.call subroutines:调用
        2.return(action)
        3.new
        4.set
        5.unset