Linux Varnish

Linux Varnish
    Web Cache:通常的大型网站架构都会使用缓存,缓存通常位于前段代理与后端服务器之间,当用户发出请求之后,会首先经过代理查找缓存,若是缓存中有相关的数据就直接反回给客户端,若是没有就继续向后端真实提供数据的原始服务器请求相关数据,而后再返回给客户端;你可能会有疑问,这样引入缓存难道不会增长网络延迟吗?固然会,可是引入缓存的效益是能够彻底抵消引入缓存带来的延迟的,由于若是不使用缓存,客户端的全部请求都会被发送到后端原始服务器,这样一来对后端原始服务器的压力就会急剧上升,尤为是访问量巨大的大型网站,更是扛不住的,还有一种缘由就是缓存能够直接缓存某些用户请求的动态内容的结果,无需服务器再执行一遍,这样也会节省不少时间,因此这种状况下引入缓存是利大于弊的;
    缓存之因此存在的缘由:
        之因此有缓存这一说法,是由于程序(指令和数据)具备局部性;其局部性包括时间局部性和空间局部性;
            时间局部性:对于同一程序,刚刚被访问到的数据,在接下来有很大可能还会再次被访问到;
            空间局部性:一个数据被访问到,与之较近的数据也可能被访问到;因此才有热区数据这一说法;
        正是由于程序的此种特性,因此缓存才有存在的意义;
    缓存的存储形式:
        缓存在内存中通常是以key-value的形式存在的,其中key通常为访问路径,其能够是URL或者IP地址等,而且key通常都会被hash处理之后再进行存储,由于被hash之后的数据查找起来方便、速度快(O(1));value通常为访问路径所对应的资源;
    缓存命中率:
        若是在缓存中有用户须要的数据咱们称为缓存命中;
        命中率:hit/(hit+miss)
    LRU:当缓存空间被耗尽时,若是有新的缓存进来,缓存服务器就会根据LRU(最近最少使用)算法将一些缓存清理掉,用来存储新的缓存数据;而且缓存也是有生命周期的(好比缓存过时),会按期进行清理;
    缓存数据类型:可缓存的和不可缓存的;
        可缓存的:好比网站的图标,各类图片、文本等
        不可缓存的:带有用户私有信息的,好比cookie信息等;
    缓存处理的步骤:
        接收请求→解析请求(提取请求中的URL及各类HTTP首部)→查询缓存→新鲜度检测(缓存是否过时)→建立响应报文→返回响应→记录日志
    新鲜度检测机制:
        过时日期:
            HTTP/1.0经过http response中的expires首部指定资源过时时间(绝对时间|相对时间);
            HTTP/1.1经过http response中的Cache-Control:max-age来指定资源过时时间;
        有效性再验证(revalidate):
            在返回缓存前先到服务器验证一下,询问服务器本身的某个缓存资源是否过时,可否继续使用,服务器会进行检测:
                1.若是服务器中的原始内容没有改变,则仅返回响应首部(不附带body部分),响应码为304(not modified)
                2.若是服务器中的原始内容发生改变,则正常响应,响应码为200;
                3.若是响应内容不存在了,则响应404;此时缓存中的对象(object)也应该删除;
        条件式请求首部:
            If-Modified-Since:基于时间戳验证,自从某个时间点以后资源是否发生改变;
            If-Unmodified-Since:基于时间戳验证,自动某个时间点以后资源是否没有发生改变;
                一般使用在变化周期慢的资源中;
            If-Match:基于Etag验证资源是否匹配;
            If-None-Match:基于Etag验证资源是否不匹配;
                一般使用在变化周期快的资源中;
 
    Varnish (v4):相对于squid来讲比较轻量级;
        Varnish是一个缓存HTTP数据的反向代理。它接收来自客户端的请求并尝试从缓存中回答它们。若是Varnish没法使用缓存应答来自客户端的请求,它会将请求转发给后端,获取后端服务器的响应,而后将响应数据存储在缓存中再将其响应给客户端。
        当咱们使用缓存时通常在前端的负载均衡调度器上建议使用基于URI的负载均衡调度算法,使对同一资源的请求始终发往同一缓存服务器;
    Varnish Arch:
 
 css


        Varnish程序运行起来之后会启动一个管理(Management)进程和一个或多个子进程(Child)组成,其中一个子进程能够生成多个线程,而后经过线程对请求完成响应等操做;其中管理进程负责编译配置文件并从配置文件中读取配置参数、管理并监控子进程、完成varnish的初始化、提供CLI管理接口等;子进程负责加载管理进程编译好的配置文件中的参数,而后提供相应的缓存服务;子进程还负责接收命令行参数、存储缓存、hash数据、记录日志、统计数据、清理过时缓存、接收链接请求、处理用户请求、与后端服务器交互等;
            Note:Varnish的配置文件是使用VCL编写的,当Varnish程序读取配置文件是并非像ningx这种软件同样,直接读取配置文件中的参数来设置各类功能的,而是首先将编写好的配置文件经过VCL编译器调用C编译器编译成二进制代码,而后才能被Varnish加载使用的;
        Varnish的日志功能:
            Varnish日志使用的是Shared Memory Log(共享内存日志),其默认大小通常为90MB;而且分为两部分:一部分为计数器,另外一部分为请求相关的日志数据;
        VCL:Varnish Configuration Language
            Varnish的配置文件就是使用这种语言编写的,其为基于域的简单编程语言;
        Varnish的缓存都是存放在内存中的,因此对内存的操做效率就极为关注,一般状况先通常的软件都是使用malloc()和free()函数来分配和释放内存,可是varnish使用的并非这个,而是另一种更高效的组件jemalloc来管理内存,能够实现并发malloc;
        Varnish存储缓存的方式:能够经过varnishd 的”-s”选项来进程设置;
            file:将全部缓存放在单个文件中,varnish进程内部会对这些存储在一块儿的各个缓存做区分,存储在磁盘中,因此磁盘IO性能可能成为瓶颈,可是重启会失效;
            malloc:基于内存做缓存,性能高,大小有限,重启失效;
            persistent:基于文件的持久存储;(暂时是实验开发中的功能);
        配置Varnish的三种方法:
            1.varnishd应用程序的命令行参数参数;
                用于设置监听的套接字、使用的存储类型等;
                经过”-p”选项指明各类参数;可在运行时实时配置;
                Note:能够经过查看/usr/lib/systemd/system/varnish.service的内容,进行了解;
            2.VCL:配置缓存系统的缓存机制;
                经过vcl配置文件进行配置,先编译后应用,依赖于C编译器;
    Varnish配置:
        配置文件:
            /etc/varnish/default.vcl
                varnish使用的vcl编写的配置文件,设置缓存机制;
            /etc/varnish/varnish.params
                varnish启动时使用的参数,其中定义的变量会被/usr/lib/systemd/system/varnish.service调用;也能够在命令行中使用varnishd命令手动指定启动时加载的参数及文件;
        监听端口:
            服务端口默认监听在6081号端口上;
            管理端口默认监听在6082号端口上;
        实例:
            三台主机,一台centos7(ip:192.168.80.139)运行varnish v4,两台centos6(clone1,ip:192.168.80.13一、clone2)做为后端服务器运行httpd;
            Centos7:
                vim /etc/varnish/default.vcl
                    backend default {
                        .host = "192.168.80.131";   指定后端服务器地址,也可使用主机名;
                        .port = "80";    指定后端服务器WEB服务监听的接口;
                    }
            Centos6:clone1
                service httpd start
                for i in {1..10} ; do echo "<h1>page $i on clone1</h1>" > /var/www/html/test$i.html ; done
            Centos6:clone2
                service httpd start
                for i in {1..10} ; do echo "<h1>page $i on clone2</h1>" > /var/www/html/test$i.html ; done
            Centos7:
                systemctl start varnish.service
            浏览器键入:http://192.168.80.139:6081/test1.html
        管理工具介绍:varnishadm
            -S:指定秘钥文件
            -T:指定被管理主机的链接的地址和端口
            例子: varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 →便可进入管理接口;
                使用help获取帮助信息;
                varnish> help
                    help [<command>]   获取帮助
                    ping [<timestamp>]   ping测试
                    auth <response>
                    quit         退出CLIL界面
                    banner
                    status       列出子进程的状态信息
                    start        启动子进程
                    stop        中止子进程
                    vcl.load <configname> <filename>     加载.vcl配置文件
                        configname:自定义配置文件名
                        filename:未编译的.vcl文件
                        例子:varnish> vcl.load test1 default.vcl
                    vcl.inline <configname> <quoted_VCLstring>
                    vcl.use <configname>    指定欲使用.vcl配置文件
                    vcl.discard <configname>   删除编译后的指定配置文件
                    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
        日志工具:
            varnishlog
            varnishncsa
        其余工具:
            varnishtop:日志条目排序
            varnishstat:缓存统计信息
    Varnish的VCL配置文件:
        当请求进入Varnish代理中时,Varnish服务会对其进行各类各样的检查,好比是否容许其访问、其访问的资源类型(动|静)、是否含有cookie、请求头部中的方法为什么、怎么将请求转发至后端、服务器端响应的资源是否进行缓存等都是须要考虑的;这些配置都是要在.vcl文件中设定的;为了解决上面的多种问题,Varnish设计了一种相似netfilter的钩子函数的机制,在Varnish中称之为状态引擎;
    Varnish(v3)接收请求后的流程:请求首先会被vcl_recv()这个状态引擎接收,而后判断这个请求是否为一个可缓存对象(好比PUT和POST方法就不可缓存),若是不是就将请求传到vcl_fetch()这个状态引擎中,到后端服务器取相应资源,而后再通过vcl_delive()r这个状态引擎构建响应报文,响应客户端;若是是可缓存对象,首先会交给vcl_hash()进行URL的hash计算,而后将hash后的结果与缓存中的key进行比较,若是有匹配的key则为命中(hit),而后通过vcl_hit()进行缓存处理,最后通过vcl_deliver()构建响应报文,响应给客户端,若是没有匹配成功则为未命中(miss),则会经过vcl_miss()作未命中处理,而后经过vcl_fetch()去后端服务器取资源,最后经过vcl_deliver()构建响应报文,响应给客户端;
        Note:从上面能够看出来,各状态引擎之间有相关性;前一个状态引擎(engine)若是能够有多种下游的状态引擎,则上游的状态引擎须要使用return()指明要转移至的下游状态引擎;
        处理上面提到的那几种状态引擎以外还有一些经常使用的:
            vcl_pass():若是请求头部的方法为PUT、POST或者带有cookie或者须要验证则就会使用此状态引擎;
            vcl_error():直接由Varnish在前端构成错误页面信息,告诉客户端有错误发生;
            vcl_pipe():当遇到本身没法理解的后端响应时,本身什么也不作,直接将请求传递给后端服务器;
 
    Varnish服务接收请求后的流程图(v4):
 html


 


 
图片来自varnish-book;
        vcl_recv():req.
        vcl_hash():req.
        vcl_hit():req.、obj.
        vcl_miss():req.、bereq.
        vcl_backend_fetch():req.、bereq.、beresp.
        vcl_deliver():resp.
    VCL语法:
        1.使用//、#、/*foo*/做为注释;
        2.每一个状态引擎均可以当作是varnish的子例程,能够经过”sub”关键字进行定义;
        3.不支持循环;支持不少内置的状态变量;
        4.使用return(action)来选定其下游状态引擎;
        5.使用域做为配置段,好比 sub req_recv { };
        6.能够自定义设置;
        7.支持操做符:=、==、~、!、&&、||;
        8.使用if做条件判断,能够嵌套;
            if  (CONDTION) {
            
            } else {
            
            }
        9.经过”set”来设定变量值;
            set name=value
        10.经过”unset”来撤销设定的变量值;
            unset name
        11.VCL变量
            client
                client.ip:客户端的IP地址;
            server
                server.ip:接收客户端链接的IP地址;
                server.hostname:服务器的主机名;
            req
                req.http.*:调用request报文中http协议的指定的HEADER首部;
                    req.http.X-Forwarded-For
                req.method | req.request:指定请求方法;
                req.url:请求的URL
                req.proto:客户端使用的HTTP协议版本,一般为“HTTP / 1.1”或“HTTP / 2.0”;
                req.ttl:查找高速缓存返回响应的最大时间限制;
            resp
                resp.proto:用于响应的HTTP协议版本;
                resp.status:用于响应的HTTP状态码;
                resp.http.*:响应报文中的HTTP头部信息;
            bereq
                bereq.method:请求方法
                bereq.url:请求的URL,从req.url复制而来
                bereq.http.*:由Varnish发日后端主机的请求报文中的http协议的指定HEADER首部;
                bereq.backend:后端主机;
                bereq.backend:指明使用的后端主机;
            beresp
                beresp.status:后端主机响应的状态码信息;
                beresp.reason:后端主机返回的HTTP状态消息(缘由短语);
                beresp.http.*:调用后端主机返回的http报文中指定的HEADER首部;
                brresp.ttl:后端服务器响应的内容的余下的生存时长;
            obj
                obj.proto:存储在对象中的HTTP协议版本;
                obj.status:存储在对象中的HTTP状态码;
                obj.reason:存储在对象中的HTTP缘由短语;
                obj.http.*:存储在对象中HTTP标头;
                obj.hits:从缓存中命中次数;
                obj.ttl:存储在对象中的ttl值;
            storage
                storage.<name>.free_space:查看缓存空间空闲的大小;
                storage.<name>.used_space:查看缓存空间已使用的大小;前端

Type: BYTES
        变量详解:https://varnish-cache.org/docs/6.2/reference/vcl.html#local-server-remote-and-client
 
 
 
    支持虚拟主机:
        sub vcl_recv {
            if  (req.http.host == www.guowei.com) {
                set bereq.http.host = “www.GW.com”;
            }
        }
    强制对某资源的请求不检查缓存:
        sub vcl_recv {
            if  (req.url ~ “\.jpg$” || req.url ~ “(?i)\.png$”) {
                return(pass);
            }
        }
        只要是.jpg或者.png结尾的请求都不查找缓存,而且不区分大小写“(?i)”;
    对特定类型的资源取消其私有的cookie标识:
        sub vcl_backend_response {
            if  (beresp.http.cache-control !~ “s-maxage”) {
                if  (bereq.url ~ “(?i)\.jpg$”) {
                    set beresp.ttl = 600s;
                    unset beresp.http.Set.-Cookie;
                }
                if  (bereq.url ~ “(?i).\css$”) {
                    set beresp.ttl = 300s;
                    unset beresp.http.Set-Cookie;
                }
            }
    实现负载均衡:
        须要在配置文件中添加:import directors;
 web


    backend name { }:设置后端服务器属性;
 算法


        例子:
            vcl 4.0;
            import directors;
            # Default backend definition. Set this to point to your content server.
            backend clone1 {
                .host = "192.168.80.131";
                .port = "80";
            }
            backend clone2 {
                .host = "192.168.80.134";
                .port = "80";
            }
            sub vcl_init {
                new web = directors.round_robin();
                web.add_backend(clone1);
                web.add_backend(clone2);
            }
            sub vcl_recv {
                   if (req.url ~ "/test3.html$") {
                       return(pass);
                } else {
                    set req.backend_hint = web.backend();
                }
            }
    后端主机的健康状态检测方式:
 express

        .url:断定后端主机健康与否要请求的url;
        .expected_response:指望的响应状态码,默认为200;
        例子:
            backend clone1 {
                .host = "192.168.80.131";
                .port = "80";
                .probe = {
                    .url = "/test1.html";
                }
            }
            backend clone2 {
                .host = "192.168.80.134";
                .port = "80";
                .probe = {
                    .url = "/test1.html";
                }
            }
    动静分离:
        backend clone1 {
            .host = "192.168.80.131";
            .port = "80";
            .probe = {
                .url = "/test1.html";
            }
        }
        backend clone2 {
            .host = "192.168.80.134";
            .port = "80";
            .probe = {
                .url = "/test1.html";
            }
        }
        sub vcl_recv {
            if (req.url ~ "/test4.html$") {
                set req.backend_hint = clone1;
            } else {
                set req.backend_hint = clone2;
            }
        }编程

 
             注:根据马哥视频作的学习笔记,若有错误,欢迎指正;侵删;vim

相关文章
相关标签/搜索